forked from gitea/gitea
		
	feat(API): add route and implementation for creating/updating repository secret (#26766)
spec: https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#create-or-update-a-repository-secret - Add a new route for creating or updating a secret value in a repository - Create a new file `routers/api/v1/repo/action.go` with the implementation of the `CreateOrUpdateSecret` function - Update the Swagger documentation for the `updateRepoSecret` operation in the `v1_json.tmpl` template file --------- Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
		
							parent
							
								
									2d9249b6d9
								
							
						
					
					
						commit
						b91057b172
					
				| @ -160,3 +160,31 @@ func DeleteSecret(ctx context.Context, orgID, repoID int64, name string) error { | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CreateOrUpdateSecret creates or updates a secret and returns true if it was created | ||||
| func CreateOrUpdateSecret(ctx context.Context, orgID, repoID int64, name, data string) (bool, error) { | ||||
| 	sc := new(Secret) | ||||
| 	name = strings.ToUpper(name) | ||||
| 	has, err := db.GetEngine(ctx). | ||||
| 		Where("owner_id=?", orgID). | ||||
| 		And("repo_id=?", repoID). | ||||
| 		And("name=?", name). | ||||
| 		Get(sc) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	if !has { | ||||
| 		_, err = InsertEncryptedSecret(ctx, orgID, repoID, name, data) | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		return true, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if err := UpdateSecret(ctx, orgID, repoID, name, data); err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 
 | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| @ -933,6 +933,10 @@ func Routes() *web.Route { | ||||
| 					m.Post("/accept", repo.AcceptTransfer) | ||||
| 					m.Post("/reject", repo.RejectTransfer) | ||||
| 				}, reqToken()) | ||||
| 				m.Group("/actions/secrets", func() { | ||||
| 					m.Combo("/{secretname}"). | ||||
| 						Put(reqToken(), reqOwner(), bind(api.CreateOrUpdateSecretOption{}), repo.CreateOrUpdateSecret) | ||||
| 				}) | ||||
| 				m.Group("/hooks/git", func() { | ||||
| 					m.Combo("").Get(repo.ListGitHooks) | ||||
| 					m.Group("/{id}", func() { | ||||
| @ -1301,7 +1305,7 @@ func Routes() *web.Route { | ||||
| 			m.Group("/actions/secrets", func() { | ||||
| 				m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets) | ||||
| 				m.Combo("/{secretname}"). | ||||
| 					Put(reqToken(), reqOrgOwnership(), bind(api.CreateOrUpdateSecretOption{}), org.CreateOrUpdateOrgSecret). | ||||
| 					Put(reqToken(), reqOrgOwnership(), bind(api.CreateOrUpdateSecretOption{}), org.CreateOrUpdateSecret). | ||||
| 					Delete(reqToken(), reqOrgOwnership(), org.DeleteOrgSecret) | ||||
| 			}) | ||||
| 			m.Group("/public_members", func() { | ||||
|  | ||||
| @ -74,7 +74,7 @@ func listActionsSecrets(ctx *context.APIContext) { | ||||
| } | ||||
| 
 | ||||
| // create or update one secret of the organization | ||||
| func CreateOrUpdateOrgSecret(ctx *context.APIContext) { | ||||
| func CreateOrUpdateSecret(ctx *context.APIContext) { | ||||
| 	// swagger:operation PUT /orgs/{org}/actions/secrets/{secretname} organization updateOrgSecret | ||||
| 	// --- | ||||
| 	// summary: Create or Update a secret value in an organization | ||||
| @ -108,26 +108,17 @@ func CreateOrUpdateOrgSecret(ctx *context.APIContext) { | ||||
| 	//     "$ref": "#/responses/forbidden" | ||||
| 	secretName := ctx.Params(":secretname") | ||||
| 	if err := actions.NameRegexMatch(secretName); err != nil { | ||||
| 		ctx.Error(http.StatusBadRequest, "CreateOrUpdateOrgSecret", err) | ||||
| 		ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err) | ||||
| 		return | ||||
| 	} | ||||
| 	opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption) | ||||
| 	err := secret_model.UpdateSecret( | ||||
| 		ctx, ctx.Org.Organization.ID, 0, secretName, opt.Data, | ||||
| 	) | ||||
| 	if secret_model.IsErrSecretNotFound(err) { | ||||
| 		_, err := secret_model.InsertEncryptedSecret( | ||||
| 			ctx, ctx.Org.Organization.ID, 0, secretName, actions.ReserveLineBreakForTextarea(opt.Data), | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			ctx.Error(http.StatusInternalServerError, "InsertEncryptedSecret", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Status(http.StatusCreated) | ||||
| 	isCreated, err := secret_model.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, secretName, opt.Data) | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "UpdateSecret", err) | ||||
| 	if isCreated { | ||||
| 		ctx.Status(http.StatusCreated) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										75
									
								
								routers/api/v1/repo/action.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								routers/api/v1/repo/action.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
| 
 | ||||
| package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	secret_model "code.gitea.io/gitea/models/secret" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	api "code.gitea.io/gitea/modules/structs" | ||||
| 	"code.gitea.io/gitea/modules/web" | ||||
| 	"code.gitea.io/gitea/routers/web/shared/actions" | ||||
| ) | ||||
| 
 | ||||
| // create or update one secret of the repository | ||||
| func CreateOrUpdateSecret(ctx *context.APIContext) { | ||||
| 	// swagger:operation PUT /repos/{owner}/{repo}/actions/secrets/{secretname} repository updateRepoSecret | ||||
| 	// --- | ||||
| 	// summary: Create or Update a secret value 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 | ||||
| 	// - name: body | ||||
| 	//   in: body | ||||
| 	//   schema: | ||||
| 	//     "$ref": "#/definitions/CreateOrUpdateSecretOption" | ||||
| 	// responses: | ||||
| 	//   "201": | ||||
| 	//     description: response when creating a secret | ||||
| 	//   "204": | ||||
| 	//     description: response when updating a secret | ||||
| 	//   "400": | ||||
| 	//     "$ref": "#/responses/error" | ||||
| 	//   "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, "CreateOrUpdateSecret", err) | ||||
| 		return | ||||
| 	} | ||||
| 	opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption) | ||||
| 	isCreated, err := secret_model.CreateOrUpdateSecret(ctx, owner.ID, repo.ID, secretName, opt.Data) | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if isCreated { | ||||
| 		ctx.Status(http.StatusCreated) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Status(http.StatusNoContent) | ||||
| } | ||||
							
								
								
									
										59
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										59
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							| @ -3230,6 +3230,65 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/repos/{owner}/{repo}/actions/secrets/{secretname}": { | ||||
|       "put": { | ||||
|         "consumes": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "produces": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "repository" | ||||
|         ], | ||||
|         "summary": "Create or Update a secret value in a repository", | ||||
|         "operationId": "updateRepoSecret", | ||||
|         "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 | ||||
|           }, | ||||
|           { | ||||
|             "name": "body", | ||||
|             "in": "body", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/CreateOrUpdateSecretOption" | ||||
|             } | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "201": { | ||||
|             "description": "response when creating a secret" | ||||
|           }, | ||||
|           "204": { | ||||
|             "description": "response when updating a secret" | ||||
|           }, | ||||
|           "400": { | ||||
|             "$ref": "#/responses/error" | ||||
|           }, | ||||
|           "403": { | ||||
|             "$ref": "#/responses/forbidden" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/repos/{owner}/{repo}/activities/feeds": { | ||||
|       "get": { | ||||
|         "produces": [ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 GitHub
							GitHub