From a1ac8922a0b7182d0882f9bdf8f7d6e3af709243 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 11:46:48 +0800 Subject: [PATCH 01/12] feat: add new functions and files related to secrets management - Add a new function `CountOrgSecrets` in the file `models/secret/secret.go` - Add a new file `modules/structs/secret.go` - Add a new function `ListActionsSecrets` in the file `routers/api/v1/api.go` - Add a new file `routers/api/v1/org/action.go` - Add a new function `listActionsSecrets` in the file `routers/api/v1/org/action.go` Signed-off-by: Bo-Yi Wu --- models/secret/secret.go | 6 +++ modules/structs/secret.go | 15 +++++++ routers/api/v1/api.go | 3 ++ routers/api/v1/org/action.go | 83 ++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 modules/structs/secret.go create mode 100644 routers/api/v1/org/action.go diff --git a/models/secret/secret.go b/models/secret/secret.go index 5a17cc37a5dc0..a1974c59b1d1d 100644 --- a/models/secret/secret.go +++ b/models/secret/secret.go @@ -88,3 +88,9 @@ func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error Where(opts.toConds()). Find(&secrets) } + +// CountOrgSecrets counts the organization's secrets +func CountOrgSecrets(opts *FindSecretsOptions) (int64, error) { + sess := db.GetEngine(db.DefaultContext).Where("owner_id=?", opts.OwnerID) + return sess.Count(new(Secret)) +} diff --git a/modules/structs/secret.go b/modules/structs/secret.go new file mode 100644 index 0000000000000..cd20e93bd22ce --- /dev/null +++ b/modules/structs/secret.go @@ -0,0 +1,15 @@ +// Copyright 2023 The Gogs Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package structs + +import "time" + +// User represents a secret +// swagger:model +type Secret struct { + // the secret's name + Name string `json:"name"` + // swagger:strfmt date-time + Created time.Time `json:"created,omitempty"` +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 397eb105582b0..2d635f273c756 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1298,6 +1298,9 @@ func Routes() *web.Route { m.Combo("/{username}").Get(reqToken(), org.IsMember). Delete(reqToken(), reqOrgOwnership(), org.DeleteMember) }) + m.Group("/actions/secrets", func() { + m.Get("", reqToken(), org.ListActionsSecrets) + }) m.Group("/public_members", func() { m.Get("", org.ListPublicMembers) m.Combo("/{username}").Get(org.IsPublicMember). diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go new file mode 100644 index 0000000000000..b7b9ea23d45bd --- /dev/null +++ b/routers/api/v1/org/action.go @@ -0,0 +1,83 @@ +// Copyright 2023 The Gogs Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "net/http" + + "code.gitea.io/gitea/models/secret" + "code.gitea.io/gitea/modules/context" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/utils" +) + +// ListActionsSecrets list an organization's actions secrets +func ListActionsSecrets(ctx *context.APIContext) { + // swagger:operation GET /orgs/{org}/actions/secrets organization orgListActionsSecrets + // --- + // summary: List an organization's actions secrets + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/SecretList" + + if ctx.Doer != nil { + isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID) + if err != nil { + ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) + return + } + if !isMember && !ctx.Doer.IsAdmin { + ctx.Error(http.StatusUnauthorized, "IsOrgMember", nil) + return + } + } + listActionsSecrets(ctx) +} + +// listActionsSecrets list an organization's actions secrets +func listActionsSecrets(ctx *context.APIContext) { + opts := &secret.FindSecretsOptions{ + OwnerID: ctx.Org.Organization.ID, + ListOptions: utils.GetListOptions(ctx), + } + + count, err := secret.CountOrgSecrets(opts) + if err != nil { + ctx.InternalServerError(err) + return + } + + secrets, err := secret.FindSecrets(ctx, *opts) + if err != nil { + ctx.InternalServerError(err) + return + } + + apiSecrets := make([]*api.Secret, len(secrets)) + for k, v := range secrets { + apiSecrets[k] = &api.Secret{ + Name: v.Name, + Created: v.CreatedUnix.AsTime(), + } + } + + ctx.SetTotalCountHeader(count) + ctx.JSON(http.StatusOK, apiSecrets) +} From 3fd82012ae8acb010bb5175a06aa920ccf29fd46 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:09:56 +0800 Subject: [PATCH 02/12] feat: add API endpoint for listing organization's actions secrets - Add a new API endpoint for listing an organization's actions secrets Signed-off-by: Bo-Yi Wu --- routers/api/v1/org/action.go | 2 +- templates/swagger/v1_json.tmpl | 40 +++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index b7b9ea23d45bd..4d3e6910f1369 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -16,7 +16,7 @@ import ( func ListActionsSecrets(ctx *context.APIContext) { // swagger:operation GET /orgs/{org}/actions/secrets organization orgListActionsSecrets // --- - // summary: List an organization's actions secrets + // summary: List an organization's actions secrets // produces: // - application/json // parameters: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8cf5332bafc48..99de17d92c341 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1550,6 +1550,44 @@ } } }, + "/orgs/{org}/actions/secrets": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "List an organization's actions secrets", + "operationId": "orgListActionsSecrets", + "parameters": [ + { + "type": "string", + "description": "name of the organization", + "name": "org", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/SecretList" + } + } + } + }, "/orgs/{org}/activities/feeds": { "get": { "produces": [ @@ -23140,4 +23178,4 @@ "TOTPHeader": [] } ] -} +} \ No newline at end of file From ae362b595d8c84ba8f9e283229c1a23dc85dfe24 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:10:37 +0800 Subject: [PATCH 03/12] Update models/secret/secret.go Co-authored-by: Lunny Xiao --- models/secret/secret.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/models/secret/secret.go b/models/secret/secret.go index a1974c59b1d1d..463bf6aef7686 100644 --- a/models/secret/secret.go +++ b/models/secret/secret.go @@ -89,8 +89,7 @@ func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error Find(&secrets) } -// CountOrgSecrets counts the organization's secrets -func CountOrgSecrets(opts *FindSecretsOptions) (int64, error) { - sess := db.GetEngine(db.DefaultContext).Where("owner_id=?", opts.OwnerID) - return sess.Count(new(Secret)) +// CountSecrets counts the organization's secrets +func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) { + return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret)) } From 8a502a2fecfe80c8b8b27af84e83807128d08712 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:10:44 +0800 Subject: [PATCH 04/12] Update modules/structs/secret.go Co-authored-by: techknowlogick --- modules/structs/secret.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/structs/secret.go b/modules/structs/secret.go index cd20e93bd22ce..f2bd144cf9e44 100644 --- a/modules/structs/secret.go +++ b/modules/structs/secret.go @@ -1,4 +1,4 @@ -// Copyright 2023 The Gogs Authors. All rights reserved. +// Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package structs From b54742df929a296d647c42c8615833b3e87c9ee4 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:10:50 +0800 Subject: [PATCH 05/12] Update routers/api/v1/org/action.go Co-authored-by: techknowlogick --- routers/api/v1/org/action.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index 4d3e6910f1369..c7184b0faafd2 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -1,4 +1,4 @@ -// Copyright 2023 The Gogs Authors. All rights reserved. +// Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package org From 9f48dfc3aca69d4f352976afaf54c6b83c36c5ad Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:17:11 +0800 Subject: [PATCH 06/12] feat: add support for Swagger secret list in API v1 - Add a new file `routers/api/v1/swagger/action.go` - Add a new struct `swaggerResponseSecretList` in the `action.go` file - Add a new file `templates/swagger/v1_json.tmpl` - Modify the `v1_json.tmpl` file to include a new property `Secret` in the `properties` section of the `User` object - Modify the `v1_json.tmpl` file to include a new definition `SecretList` in the `definitions` section Signed-off-by: Bo-Yi Wu --- routers/api/v1/swagger/action.go | 13 +++++++++++++ templates/swagger/v1_json.tmpl | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 routers/api/v1/swagger/action.go diff --git a/routers/api/v1/swagger/action.go b/routers/api/v1/swagger/action.go new file mode 100644 index 0000000000000..493b167f725a1 --- /dev/null +++ b/routers/api/v1/swagger/action.go @@ -0,0 +1,13 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package swagger + +import api "code.gitea.io/gitea/modules/structs" + +// SecretList +// swagger:response SecretList +type swaggerResponseSecretList struct { + // in:body + Body []api.Secret `json:"body"` +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 99de17d92c341..56b9d3a3d325e 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -21314,6 +21314,23 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "Secret": { + "description": "User represents a secret", + "type": "object", + "properties": { + "created": { + "type": "string", + "format": "date-time", + "x-go-name": "Created" + }, + "name": { + "description": "the secret's name", + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "ServerVersion": { "description": "ServerVersion wraps the version of the server", "type": "object", @@ -22885,6 +22902,15 @@ "$ref": "#/definitions/SearchResults" } }, + "SecretList": { + "description": "SecretList", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Secret" + } + } + }, "ServerVersion": { "description": "ServerVersion", "schema": { From e6c2a01539f0f5d4ef86ddacb61a24c07239c4b7 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:25:13 +0800 Subject: [PATCH 07/12] refactor: consolidate function names for counting secrets - Change the function name from `FindSecrets` to `CountSecrets` in `models/secret/secret.go` - Change the function name from `CountOrgSecrets` to `CountSecrets` in `routers/api/v1/org/action.go` Signed-off-by: Bo-Yi Wu --- models/secret/secret.go | 2 +- routers/api/v1/org/action.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/models/secret/secret.go b/models/secret/secret.go index 463bf6aef7686..c9c95e82d3024 100644 --- a/models/secret/secret.go +++ b/models/secret/secret.go @@ -89,7 +89,7 @@ func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error Find(&secrets) } -// CountSecrets counts the organization's secrets +// CountSecrets counts the secrets func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) { return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret)) } diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index c7184b0faafd2..c47825ca10655 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -58,7 +58,7 @@ func listActionsSecrets(ctx *context.APIContext) { ListOptions: utils.GetListOptions(ctx), } - count, err := secret.CountOrgSecrets(opts) + count, err := secret.CountSecrets(ctx, opts) if err != nil { ctx.InternalServerError(err) return From ab59235adb37bc94b32994a371000b1dff3655d2 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 13:31:10 +0800 Subject: [PATCH 08/12] backup Signed-off-by: Bo-Yi Wu --- templates/swagger/v1_json.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 56b9d3a3d325e..da5f62340b9fc 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -23204,4 +23204,4 @@ "TOTPHeader": [] } ] -} \ No newline at end of file +} From 5dc1f25d214c214f929866d3850c66f527604e83 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 14:28:08 +0800 Subject: [PATCH 09/12] Update routers/api/v1/api.go Co-authored-by: Lunny Xiao --- routers/api/v1/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 2d635f273c756..ccae83a940b07 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1299,7 +1299,7 @@ func Routes() *web.Route { Delete(reqToken(), reqOrgOwnership(), org.DeleteMember) }) m.Group("/actions/secrets", func() { - m.Get("", reqToken(), org.ListActionsSecrets) + m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets) }) m.Group("/public_members", func() { m.Get("", org.ListPublicMembers) From ff80b03d2a9847e4260ad351d248b6eeb6f7a59c Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 20:59:36 +0800 Subject: [PATCH 10/12] refactor: refactor `Secret` struct field name to `created_at` - Rename the `Created` field to `created_at` in the `Secret` struct Signed-off-by: Bo-Yi Wu --- modules/structs/secret.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/structs/secret.go b/modules/structs/secret.go index f2bd144cf9e44..6a41db4cd2f58 100644 --- a/modules/structs/secret.go +++ b/modules/structs/secret.go @@ -11,5 +11,5 @@ type Secret struct { // the secret's name Name string `json:"name"` // swagger:strfmt date-time - Created time.Time `json:"created,omitempty"` + Created time.Time `json:"created_at"` } From d72bcee72170c0822feb0141b8c1c8f2ccac9563 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 14 Aug 2023 21:31:01 +0800 Subject: [PATCH 11/12] refactor: refactor property name in User object - Change the property name from "created" to "created_at" in the User object Signed-off-by: Bo-Yi Wu --- templates/swagger/v1_json.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 3bfac9b796d49..da43c530af1f5 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -21333,7 +21333,7 @@ "description": "User represents a secret", "type": "object", "properties": { - "created": { + "created_at": { "type": "string", "format": "date-time", "x-go-name": "Created" From 26beefdabd92509d8187a6e7b37d5a5676f805d6 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Tue, 15 Aug 2023 10:10:19 +0800 Subject: [PATCH 12/12] refactor: refactor code for checking organization membership and admin status - Remove unnecessary code for checking organization membership and admin status in `ListActionsSecrets` function Signed-off-by: Bo-Yi Wu --- routers/api/v1/org/action.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index c47825ca10655..9deda2209c207 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -37,17 +37,6 @@ func ListActionsSecrets(ctx *context.APIContext) { // "200": // "$ref": "#/responses/SecretList" - if ctx.Doer != nil { - isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID) - if err != nil { - ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) - return - } - if !isMember && !ctx.Doer.IsAdmin { - ctx.Error(http.StatusUnauthorized, "IsOrgMember", nil) - return - } - } listActionsSecrets(ctx) }