mirror of https://github.com/go-gitea/gitea
Compare commits
7 Commits
f4164216a9
...
702944ac32
Author | SHA1 | Date |
---|---|---|
silverwind | 702944ac32 | |
GiteaBot | 27861d711b | |
silverwind | c93eefb42b | |
Bo-Yi Wu | 852547d0dc | |
silverwind | 453c63ddc5 | |
silverwind | d0303ffd68 | |
silverwind | ff0c9a04a5 |
|
@ -321,7 +321,7 @@ rules:
|
|||
jquery/no-sizzle: [2]
|
||||
jquery/no-slide: [2]
|
||||
jquery/no-submit: [2]
|
||||
jquery/no-text: [0]
|
||||
jquery/no-text: [2]
|
||||
jquery/no-toggle: [2]
|
||||
jquery/no-trigger: [0]
|
||||
jquery/no-trim: [2]
|
||||
|
@ -474,7 +474,7 @@ rules:
|
|||
no-jquery/no-slide: [2]
|
||||
no-jquery/no-sub: [2]
|
||||
no-jquery/no-support: [2]
|
||||
no-jquery/no-text: [0]
|
||||
no-jquery/no-text: [2]
|
||||
no-jquery/no-trigger: [0]
|
||||
no-jquery/no-trim: [2]
|
||||
no-jquery/no-type: [2]
|
||||
|
|
|
@ -436,6 +436,7 @@ oauth_signin_submit=Vincular conta
|
|||
oauth.signin.error=Ocorreu um erro durante o processamento do pedido de autorização. Se este erro persistir, contacte o administrador.
|
||||
oauth.signin.error.access_denied=O pedido de autorização foi negado.
|
||||
oauth.signin.error.temporarily_unavailable=A autorização falhou porque o servidor de autenticação está temporariamente indisponĂvel. Tente mais tarde.
|
||||
oauth_callback_unable_auto_reg=O registo automático está habilitado, mas o fornecedor OAuth2 %[1]s sinalizou campos em falta: %[2]s, por isso nĂŁo foi possĂvel criar uma conta automaticamente. Crie ou vincule uma conta ou contacte o administrador do sĂtio.
|
||||
openid_connect_submit=Estabelecer ligação
|
||||
openid_connect_title=Estabelecer ligação a uma conta existente
|
||||
openid_connect_desc=O URI do OpenID escolhido Ă© desconhecido. Associe-o a uma nova conta aqui.
|
||||
|
|
|
@ -93,6 +93,7 @@ import (
|
|||
"code.gitea.io/gitea/routers/api/v1/settings"
|
||||
"code.gitea.io/gitea/routers/api/v1/user"
|
||||
"code.gitea.io/gitea/routers/common"
|
||||
"code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/services/auth"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
|
@ -835,6 +836,34 @@ func Routes() *web.Route {
|
|||
SignInRequired: setting.Service.RequireSignInView,
|
||||
}))
|
||||
|
||||
addActionsRoutes := func(
|
||||
m *web.Route,
|
||||
reqChecker func(ctx *context.APIContext),
|
||||
act actions.API,
|
||||
) {
|
||||
m.Group("/actions", func() {
|
||||
m.Group("/secrets", func() {
|
||||
m.Get("", reqToken(), reqChecker, act.ListActionsSecrets)
|
||||
m.Combo("/{secretname}").
|
||||
Put(reqToken(), reqChecker, bind(api.CreateOrUpdateSecretOption{}), act.CreateOrUpdateSecret).
|
||||
Delete(reqToken(), reqChecker, act.DeleteSecret)
|
||||
})
|
||||
|
||||
m.Group("/variables", func() {
|
||||
m.Get("", reqToken(), reqChecker, act.ListVariables)
|
||||
m.Combo("/{variablename}").
|
||||
Get(reqToken(), reqChecker, act.GetVariable).
|
||||
Delete(reqToken(), reqChecker, act.DeleteVariable).
|
||||
Post(reqToken(), reqChecker, bind(api.CreateVariableOption{}), act.CreateVariable).
|
||||
Put(reqToken(), reqChecker, bind(api.UpdateVariableOption{}), act.UpdateVariable)
|
||||
})
|
||||
|
||||
m.Group("/runners", func() {
|
||||
m.Get("/registration-token", reqToken(), reqChecker, act.GetRegistrationToken)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
m.Group("", func() {
|
||||
// Miscellaneous (no scope required)
|
||||
if setting.API.EnableSwagger {
|
||||
|
@ -1073,26 +1102,11 @@ func Routes() *web.Route {
|
|||
m.Post("/accept", repo.AcceptTransfer)
|
||||
m.Post("/reject", repo.RejectTransfer)
|
||||
}, reqToken())
|
||||
m.Group("/actions", func() {
|
||||
m.Group("/secrets", func() {
|
||||
m.Combo("/{secretname}").
|
||||
Put(reqToken(), reqOwner(), bind(api.CreateOrUpdateSecretOption{}), repo.CreateOrUpdateSecret).
|
||||
Delete(reqToken(), reqOwner(), repo.DeleteSecret)
|
||||
})
|
||||
|
||||
m.Group("/variables", func() {
|
||||
m.Get("", reqToken(), reqOwner(), repo.ListVariables)
|
||||
m.Combo("/{variablename}").
|
||||
Get(reqToken(), reqOwner(), repo.GetVariable).
|
||||
Delete(reqToken(), reqOwner(), repo.DeleteVariable).
|
||||
Post(reqToken(), reqOwner(), bind(api.CreateVariableOption{}), repo.CreateVariable).
|
||||
Put(reqToken(), reqOwner(), bind(api.UpdateVariableOption{}), repo.UpdateVariable)
|
||||
})
|
||||
|
||||
m.Group("/runners", func() {
|
||||
m.Get("/registration-token", reqToken(), reqOwner(), repo.GetRegistrationToken)
|
||||
})
|
||||
})
|
||||
addActionsRoutes(
|
||||
m,
|
||||
reqOwner(),
|
||||
repo.NewAction(),
|
||||
)
|
||||
m.Group("/hooks/git", func() {
|
||||
m.Combo("").Get(repo.ListGitHooks)
|
||||
m.Group("/{id}", func() {
|
||||
|
@ -1460,27 +1474,11 @@ func Routes() *web.Route {
|
|||
m.Combo("/{username}").Get(reqToken(), org.IsMember).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.DeleteMember)
|
||||
})
|
||||
m.Group("/actions", func() {
|
||||
m.Group("/secrets", func() {
|
||||
m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets)
|
||||
m.Combo("/{secretname}").
|
||||
Put(reqToken(), reqOrgOwnership(), bind(api.CreateOrUpdateSecretOption{}), org.CreateOrUpdateSecret).
|
||||
Delete(reqToken(), reqOrgOwnership(), org.DeleteSecret)
|
||||
})
|
||||
|
||||
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(api.CreateVariableOption{}), org.CreateVariable).
|
||||
Put(reqToken(), reqOrgOwnership(), bind(api.UpdateVariableOption{}), org.UpdateVariable)
|
||||
})
|
||||
|
||||
m.Group("/runners", func() {
|
||||
m.Get("/registration-token", reqToken(), reqOrgOwnership(), org.GetRegistrationToken)
|
||||
})
|
||||
})
|
||||
addActionsRoutes(
|
||||
m,
|
||||
reqOrgOwnership(),
|
||||
org.NewAction(),
|
||||
)
|
||||
m.Group("/public_members", func() {
|
||||
m.Get("", org.ListPublicMembers)
|
||||
m.Combo("/{username}").Get(org.IsPublicMember).
|
||||
|
|
|
@ -9,16 +9,188 @@ import (
|
|||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
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/shared"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
secret_service "code.gitea.io/gitea/services/secrets"
|
||||
)
|
||||
|
||||
// ListActionsSecrets list an organization's actions secrets
|
||||
func (Action) 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"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
opts := &secret_model.FindSecretsOptions{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
secrets, count, err := db.FindAndCount[secret_model.Secret](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)
|
||||
}
|
||||
|
||||
// create or update one secret of the organization
|
||||
func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
|
||||
// swagger:operation PUT /orgs/{org}/actions/secrets/{secretname} organization updateOrgSecret
|
||||
// ---
|
||||
// summary: Create or Update a secret value in an organization
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of organization
|
||||
// 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"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
||||
|
||||
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"), opt.Data)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "CreateOrUpdateSecret", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if created {
|
||||
ctx.Status(http.StatusCreated)
|
||||
} else {
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSecret delete one secret of the organization
|
||||
func (Action) DeleteSecret(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /orgs/{org}/actions/secrets/{secretname} organization deleteOrgSecret
|
||||
// ---
|
||||
// summary: Delete a secret in an organization
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of organization
|
||||
// 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
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := secret_service.DeleteSecretByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"))
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "DeleteSecret", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
|
||||
// GetRegistrationToken returns the token to register org runners
|
||||
func (Action) GetRegistrationToken(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/actions/runners/registration-token organization orgGetRunnerRegistrationToken
|
||||
// ---
|
||||
// summary: Get an organization's actions runner registration token
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of the organization
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RegistrationToken"
|
||||
|
||||
shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
|
||||
}
|
||||
|
||||
// ListVariables list org-level variables
|
||||
func ListVariables(ctx *context.APIContext) {
|
||||
func (Action) ListVariables(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/actions/variables organization getOrgVariablesList
|
||||
// ---
|
||||
// summary: Get an org-level variables list
|
||||
|
@ -70,7 +242,7 @@ func ListVariables(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// GetVariable get an org-level variable
|
||||
func GetVariable(ctx *context.APIContext) {
|
||||
func (Action) GetVariable(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/actions/variables/{variablename} organization getOrgVariable
|
||||
// ---
|
||||
// summary: Get an org-level variable
|
||||
|
@ -119,7 +291,7 @@ func GetVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// DeleteVariable delete an org-level variable
|
||||
func DeleteVariable(ctx *context.APIContext) {
|
||||
func (Action) DeleteVariable(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /orgs/{org}/actions/variables/{variablename} organization deleteOrgVariable
|
||||
// ---
|
||||
// summary: Delete an org-level variable
|
||||
|
@ -163,7 +335,7 @@ func DeleteVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// CreateVariable create an org-level variable
|
||||
func CreateVariable(ctx *context.APIContext) {
|
||||
func (Action) CreateVariable(ctx *context.APIContext) {
|
||||
// swagger:operation POST /orgs/{org}/actions/variables/{variablename} organization createOrgVariable
|
||||
// ---
|
||||
// summary: Create an org-level variable
|
||||
|
@ -227,7 +399,7 @@ func CreateVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// UpdateVariable update an org-level variable
|
||||
func UpdateVariable(ctx *context.APIContext) {
|
||||
func (Action) UpdateVariable(ctx *context.APIContext) {
|
||||
// swagger:operation PUT /orgs/{org}/actions/variables/{variablename} organization updateOrgVariable
|
||||
// ---
|
||||
// summary: Update an org-level variable
|
||||
|
@ -289,3 +461,13 @@ func UpdateVariable(ctx *context.APIContext) {
|
|||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
var _ actions_service.API = new(Action)
|
||||
|
||||
// Action implements actions_service.API
|
||||
type Action struct{}
|
||||
|
||||
// NewAction creates a new Action service
|
||||
func NewAction() actions_service.API {
|
||||
return Action{}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/routers/api/v1/shared"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
|
||||
|
||||
// GetRegistrationToken returns the token to register org runners
|
||||
func GetRegistrationToken(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/actions/runners/registration-token organization orgGetRunnerRegistrationToken
|
||||
// ---
|
||||
// summary: Get an organization's actions runner registration token
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of the organization
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RegistrationToken"
|
||||
|
||||
shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
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"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
secret_service "code.gitea.io/gitea/services/secrets"
|
||||
)
|
||||
|
||||
// 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"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
opts := &secret_model.FindSecretsOptions{
|
||||
OwnerID: ctx.Org.Organization.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
secrets, count, err := db.FindAndCount[secret_model.Secret](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)
|
||||
}
|
||||
|
||||
// create or update one secret of the organization
|
||||
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
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of organization
|
||||
// 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"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
|
||||
|
||||
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"), opt.Data)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "CreateOrUpdateSecret", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if created {
|
||||
ctx.Status(http.StatusCreated)
|
||||
} else {
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// consumes:
|
||||
// - application/json
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: org
|
||||
// in: path
|
||||
// description: name of organization
|
||||
// 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
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
err := secret_service.DeleteSecretByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"))
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
|
||||
} else if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.Error(http.StatusNotFound, "DeleteSecret", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
|
@ -9,17 +9,76 @@ import (
|
|||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
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/shared"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
actions_service "code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
secret_service "code.gitea.io/gitea/services/secrets"
|
||||
)
|
||||
|
||||
// ListActionsSecrets list an repo's actions secrets
|
||||
func (Action) ListActionsSecrets(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/actions/secrets repository repoListActionsSecrets
|
||||
// ---
|
||||
// summary: List an repo's actions secrets
|
||||
// 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: 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"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
repo := ctx.Repo.Repository
|
||||
|
||||
opts := &secret_model.FindSecretsOptions{
|
||||
RepoID: repo.ID,
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
}
|
||||
|
||||
secrets, count, err := db.FindAndCount[secret_model.Secret](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)
|
||||
}
|
||||
|
||||
// create or update one secret of the repository
|
||||
func CreateOrUpdateSecret(ctx *context.APIContext) {
|
||||
func (Action) 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
|
||||
|
@ -82,7 +141,7 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// DeleteSecret delete one secret of the repository
|
||||
func DeleteSecret(ctx *context.APIContext) {
|
||||
func (Action) DeleteSecret(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secretname} repository deleteRepoSecret
|
||||
// ---
|
||||
// summary: Delete a secret in a repository
|
||||
|
@ -133,7 +192,7 @@ func DeleteSecret(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// GetVariable get a repo-level variable
|
||||
func GetVariable(ctx *context.APIContext) {
|
||||
func (Action) GetVariable(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/actions/variables/{variablename} repository getRepoVariable
|
||||
// ---
|
||||
// summary: Get a repo-level variable
|
||||
|
@ -186,7 +245,7 @@ func GetVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// DeleteVariable delete a repo-level variable
|
||||
func DeleteVariable(ctx *context.APIContext) {
|
||||
func (Action) DeleteVariable(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/actions/variables/{variablename} repository deleteRepoVariable
|
||||
// ---
|
||||
// summary: Delete a repo-level variable
|
||||
|
@ -235,7 +294,7 @@ func DeleteVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// CreateVariable create a repo-level variable
|
||||
func CreateVariable(ctx *context.APIContext) {
|
||||
func (Action) CreateVariable(ctx *context.APIContext) {
|
||||
// swagger:operation POST /repos/{owner}/{repo}/actions/variables/{variablename} repository createRepoVariable
|
||||
// ---
|
||||
// summary: Create a repo-level variable
|
||||
|
@ -302,7 +361,7 @@ func CreateVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// UpdateVariable update a repo-level variable
|
||||
func UpdateVariable(ctx *context.APIContext) {
|
||||
func (Action) UpdateVariable(ctx *context.APIContext) {
|
||||
// swagger:operation PUT /repos/{owner}/{repo}/actions/variables/{variablename} repository updateRepoVariable
|
||||
// ---
|
||||
// summary: Update a repo-level variable
|
||||
|
@ -369,7 +428,7 @@ func UpdateVariable(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// ListVariables list repo-level variables
|
||||
func ListVariables(ctx *context.APIContext) {
|
||||
func (Action) ListVariables(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/actions/variables repository getRepoVariablesList
|
||||
// ---
|
||||
// summary: Get repo-level variables list
|
||||
|
@ -423,3 +482,38 @@ func ListVariables(ctx *context.APIContext) {
|
|||
ctx.SetTotalCountHeader(count)
|
||||
ctx.JSON(http.StatusOK, variables)
|
||||
}
|
||||
|
||||
// GetRegistrationToken returns the token to register repo runners
|
||||
func (Action) GetRegistrationToken(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/runners/registration-token repository repoGetRunnerRegistrationToken
|
||||
// ---
|
||||
// summary: Get a repository's actions runner registration token
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: owner
|
||||
// in: path
|
||||
// description: owner of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repo
|
||||
// in: path
|
||||
// description: name of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RegistrationToken"
|
||||
|
||||
shared.GetRegistrationToken(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
|
||||
}
|
||||
|
||||
var _ actions_service.API = new(Action)
|
||||
|
||||
// Action implements actions_service.API
|
||||
type Action struct{}
|
||||
|
||||
// NewAction creates a new Action service
|
||||
func NewAction() actions_service.API {
|
||||
return Action{}
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/routers/api/v1/shared"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
// GetRegistrationToken returns the token to register repo runners
|
||||
func GetRegistrationToken(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/runners/registration-token repository repoGetRunnerRegistrationToken
|
||||
// ---
|
||||
// summary: Get a repository's actions runner registration token
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: owner
|
||||
// in: path
|
||||
// description: owner of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// - name: repo
|
||||
// in: path
|
||||
// description: name of the repo
|
||||
// type: string
|
||||
// required: true
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RegistrationToken"
|
||||
|
||||
shared.GetRegistrationToken(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import "code.gitea.io/gitea/services/context"
|
||||
|
||||
// API for actions of a repository or organization
|
||||
type API interface {
|
||||
// ListActionsSecrets list secrets
|
||||
ListActionsSecrets(*context.APIContext)
|
||||
// CreateOrUpdateSecret create or update a secret
|
||||
CreateOrUpdateSecret(*context.APIContext)
|
||||
// DeleteSecret delete a secret
|
||||
DeleteSecret(*context.APIContext)
|
||||
// ListVariables list variables
|
||||
ListVariables(*context.APIContext)
|
||||
// GetVariable get a variable
|
||||
GetVariable(*context.APIContext)
|
||||
// DeleteVariable delete a variable
|
||||
DeleteVariable(*context.APIContext)
|
||||
// CreateVariable create a variable
|
||||
CreateVariable(*context.APIContext)
|
||||
// UpdateVariable update a variable
|
||||
UpdateVariable(*context.APIContext)
|
||||
// GetRegistrationToken get registration token
|
||||
GetRegistrationToken(*context.APIContext)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{{if $.IsSplitStyle}}
|
||||
{{range $k, $line := $.section.Lines}}
|
||||
<tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}}">
|
||||
<tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}} line-expanded">
|
||||
{{if eq .GetType 4}}
|
||||
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}">
|
||||
<div class="tw-flex">
|
||||
|
@ -26,17 +26,17 @@
|
|||
{{else}}
|
||||
{{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}}
|
||||
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{$.FileNameHash}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
||||
<td class="blob-excerpt lines-escape lines-escape-old">{{if and $line.LeftIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="blob-excerpt lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td>
|
||||
<td class="blob-excerpt lines-code lines-code-old">{{/*
|
||||
<td class="lines-escape lines-escape-old">{{if and $line.LeftIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td>
|
||||
<td class="lines-code lines-code-old">{{/*
|
||||
*/}}{{if $line.LeftIdx}}{{template "repo/diff/section_code" dict "diff" $inlineDiff}}{{else}}{{/*
|
||||
*/}}<code class="code-inner"></code>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
*/}}</td>
|
||||
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$.FileNameHash}}R{{$line.RightIdx}}{{end}}"></span></td>
|
||||
<td class="blob-excerpt lines-escape lines-escape-new">{{if and $line.RightIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="blob-excerpt lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td>
|
||||
<td class="blob-excerpt lines-code lines-code-new">{{/*
|
||||
<td class="lines-escape lines-escape-new">{{if and $line.RightIdx $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="tw-font-mono" data-type-marker=""></span>{{end}}</td>
|
||||
<td class="lines-code lines-code-new">{{/*
|
||||
*/}}{{if $line.RightIdx}}{{template "repo/diff/section_code" dict "diff" $inlineDiff}}{{else}}{{/*
|
||||
*/}}<code class="code-inner"></code>{{/*
|
||||
*/}}{{end}}{{/*
|
||||
|
@ -46,7 +46,7 @@
|
|||
{{end}}
|
||||
{{else}}
|
||||
{{range $k, $line := $.section.Lines}}
|
||||
<tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}}">
|
||||
<tr class="{{.GetHTMLDiffLineType}}-code nl-{{$k}} ol-{{$k}} line-expanded">
|
||||
{{if eq .GetType 4}}
|
||||
<td colspan="2" class="lines-num">
|
||||
<div class="tw-flex">
|
||||
|
@ -72,9 +72,9 @@
|
|||
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$.FileNameHash}}R{{$line.RightIdx}}{{end}}"></span></td>
|
||||
{{end}}
|
||||
{{$inlineDiff := $.section.GetComputedInlineDiffFor $line ctx.Locale}}
|
||||
<td class="blob-excerpt lines-escape">{{if $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="blob-excerpt lines-type-marker"><span class="tw-font-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
|
||||
<td class="blob-excerpt lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}"><code {{if $inlineDiff.EscapeStatus.Escaped}}class="code-inner has-escaped" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"{{else}}class="code-inner"{{end}}>{{$inlineDiff.Content}}</code></td>
|
||||
<td class="lines-escape">{{if $inlineDiff.EscapeStatus.Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"></button>{{end}}</td>
|
||||
<td class="lines-type-marker"><span class="tw-font-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
|
||||
<td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}"><code {{if $inlineDiff.EscapeStatus.Escaped}}class="code-inner has-escaped" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff}}"{{else}}class="code-inner"{{end}}>{{$inlineDiff.Content}}</code></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -3843,6 +3843,54 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/actions/secrets": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
"summary": "List an repo's actions secrets",
|
||||
"operationId": "repoListActionsSecrets",
|
||||
"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": "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"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/responses/notFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/actions/secrets/{secretname}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
|
|
|
@ -24,6 +24,12 @@ func TestAPIRepoSecrets(t *testing.T) {
|
|||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
t.Run("List", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/secrets", repo.FullName())).
|
||||
AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
})
|
||||
|
||||
t.Run("Create", func(t *testing.T) {
|
||||
cases := []struct {
|
||||
Name string
|
||||
|
@ -31,7 +37,7 @@ func TestAPIRepoSecrets(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
Name: "",
|
||||
ExpectedStatus: http.StatusNotFound,
|
||||
ExpectedStatus: http.StatusMethodNotAllowed,
|
||||
},
|
||||
{
|
||||
Name: "-",
|
||||
|
|
|
@ -2377,7 +2377,7 @@ tbody.commit-list {
|
|||
|
||||
.tag-code,
|
||||
.tag-code td,
|
||||
.tag-code .blob-excerpt {
|
||||
.tag-code.line-expanded {
|
||||
background-color: var(--color-box-body-highlight);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@ -2393,8 +2393,8 @@ tbody.commit-list {
|
|||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
.blob-excerpt {
|
||||
background-color: var(--color-secondary-alpha-30);
|
||||
.line-expanded {
|
||||
background-color: var(--color-secondary-alpha-20);
|
||||
}
|
||||
|
||||
.issue-keyword {
|
||||
|
@ -2553,11 +2553,9 @@ tbody.commit-list {
|
|||
|
||||
.code-diff-unified .add-code,
|
||||
.code-diff-unified .add-code td,
|
||||
.code-diff-split .add-code .lines-num-new,
|
||||
.code-diff-split .add-code .lines-type-marker-new,
|
||||
.code-diff-split .add-code .lines-escape-new,
|
||||
.code-diff-split .add-code .lines-code-new,
|
||||
.code-diff-split .del-code .add-code.lines-num-new,
|
||||
.code-diff-split .del-code .add-code.lines-type-marker-new,
|
||||
.code-diff-split .del-code .add-code.lines-escape-new,
|
||||
.code-diff-split .del-code .add-code.lines-code-new {
|
||||
|
@ -2565,17 +2563,33 @@ tbody.commit-list {
|
|||
border-color: var(--color-diff-added-row-border);
|
||||
}
|
||||
|
||||
.code-diff-split .del-code .lines-num-new,
|
||||
.code-diff-split .del-code .lines-type-marker-new,
|
||||
.code-diff-split .del-code .lines-code-new,
|
||||
.code-diff-split .del-code .lines-escape-new,
|
||||
.code-diff-split .add-code .lines-num-old,
|
||||
.code-diff-split .add-code .lines-escape-old,
|
||||
.code-diff-split .add-code .lines-type-marker-old,
|
||||
.code-diff-split .add-code .lines-code-old {
|
||||
background: var(--color-diff-inactive);
|
||||
}
|
||||
|
||||
.code-diff-split .add-code .lines-num.lines-num-old,
|
||||
.code-diff-split .del-code .lines-num.lines-num-new {
|
||||
background: var(--color-diff-inactive);
|
||||
}
|
||||
|
||||
.code-diff-unified .del-code .lines-num,
|
||||
.code-diff-split .del-code .lines-num {
|
||||
background: var(--color-diff-removed-linenum-bg);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.code-diff-unified .add-code .lines-num,
|
||||
.code-diff-split .add-code .lines-num,
|
||||
.code-diff-split .del-code .add-code.lines-num {
|
||||
background: var(--color-diff-added-linenum-bg);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.code-diff-split tbody tr td:nth-child(5),
|
||||
.code-diff-split tbody tr td.add-comment-right {
|
||||
border-left: 1px solid var(--color-secondary);
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
/* red/green colorblind-friendly colors */
|
||||
/* from GitHub: --diffBlob-addition-*, --diffBlob-deletion-*, etc */
|
||||
:root {
|
||||
--color-diff-added-word-bg: #388bfd66;
|
||||
--color-diff-added-row-bg: #388bfd26;
|
||||
|
||||
--color-diff-removed-word-bg: #db6d2866;
|
||||
--color-diff-removed-row-bg: #db6d2826;
|
||||
--color-diff-added-linenum-bg: #1979fd46;
|
||||
--color-diff-added-row-bg: #1979fd20;
|
||||
--color-diff-added-word-bg: #1979fd66;
|
||||
--color-diff-removed-linenum-bg: #c8622146;
|
||||
--color-diff-removed-row-bg: #c8622120;
|
||||
--color-diff-removed-word-bg: #c8622166;
|
||||
}
|
||||
|
|
|
@ -143,14 +143,16 @@
|
|||
--color-grey-light: #818f9e;
|
||||
--color-gold: #b1983b;
|
||||
--color-white: #ffffff;
|
||||
--color-diff-removed-word-bg: #6f3333;
|
||||
--color-diff-added-word-bg: #3c653c;
|
||||
--color-diff-removed-row-bg: #3c2626;
|
||||
--color-diff-moved-row-bg: #818044;
|
||||
--color-diff-added-row-bg: #283e2d;
|
||||
--color-diff-removed-row-border: #634343;
|
||||
--color-diff-moved-row-border: #bcca6f;
|
||||
--color-diff-added-linenum-bg: #274227;
|
||||
--color-diff-added-row-bg: #203224;
|
||||
--color-diff-added-row-border: #314a37;
|
||||
--color-diff-added-word-bg: #3c653c;
|
||||
--color-diff-moved-row-bg: #818044;
|
||||
--color-diff-moved-row-border: #bcca6f;
|
||||
--color-diff-removed-linenum-bg: #482121;
|
||||
--color-diff-removed-row-bg: #301e1e;
|
||||
--color-diff-removed-row-border: #634343;
|
||||
--color-diff-removed-word-bg: #6f3333;
|
||||
--color-diff-inactive: #22282d;
|
||||
--color-error-border: #a04141;
|
||||
--color-error-bg: #522;
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
/* red/green colorblind-friendly colors */
|
||||
/* from GitHub: --diffBlob-addition-*, --diffBlob-deletion-*, etc */
|
||||
:root {
|
||||
--color-diff-added-word-bg: #54aeff66;
|
||||
--color-diff-added-linenum-bg: #54aeff4d;
|
||||
--color-diff-added-row-bg: #ddf4ff80;
|
||||
|
||||
--color-diff-removed-word-bg: #ffb77c80;
|
||||
--color-diff-added-word-bg: #54aeff66;
|
||||
--color-diff-removed-linenum-bg: #ffb77c4d;
|
||||
--color-diff-removed-row-bg: #fff1e580;
|
||||
--color-diff-removed-word-bg: #ffb77c80;
|
||||
}
|
||||
|
|
|
@ -143,14 +143,16 @@
|
|||
--color-grey-light: #7c838a;
|
||||
--color-gold: #a1882b;
|
||||
--color-white: #ffffff;
|
||||
--color-diff-removed-word-bg: #fdb8c0;
|
||||
--color-diff-added-word-bg: #acf2bd;
|
||||
--color-diff-removed-row-bg: #ffeef0;
|
||||
--color-diff-moved-row-bg: #f1f8d1;
|
||||
--color-diff-added-linenum-bg: #d1f8d9;
|
||||
--color-diff-added-row-bg: #e6ffed;
|
||||
--color-diff-removed-row-border: #f1c0c0;
|
||||
--color-diff-moved-row-border: #d0e27f;
|
||||
--color-diff-added-row-border: #e6ffed;
|
||||
--color-diff-added-word-bg: #acf2bd;
|
||||
--color-diff-moved-row-bg: #f1f8d1;
|
||||
--color-diff-moved-row-border: #d0e27f;
|
||||
--color-diff-removed-linenum-bg: #ffcecb;
|
||||
--color-diff-removed-row-bg: #ffeef0;
|
||||
--color-diff-removed-row-border: #f1c0c0;
|
||||
--color-diff-removed-word-bg: #fdb8c0;
|
||||
--color-diff-inactive: #f0f2f4;
|
||||
--color-error-border: #e0b4b4;
|
||||
--color-error-bg: #fff6f6;
|
||||
|
|
|
@ -304,10 +304,10 @@ export function initGlobalLinkActions() {
|
|||
}
|
||||
|
||||
const $dialog = $(`.delete.modal${filter}`);
|
||||
$dialog.find('.name').text($this.data('name'));
|
||||
$dialog.find('.name')[0].textContent = $this.data('name');
|
||||
for (const [key, value] of Object.entries(dataArray)) {
|
||||
if (key && key.startsWith('data')) {
|
||||
$dialog.find(`.${key}`).text(value);
|
||||
$dialog.find(`.${key}`)[0].textContent = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,7 @@ function initGlobalShowModal() {
|
|||
} else if ($attrTarget[0].matches('input, textarea')) {
|
||||
$attrTarget.val(attrib.value); // FIXME: add more supports like checkbox
|
||||
} else {
|
||||
$attrTarget.text(attrib.value); // FIXME: it should be more strict here, only handle div/span/p
|
||||
$attrTarget[0].textContent = attrib.value; // FIXME: it should be more strict here, only handle div/span/p
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ export function initImageDiff() {
|
|||
return loadElem(img, info.path);
|
||||
}));
|
||||
// only the first images is associated with $boundsInfo
|
||||
if (!success) info.$boundsInfo.text('(image error)');
|
||||
if (!success) info.$boundsInfo[0].textContent = '(image error)';
|
||||
if (info.mime === 'image/svg+xml') {
|
||||
const resp = await GET(info.path);
|
||||
const text = await resp.text();
|
||||
|
|
|
@ -47,16 +47,13 @@ async function receiveUpdateCount(event) {
|
|||
|
||||
export function initNotificationCount() {
|
||||
const $notificationCount = $('.notification_count');
|
||||
|
||||
if (!$notificationCount.length) {
|
||||
return;
|
||||
}
|
||||
if (!$notificationCount.length) return;
|
||||
|
||||
let usingPeriodicPoller = false;
|
||||
const startPeriodicPoller = (timeout, lastCount) => {
|
||||
if (timeout <= 0 || !Number.isFinite(timeout)) return;
|
||||
usingPeriodicPoller = true;
|
||||
lastCount = lastCount ?? $notificationCount.text();
|
||||
lastCount = lastCount ?? getCurrentCount();
|
||||
setTimeout(async () => {
|
||||
await updateNotificationCountWithCallback(startPeriodicPoller, timeout, lastCount);
|
||||
}, timeout);
|
||||
|
@ -120,8 +117,12 @@ export function initNotificationCount() {
|
|||
startPeriodicPoller(notificationSettings.MinTimeout);
|
||||
}
|
||||
|
||||
function getCurrentCount() {
|
||||
return document.querySelector('.notification_count').textContent;
|
||||
}
|
||||
|
||||
async function updateNotificationCountWithCallback(callback, timeout, lastCount) {
|
||||
const currentCount = $('.notification_count').text();
|
||||
const currentCount = getCurrentCount();
|
||||
if (lastCount !== currentCount) {
|
||||
callback(notificationSettings.MinTimeout, currentCount);
|
||||
return;
|
||||
|
|
|
@ -70,7 +70,7 @@ export function initRepoEditor() {
|
|||
hideElem('.quick-pull-branch-name');
|
||||
document.querySelector('.quick-pull-branch-name input').required = false;
|
||||
}
|
||||
$('#commit-button').text(this.getAttribute('button_text'));
|
||||
$('#commit-button')[0].textContent = this.getAttribute('button_text');
|
||||
});
|
||||
|
||||
const joinTreePath = ($fileNameEl) => {
|
||||
|
@ -78,9 +78,9 @@ export function initRepoEditor() {
|
|||
$('.breadcrumb span.section').each(function () {
|
||||
const $element = $(this);
|
||||
if ($element.find('a').length) {
|
||||
parts.push($element.find('a').text());
|
||||
parts.push($element.find('a')[0].textContent);
|
||||
} else {
|
||||
parts.push($element.text());
|
||||
parts.push($element[0].textContent);
|
||||
}
|
||||
});
|
||||
if ($fileNameEl.val()) parts.push($fileNameEl.val());
|
||||
|
@ -116,7 +116,7 @@ export function initRepoEditor() {
|
|||
if (e.code === 'Backspace' && getCursorPosition($(this)) === 0 && $section.length > 0) {
|
||||
e.preventDefault();
|
||||
const $divider = $('.breadcrumb .breadcrumb-divider');
|
||||
const value = $section.last().find('a').text();
|
||||
const value = $section.last().find('a')[0].textContent;
|
||||
$(this).val(value + $(this).val());
|
||||
this.setSelectionRange(value.length, value.length);
|
||||
$section.last().remove();
|
||||
|
|
|
@ -183,7 +183,7 @@ export function initRepoIssueCommentEdit() {
|
|||
$(document).on('click', '.quote-reply', async function (event) {
|
||||
event.preventDefault();
|
||||
const target = $(this).data('target');
|
||||
const quote = $(`#${target}`).text().replace(/\n/g, '\n> ');
|
||||
const quote = $(`#${target}`)[0].textContent.replace(/\n/g, '\n> ');
|
||||
const content = `> ${quote}\n\n`;
|
||||
let editor;
|
||||
if ($(this).hasClass('quote-reply-diff')) {
|
||||
|
|
|
@ -281,7 +281,7 @@ export function initRepoPullRequestUpdate() {
|
|||
if (url) {
|
||||
const buttonText = pullUpdateButton.querySelector('.button-text');
|
||||
if (buttonText) {
|
||||
buttonText.textContent = $choice.text();
|
||||
buttonText.textContent = $choice[0].textContent;
|
||||
}
|
||||
pullUpdateButton.setAttribute('data-do', url);
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ export function initRepoIssueReferenceIssue() {
|
|||
// Reference issue
|
||||
$(document).on('click', '.reference-issue', function (event) {
|
||||
const $this = $(this);
|
||||
const content = $(`#${$this.data('target')}`).text();
|
||||
const content = $(`#${$this.data('target')}`)[0].textContent;
|
||||
const poster = $this.data('poster-username');
|
||||
const reference = toAbsoluteUrl($this.data('reference'));
|
||||
const $modal = $($this.data('modal'));
|
||||
|
@ -603,8 +603,7 @@ export function initRepoIssueWipToggle() {
|
|||
|
||||
async function pullrequest_targetbranch_change(update_url) {
|
||||
const targetBranch = $('#pull-target-branch').data('branch');
|
||||
const $branchTarget = $('#branch_target');
|
||||
if (targetBranch === $branchTarget.text()) {
|
||||
if (targetBranch === $('#branch_target')[0].textContent) {
|
||||
window.location.reload();
|
||||
return false;
|
||||
}
|
||||
|
@ -640,8 +639,9 @@ export function initRepoIssueTitleEdit() {
|
|||
$('#cancel-edit-title').on('click', editTitleToggle);
|
||||
$('#save-edit-title').on('click', editTitleToggle).on('click', async function () {
|
||||
const pullrequest_target_update_url = this.getAttribute('data-target-update-url');
|
||||
if (!$editInput.val().length || $editInput.val() === $issueTitle.text()) {
|
||||
$editInput.val($issueTitle.text());
|
||||
const titleText = $issueTitle[0].textContent;
|
||||
if (!$editInput.val().length || $editInput.val() === titleText) {
|
||||
$editInput.val(titleText);
|
||||
await pullrequest_targetbranch_change(pullrequest_target_update_url);
|
||||
} else {
|
||||
try {
|
||||
|
@ -650,7 +650,7 @@ export function initRepoIssueTitleEdit() {
|
|||
const response = await POST(this.getAttribute('data-update-url'), {data: params});
|
||||
const data = await response.json();
|
||||
$editInput.val(data.title);
|
||||
$issueTitle.text(data.title);
|
||||
$issueTitle[0].textContent = data.title;
|
||||
if (pullrequest_target_update_url) {
|
||||
await pullrequest_targetbranch_change(pullrequest_target_update_url); // it will reload the window
|
||||
} else {
|
||||
|
|
|
@ -64,7 +64,7 @@ export function initRepoCommentForm() {
|
|||
const editMode = $('#editing_mode').val();
|
||||
$($(this).data('id-selector')).val(selectedValue);
|
||||
if ($isNewIssue) {
|
||||
$selectBranch.find('.ui .branch-name').text($(this).data('name'));
|
||||
$selectBranch.find('.ui .branch-name')[0].textContent = $(this).data('name');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ export function initRepoCommentForm() {
|
|||
console.error(error);
|
||||
}
|
||||
} else if (editMode === '') {
|
||||
$selectBranch.find('.ui .branch-name').text(selectedValue);
|
||||
$selectBranch.find('.ui .branch-name')[0].textContent = selectedValue;
|
||||
}
|
||||
});
|
||||
$selectBranch.find('.reference.column').on('click', function () {
|
||||
|
@ -275,7 +275,7 @@ export function initRepoCommentForm() {
|
|||
$list.find('.selected').html(`
|
||||
<a class="item muted sidebar-item-link" href=${$(this).data('href')}>
|
||||
${icon}
|
||||
${htmlEscape($(this).text())}
|
||||
${htmlEscape(this.textContent)}
|
||||
</a>
|
||||
`);
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ export function initRepoSettingsCollaboration() {
|
|||
data.append('mode', value);
|
||||
await POST(el.getAttribute('data-url'), {data});
|
||||
} catch {
|
||||
$text.text('(error)'); // prevent from misleading users when error occurs
|
||||
$text[0].textContent = '(error)'; // prevent from misleading users when error occurs
|
||||
el.setAttribute('data-last-value', lastValue);
|
||||
}
|
||||
},
|
||||
onChange(_value, text, _$choice) {
|
||||
$text.text(text); // update the text when using keyboard navigating
|
||||
$text[0].textContent = text; // update the text when using keyboard navigating
|
||||
},
|
||||
onHide() {
|
||||
// set to the really selected value, defer to next tick to make sure `action` has finished its work because the calling order might be onHide -> action
|
||||
|
@ -36,7 +36,7 @@ export function initRepoSettingsCollaboration() {
|
|||
if ($item) {
|
||||
$dropdown.dropdown('set selected', el.getAttribute('data-last-value'));
|
||||
} else {
|
||||
$text.text('(none)'); // prevent from misleading users when the access mode is undefined
|
||||
$text[0].textContent = '(none)'; // prevent from misleading users when the access mode is undefined
|
||||
}
|
||||
}, 0);
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue