From 9eb4a9e601c16174306d81ec4d73ffa5a0adc788 Mon Sep 17 00:00:00 2001
From: Bo-Yi Wu <appleboy.tw@gmail.com>
Date: Fri, 1 Sep 2023 21:02:49 +0800
Subject: [PATCH] feat(API): add secret deletion functionality for repository
 (#26808)

- Modify the `CreateOrUpdateSecret` function in `api.go` to include a
`Delete` operation for the secret
- Modify the `DeleteOrgSecret` function in `action.go` to include a
`DeleteSecret` operation for the organization
- Modify the `DeleteSecret` function in `action.go` to include a
`DeleteSecret` operation for the repository
- Modify the `v1_json.tmpl` template file to update the `operationId`
and `summary` for the `deleteSecret` operation in both the organization
and repository sections

---------

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
---
 routers/api/v1/api.go          |  5 ++--
 routers/api/v1/org/action.go   |  8 +++--
 routers/api/v1/repo/action.go  | 54 ++++++++++++++++++++++++++++++++++
 templates/swagger/v1_json.tmpl | 44 +++++++++++++++++++++++++++
 4 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 32e5a10bb..15bf820a6 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -935,7 +935,8 @@ func Routes() *web.Route {
 				}, reqToken())
 				m.Group("/actions/secrets", func() {
 					m.Combo("/{secretname}").
-						Put(reqToken(), reqOwner(), bind(api.CreateOrUpdateSecretOption{}), repo.CreateOrUpdateSecret)
+						Put(reqToken(), reqOwner(), bind(api.CreateOrUpdateSecretOption{}), repo.CreateOrUpdateSecret).
+						Delete(reqToken(), reqOwner(), repo.DeleteSecret)
 				})
 				m.Group("/hooks/git", func() {
 					m.Combo("").Get(repo.ListGitHooks)
@@ -1306,7 +1307,7 @@ func Routes() *web.Route {
 				m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets)
 				m.Combo("/{secretname}").
 					Put(reqToken(), reqOrgOwnership(), bind(api.CreateOrUpdateSecretOption{}), org.CreateOrUpdateSecret).
-					Delete(reqToken(), reqOrgOwnership(), org.DeleteOrgSecret)
+					Delete(reqToken(), reqOrgOwnership(), org.DeleteSecret)
 			})
 			m.Group("/public_members", func() {
 				m.Get("", org.ListPublicMembers)
diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go
index 0bf741e82..a04058be1 100644
--- a/routers/api/v1/org/action.go
+++ b/routers/api/v1/org/action.go
@@ -125,8 +125,8 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
 	ctx.Status(http.StatusNoContent)
 }
 
-// DeleteOrgSecret delete one secret of the organization
-func DeleteOrgSecret(ctx *context.APIContext) {
+// DeleteSecret delete one secret of the organization
+func DeleteSecret(ctx *context.APIContext) {
 	// swagger:operation DELETE /orgs/{org}/actions/secrets/{secretname} organization deleteOrgSecret
 	// ---
 	// summary: Delete a secret in an organization
@@ -151,6 +151,10 @@ func DeleteOrgSecret(ctx *context.APIContext) {
 	//   "403":
 	//     "$ref": "#/responses/forbidden"
 	secretName := ctx.Params(":secretname")
+	if err := actions.NameRegexMatch(secretName); err != nil {
+		ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
+		return
+	}
 	err := secret_model.DeleteSecret(
 		ctx, ctx.Org.Organization.ID, 0, secretName,
 	)
diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go
index 015c731a7..b7642b6af 100644
--- a/routers/api/v1/repo/action.go
+++ b/routers/api/v1/repo/action.go
@@ -73,3 +73,57 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
 
 	ctx.Status(http.StatusNoContent)
 }
+
+// DeleteSecret delete one secret of the repository
+func DeleteSecret(ctx *context.APIContext) {
+	// swagger:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secretname} repository deleteRepoSecret
+	// ---
+	// summary: Delete a secret in a repository
+	// consumes:
+	// - application/json
+	// produces:
+	// - application/json
+	// parameters:
+	// - name: owner
+	//   in: path
+	//   description: owner of the repository
+	//   type: string
+	//   required: true
+	// - name: repo
+	//   in: path
+	//   description: name of the repository
+	//   type: string
+	//   required: true
+	// - name: secretname
+	//   in: path
+	//   description: name of the secret
+	//   type: string
+	//   required: true
+	// responses:
+	//   "204":
+	//     description: delete one secret of the organization
+	//   "403":
+	//     "$ref": "#/responses/forbidden"
+
+	owner := ctx.Repo.Owner
+	repo := ctx.Repo.Repository
+
+	secretName := ctx.Params(":secretname")
+	if err := actions.NameRegexMatch(secretName); err != nil {
+		ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
+		return
+	}
+	err := secret_model.DeleteSecret(
+		ctx, owner.ID, repo.ID, secretName,
+	)
+	if secret_model.IsErrSecretNotFound(err) {
+		ctx.NotFound(err)
+		return
+	}
+	if err != nil {
+		ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
+		return
+	}
+
+	ctx.Status(http.StatusNoContent)
+}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 78491de2e..699653d29 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -3287,6 +3287,50 @@
             "$ref": "#/responses/forbidden"
           }
         }
+      },
+      "delete": {
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "tags": [
+          "repository"
+        ],
+        "summary": "Delete a secret in a repository",
+        "operationId": "deleteRepoSecret",
+        "parameters": [
+          {
+            "type": "string",
+            "description": "owner of the repository",
+            "name": "owner",
+            "in": "path",
+            "required": true
+          },
+          {
+            "type": "string",
+            "description": "name of the repository",
+            "name": "repo",
+            "in": "path",
+            "required": true
+          },
+          {
+            "type": "string",
+            "description": "name of the secret",
+            "name": "secretname",
+            "in": "path",
+            "required": true
+          }
+        ],
+        "responses": {
+          "204": {
+            "description": "delete one secret of the organization"
+          },
+          "403": {
+            "$ref": "#/responses/forbidden"
+          }
+        }
       }
     },
     "/repos/{owner}/{repo}/activities/feeds": {