新增:secret和variable查询
This commit is contained in:
parent
5059a43874
commit
ee5d35490f
2
main.go
2
main.go
|
|
@ -22,7 +22,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
Version = "v2.8.6, by v1.21.0, 20251111 "
|
||||
Version = "v2.8.7, by v1.21.0, 20251201 "
|
||||
Tags = ""
|
||||
MakeVersion = ""
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type FindSecretsOptions struct {
|
||||
db.ListOptions
|
||||
OwnerID int64
|
||||
RepoID int64
|
||||
SecretID int64
|
||||
Name string
|
||||
}
|
||||
|
||||
func (opts *FindSecretsOptions) toConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.OwnerID > 0 {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
}
|
||||
if opts.RepoID > 0 {
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
}
|
||||
if opts.SecretID != 0 {
|
||||
cond = cond.And(builder.Eq{"id": opts.SecretID})
|
||||
}
|
||||
if opts.Name != "" {
|
||||
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
|
||||
}
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*secret_model.Secret, error) {
|
||||
var secrets []*secret_model.Secret
|
||||
sess := db.GetEngine(ctx)
|
||||
if opts.PageSize != 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts.ListOptions)
|
||||
}
|
||||
return secrets, sess.
|
||||
Where(opts.toConds()).
|
||||
OrderBy("created_unix desc").
|
||||
Find(&secrets)
|
||||
}
|
||||
|
||||
func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) {
|
||||
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(secret_model.Secret))
|
||||
}
|
||||
|
||||
func DeleteSecret(ctx context.Context, secret *secret_model.Secret) error {
|
||||
if _, err := db.DeleteByID(ctx, secret.ID, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
gitea_actions "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type FindVariablesOpts struct {
|
||||
db.ListOptions
|
||||
IDs []int64
|
||||
RepoID int64
|
||||
OwnerID int64 // it will be ignored if RepoID is set
|
||||
Name string
|
||||
}
|
||||
|
||||
func (opts FindVariablesOpts) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if len(opts.IDs) > 0 {
|
||||
if len(opts.IDs) == 1 {
|
||||
cond = cond.And(builder.Eq{"id": opts.IDs[0]})
|
||||
} else {
|
||||
cond = cond.And(builder.In("id", opts.IDs))
|
||||
}
|
||||
}
|
||||
|
||||
// Since we now support instance-level variables,
|
||||
// there is no need to check for null values for `owner_id` and `repo_id`
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
if opts.RepoID != 0 { // if RepoID is set
|
||||
// ignore OwnerID and treat it as 0
|
||||
cond = cond.And(builder.Eq{"owner_id": 0})
|
||||
} else {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
}
|
||||
|
||||
if opts.Name != "" {
|
||||
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*gitea_actions.ActionVariable, error) {
|
||||
var variables []*gitea_actions.ActionVariable
|
||||
sess := db.GetEngine(ctx)
|
||||
if opts.PageSize != 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts.ListOptions)
|
||||
}
|
||||
return variables, sess.Where(opts.ToConds()).OrderBy("created_unix desc").Find(&variables)
|
||||
}
|
||||
|
||||
func CountVariables(ctx context.Context, opts FindVariablesOpts) (int64, error) {
|
||||
sess := db.GetEngine(ctx)
|
||||
return sess.Where(opts.ToConds()).Count(new(gitea_actions.ActionVariable))
|
||||
}
|
||||
|
||||
func DeleteVariable(ctx context.Context, variable *gitea_actions.ActionVariable) error {
|
||||
if _, err := db.DeleteByID(ctx, variable.ID, variable); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package structs
|
||||
|
||||
import "time"
|
||||
|
||||
// CreateVariableOption the option when creating variable
|
||||
// swagger:model
|
||||
type CreateSecretOption struct {
|
||||
// Value of the variable to create
|
||||
//
|
||||
// required: true
|
||||
Data string `json:"data" binding:"Required"`
|
||||
}
|
||||
|
||||
// UpdateVariableOption the option when updating variable
|
||||
// swagger:model
|
||||
type UpdateSecretOption struct {
|
||||
// New name for the variable. If the field is empty, the variable name won't be updated.
|
||||
Name string `json:"name"`
|
||||
// Value of the variable to update
|
||||
//
|
||||
// required: true
|
||||
Data string `json:"data" binding:"Required"`
|
||||
|
||||
// Description of the variable to update
|
||||
}
|
||||
|
||||
// Secret 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_at"`
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package structs
|
||||
|
||||
// CreateVariableOption the option when creating variable
|
||||
// swagger:model
|
||||
type CreateVariableOption struct {
|
||||
// Value of the variable to create
|
||||
//
|
||||
// required: true
|
||||
Value string `json:"value" binding:"Required"`
|
||||
}
|
||||
|
||||
// UpdateVariableOption the option when updating variable
|
||||
// swagger:model
|
||||
type UpdateVariableOption struct {
|
||||
// New name for the variable. If the field is empty, the variable name won't be updated.
|
||||
Name string `json:"name"`
|
||||
// Value of the variable to update
|
||||
//
|
||||
// required: true
|
||||
Value string `json:"value" binding:"Required"`
|
||||
|
||||
// Description of the variable to update
|
||||
}
|
||||
|
||||
// ActionVariable return value of the query API
|
||||
// swagger:model
|
||||
type ActionVariable struct {
|
||||
// the owner to which the variable belongs
|
||||
OwnerID int64 `json:"owner_id"`
|
||||
// the repository to which the variable belongs
|
||||
RepoID int64 `json:"repo_id"`
|
||||
// the name of the variable
|
||||
Name string `json:"name"`
|
||||
// the value of the variable
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package util
|
||||
|
||||
import "strings"
|
||||
|
||||
func ReserveLineBreakForTextarea(input string) string {
|
||||
// Since the content is from a form which is a textarea, the line endings are \r\n.
|
||||
// It's a standard behavior of HTML.
|
||||
// But we want to store them as \n like what GitHub does.
|
||||
// And users are unlikely to really need to keep the \r.
|
||||
// Other than this, we should respect the original content, even leading or trailing spaces.
|
||||
return strings.ReplaceAll(input, "\r\n", "\n")
|
||||
}
|
||||
|
|
@ -133,7 +133,21 @@ func Routers() *web.Route {
|
|||
m.Get("/code", context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode), repo.Code)
|
||||
m.Combo("").Delete(reqToken(), reqOwner(), repo.Delete)
|
||||
m.Group("/actions", func() {
|
||||
m.Get("/secrets", context.ReferencesGitRepo(), actions.ListActionsSecrets)
|
||||
m.Group("/secrets", func() {
|
||||
m.Get("", reqToken(), reqAdmin(), actions.ListActionsSecrets)
|
||||
m.Combo("/{secretname}").
|
||||
Delete(reqToken(), reqAdmin(), actions.DeleteActionsSecret).
|
||||
Post(reqToken(), reqAdmin(), bind(hat_api.CreateSecretOption{}), actions.CreateActionsSecret).
|
||||
Put(reqToken(), reqAdmin(), bind(hat_api.UpdateSecretOption{}), actions.UpdateActionsSecret)
|
||||
})
|
||||
m.Group("/variables", func() {
|
||||
m.Get("", reqToken(), reqAdmin(), actions.ListVariables)
|
||||
m.Combo("/{variablename}").
|
||||
Get(reqToken(), reqAdmin(), actions.GetVariable).
|
||||
Delete(reqToken(), reqAdmin(), actions.DeleteVariable).
|
||||
Post(reqToken(), reqAdmin(), bind(hat_api.CreateVariableOption{}), actions.CreateVariable).
|
||||
Put(reqToken(), reqAdmin(), bind(hat_api.UpdateVariableOption{}), actions.UpdateVariable)
|
||||
})
|
||||
m.Get("", context.ReferencesGitRepo(), actions.ListActions)
|
||||
m.Post("/disable", reqAdmin(), actions.DisableWorkflowFile)
|
||||
m.Post("/enable", reqAdmin(), actions.EnableWorkflowFile)
|
||||
|
|
@ -253,6 +267,23 @@ func Routers() *web.Route {
|
|||
m.Post("/orgs", reqToken(), bind(gitea_api.CreateOrgOption{}), org.Create)
|
||||
m.Group("/orgs/{org}", func() {
|
||||
m.Combo("").Patch(reqToken(), reqOrgOwnership(), bind(hat_api.EditOrgOption{}), org.Edit)
|
||||
m.Group("/actions", func() {
|
||||
m.Group("/secrets", func() {
|
||||
m.Get("", reqToken(), reqAdmin(), org.ListActionsSecrets)
|
||||
m.Combo("/{secretname}").
|
||||
Delete(reqToken(), reqAdmin(), org.DeleteActionsSecret).
|
||||
Post(reqToken(), reqAdmin(), bind(hat_api.CreateSecretOption{}), org.CreateActionsSecret).
|
||||
Put(reqToken(), reqAdmin(), bind(hat_api.UpdateSecretOption{}), org.UpdateActionsSecret)
|
||||
})
|
||||
m.Group("/variables", func() {
|
||||
m.Get("", reqToken(), reqOrgOwnership(), org.ListVariables)
|
||||
m.Combo("/{variablename}").
|
||||
Get(reqToken(), reqOrgOwnership(), org.GetVariable).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.DeleteVariable).
|
||||
Post(reqToken(), reqOrgOwnership(), bind(hat_api.CreateVariableOption{}), org.CreateVariable).
|
||||
Put(reqToken(), reqOrgOwnership(), bind(hat_api.UpdateVariableOption{}), org.UpdateVariable)
|
||||
})
|
||||
})
|
||||
}, orgAssignment(true))
|
||||
|
||||
m.Group("/teams/{teamid}", func() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,261 @@
|
|||
package org
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
|
||||
hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions"
|
||||
hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs"
|
||||
hat_actions_service "code.gitlink.org.cn/Gitlink/gitea_hat.git/services/actions"
|
||||
)
|
||||
|
||||
func DeleteActionsSecret(ctx *context.APIContext) {
|
||||
if err := hat_actions_service.DeleteSecretByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname")); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteSecretByName", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func CreateActionsSecret(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.CreateSecretOption)
|
||||
ownerID := ctx.Org.Organization.ID
|
||||
secretName := ctx.Params("secretname")
|
||||
|
||||
v, err := hat_actions_service.GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
OwnerID: ownerID,
|
||||
Name: secretName,
|
||||
})
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
if v != nil && v.ID > 0 {
|
||||
ctx.Error(http.StatusConflict, "", util.NewAlreadyExistErrorf("secret name %s already exists", secretName))
|
||||
return
|
||||
}
|
||||
if _, err := hat_actions_service.CreateSecret(ctx, ownerID, 0, secretName, opt.Data); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func UpdateActionsSecret(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.UpdateSecretOption)
|
||||
|
||||
_, err := hat_actions_service.GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
Name: ctx.Params("secretname"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "GetSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if opt.Name == "" {
|
||||
opt.Name = ctx.Params("secretname")
|
||||
}
|
||||
|
||||
_, err = hat_actions_service.UpdateSecret(ctx, ctx.Org.Organization.ID, 0, opt.Name, opt.Data)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "UpdateSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
|
||||
}
|
||||
|
||||
func ListActionsSecrets(ctx *context.APIContext) {
|
||||
opts := &hat_actions_model.FindSecretsOptions{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
count, err := hat_actions_model.CountSecrets(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
secrets, err := hat_actions_model.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)
|
||||
}
|
||||
|
||||
func GetVariable(ctx *context.APIContext) {
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
Name: ctx.Params("variablename"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
variable := &hat_api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, variable)
|
||||
}
|
||||
|
||||
func DeleteVariable(ctx *context.APIContext) {
|
||||
if err := hat_actions_service.DeleteVariableByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("variablename")); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteVariableByName", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func CreateVariable(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.CreateVariableOption)
|
||||
ownerID := ctx.Org.Organization.ID
|
||||
variableName := ctx.Params("variablename")
|
||||
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
OwnerID: ownerID,
|
||||
Name: variableName,
|
||||
})
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
if v != nil && v.ID > 0 {
|
||||
ctx.Error(http.StatusConflict, "", util.NewAlreadyExistErrorf("variable name %s already exists", variableName))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := hat_actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateVariable", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func UpdateVariable(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.UpdateVariableOption)
|
||||
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
Name: ctx.Params("variablename"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "GetVariable", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if opt.Name == "" {
|
||||
opt.Name = ctx.Params("variablename")
|
||||
}
|
||||
|
||||
v.Name = opt.Name
|
||||
v.Data = opt.Value
|
||||
|
||||
if _, err := hat_actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "UpdateVariableNameData", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func ListVariables(ctx *context.APIContext) {
|
||||
opts := hat_actions_model.FindVariablesOpts{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
vars, err := hat_actions_model.FindVariables(ctx, opts)
|
||||
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := hat_actions_model.CountVariables(ctx, opts)
|
||||
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
variables := make([]*hat_api.ActionVariable, len(vars))
|
||||
for i, v := range vars {
|
||||
variables[i] = &hat_api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
}
|
||||
}
|
||||
|
||||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, variables)
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ import (
|
|||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
|
|
@ -32,24 +31,103 @@ import (
|
|||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions"
|
||||
hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs"
|
||||
hat_actions_service "code.gitlink.org.cn/Gitlink/gitea_hat.git/services/actions"
|
||||
jobparser "github.com/nektos/act/pkg/jobparser"
|
||||
"github.com/nektos/act/pkg/model"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
func DeleteActionsSecret(ctx *context.APIContext) {
|
||||
if err := hat_actions_service.DeleteSecretByName(ctx, 0, ctx.Repo.Repository.ID, ctx.Params("secretname")); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteSecretByName", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func CreateActionsSecret(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.CreateSecretOption)
|
||||
repoID := ctx.Repo.Repository.ID
|
||||
secretName := ctx.Params("secretname")
|
||||
|
||||
v, err := hat_actions_service.GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
RepoID: repoID,
|
||||
Name: secretName,
|
||||
})
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
if v != nil && v.ID > 0 {
|
||||
ctx.Error(http.StatusConflict, "", util.NewAlreadyExistErrorf("secret name %s already exists", secretName))
|
||||
return
|
||||
}
|
||||
if _, err := hat_actions_service.CreateSecret(ctx, 0, repoID, secretName, opt.Data); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func UpdateActionsSecret(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.UpdateSecretOption)
|
||||
|
||||
_, err := hat_actions_service.GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Name: ctx.Params("secretname"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "GetSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if opt.Name == "" {
|
||||
opt.Name = ctx.Params("secretname")
|
||||
}
|
||||
|
||||
_, err = hat_actions_service.UpdateSecret(ctx, 0, ctx.Repo.Repository.ID, opt.Name, opt.Data)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "UpdateSecret", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
|
||||
}
|
||||
|
||||
func ListActionsSecrets(ctx *context.APIContext) {
|
||||
opts := &secret_model.FindSecretsOptions{
|
||||
opts := &hat_actions_model.FindSecretsOptions{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
count, err := secret_model.CountSecrets(ctx, opts)
|
||||
count, err := hat_actions_model.CountSecrets(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
secrets, err := secret_model.FindSecrets(ctx, *opts)
|
||||
secrets, err := hat_actions_model.FindSecrets(ctx, *opts)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
|
|
@ -67,6 +145,143 @@ func ListActionsSecrets(ctx *context.APIContext) {
|
|||
ctx.JSON(http.StatusOK, apiSecrets)
|
||||
}
|
||||
|
||||
func GetVariable(ctx *context.APIContext) {
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Name: ctx.Params("variablename"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
variable := &hat_api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, variable)
|
||||
}
|
||||
|
||||
func DeleteVariable(ctx *context.APIContext) {
|
||||
if err := hat_actions_service.DeleteVariableByName(ctx, 0, ctx.Repo.Repository.ID, ctx.Params("variablename")); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteVariableByName", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.NotFound(err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func CreateVariable(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.CreateVariableOption)
|
||||
repoID := ctx.Repo.Repository.ID
|
||||
variableName := ctx.Params("variablename")
|
||||
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
RepoID: repoID,
|
||||
Name: variableName,
|
||||
})
|
||||
if err != nil && !errors.Is(err, util.ErrNotExist) {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
if v != nil && v.ID > 0 {
|
||||
ctx.Error(http.StatusConflict, "", util.NewAlreadyExistErrorf("variable name %s already exists", variableName))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := hat_actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateVariable", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func UpdateVariable(ctx *context.APIContext) {
|
||||
opt := web.GetForm(ctx).(*hat_api.UpdateVariableOption)
|
||||
|
||||
v, err := hat_actions_service.GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Name: ctx.Params("variablename"),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "GetVariable", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if opt.Name == "" {
|
||||
opt.Name = ctx.Params("variablename")
|
||||
}
|
||||
|
||||
v.Name = opt.Name
|
||||
v.Data = opt.Value
|
||||
|
||||
if _, err := hat_actions_service.UpdateVariableNameData(ctx, v); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "UpdateVariableNameData", err)
|
||||
} else {
|
||||
ctx.InternalServerError(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func ListVariables(ctx *context.APIContext) {
|
||||
opts := hat_actions_model.FindVariablesOpts{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
vars, err := hat_actions_model.FindVariables(ctx, opts)
|
||||
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := hat_actions_model.CountVariables(ctx, opts)
|
||||
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
variables := make([]*hat_api.ActionVariable, len(vars))
|
||||
for i, v := range vars {
|
||||
variables[i] = &hat_api.ActionVariable{
|
||||
OwnerID: v.OwnerID,
|
||||
RepoID: v.RepoID,
|
||||
Name: v.Name,
|
||||
Data: v.Data,
|
||||
}
|
||||
}
|
||||
|
||||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, variables)
|
||||
}
|
||||
|
||||
func Run(ctx *context.APIContext) {
|
||||
workflow := ctx.FormString("workflow")
|
||||
ref := ctx.FormString("ref")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
var globalVars = sync.OnceValue(func() (ret struct {
|
||||
namePattern, forbiddenPrefixPattern *regexp.Regexp
|
||||
},
|
||||
) {
|
||||
ret.namePattern = regexp.MustCompile("(?i)^[A-Z_][A-Z0-9_]*$")
|
||||
ret.forbiddenPrefixPattern = regexp.MustCompile("(?i)^GIT(EA|HUB)_")
|
||||
return ret
|
||||
})
|
||||
|
||||
func ValidateName(name string) error {
|
||||
vars := globalVars()
|
||||
if !vars.namePattern.MatchString(name) ||
|
||||
vars.forbiddenPrefixPattern.MatchString(name) ||
|
||||
strings.EqualFold(name, "CI") /* CI is always set to true in GitHub Actions*/ {
|
||||
return util.NewInvalidArgumentErrorf("invalid variable or secret name")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*secret_model.Secret, error) {
|
||||
if err := ValidateName(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, name, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func UpdateSecret(ctx context.Context, ownerID, repoID int64, name, data string) (bool, error) {
|
||||
if err := ValidateName(name); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
s, err := GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if s == nil {
|
||||
return false, util.NewNotExistErrorf("secret not found")
|
||||
}
|
||||
|
||||
err = secret_model.UpdateSecret(ctx, s.ID, data)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func GetSecret(ctx context.Context, opts hat_actions_model.FindSecretsOptions) (*secret_model.Secret, error) {
|
||||
vars, err := hat_actions_model.FindSecrets(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(vars) != 1 {
|
||||
return nil, util.NewNotExistErrorf("variable not found")
|
||||
}
|
||||
return vars[0], nil
|
||||
}
|
||||
|
||||
func DeleteSecretByName(ctx context.Context, ownerID, repoID int64, name string) error {
|
||||
s, err := GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hat_actions_model.DeleteSecret(ctx, s)
|
||||
}
|
||||
|
||||
func DeleteSecretByID(ctx context.Context, secretID int64) error {
|
||||
s, err := GetSecret(ctx, hat_actions_model.FindSecretsOptions{
|
||||
SecretID: secretID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return hat_actions_model.DeleteSecret(ctx, s)
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
secret_service "code.gitea.io/gitea/services/secrets"
|
||||
hat_actions_model "code.gitlink.org.cn/Gitlink/gitea_hat.git/models/actions"
|
||||
hat_util "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/util"
|
||||
)
|
||||
|
||||
func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*actions_model.ActionVariable, error) {
|
||||
if err := secret_service.ValidateName(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := actions_model.InsertVariable(ctx, ownerID, repoID, name, hat_util.ReserveLineBreakForTextarea(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func UpdateVariableNameData(ctx context.Context, variable *actions_model.ActionVariable) (bool, error) {
|
||||
if err := secret_service.ValidateName(variable.Name); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
variable.Data = hat_util.ReserveLineBreakForTextarea(variable.Data)
|
||||
|
||||
return actions_model.UpdateVariable(ctx, variable)
|
||||
}
|
||||
|
||||
func DeleteVariableByID(ctx context.Context, variableID int64) error {
|
||||
v, err := GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
IDs: []int64{variableID},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return hat_actions_model.DeleteVariable(ctx, v)
|
||||
}
|
||||
|
||||
func DeleteVariableByName(ctx context.Context, ownerID, repoID int64, name string) error {
|
||||
v, err := GetVariable(ctx, hat_actions_model.FindVariablesOpts{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hat_actions_model.DeleteVariable(ctx, v)
|
||||
}
|
||||
|
||||
func GetVariable(ctx context.Context, opts hat_actions_model.FindVariablesOpts) (*actions_model.ActionVariable, error) {
|
||||
vars, err := hat_actions_model.FindVariables(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(vars) != 1 {
|
||||
return nil, util.NewNotExistErrorf("variable not found")
|
||||
}
|
||||
return vars[0], nil
|
||||
}
|
||||
Loading…
Reference in New Issue