mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-22 01:44:24 +01:00
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…
Reference in a new issue