feat: vendor gitea 1.16.2
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
const (
|
||||
tplOrgSettingsActionsGeneral templates.TplName = "org/settings/actions_general"
|
||||
tplUserSettingsActionsGeneral templates.TplName = "user/settings/actions_general"
|
||||
)
|
||||
|
||||
// ParseMaxTokenPermissions parses the maximum token permissions from form values
|
||||
func ParseMaxTokenPermissions(ctx *context.Context) *repo_model.ActionsTokenPermissions {
|
||||
parseMaxPerm := func(unitType unit.Type) perm.AccessMode {
|
||||
value := ctx.FormString("max_unit_access_mode_" + strconv.Itoa(int(unitType)))
|
||||
switch value {
|
||||
case "write":
|
||||
return perm.AccessModeWrite
|
||||
case "read":
|
||||
return perm.AccessModeRead
|
||||
default:
|
||||
return perm.AccessModeNone
|
||||
}
|
||||
}
|
||||
ret := new(repo_model.MakeActionsTokenPermissions(perm.AccessModeNone))
|
||||
for _, ut := range repo_model.ActionsTokenUnitTypes {
|
||||
ret.UnitAccessModes[ut] = parseMaxPerm(ut)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// GeneralSettings renders the actions general settings page
|
||||
func GeneralSettings(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("actions.actions")
|
||||
|
||||
rCtx, err := getRunnersCtx(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("getRunnersCtx", err)
|
||||
return
|
||||
}
|
||||
|
||||
if rCtx.IsOrg {
|
||||
ctx.Data["PageIsOrgSettings"] = true
|
||||
ctx.Data["PageIsOrgSettingsActionsGeneral"] = true
|
||||
} else if rCtx.IsUser {
|
||||
ctx.Data["PageIsUserSettings"] = true
|
||||
ctx.Data["PageIsUserSettingsActionsGeneral"] = true
|
||||
} else {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Load User/Org Actions Config
|
||||
actionsCfg, err := actions_model.GetOwnerActionsConfig(ctx, rCtx.OwnerID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOwnerActionsConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["TokenPermissionMode"] = actionsCfg.TokenPermissionMode
|
||||
ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive
|
||||
ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted
|
||||
ctx.Data["MaxTokenPermissions"] = actionsCfg.MaxTokenPermissions
|
||||
if actionsCfg.MaxTokenPermissions == nil {
|
||||
ctx.Data["MaxTokenPermissions"] = (&repo_model.ActionsConfig{}).GetMaxTokenPermissions()
|
||||
}
|
||||
ctx.Data["EnableMaxTokenPermissions"] = actionsCfg.MaxTokenPermissions != nil
|
||||
|
||||
// Load Allowed Repositories
|
||||
allowedRepos, err := repo_model.GetOwnerRepositoriesByIDs(ctx, rCtx.OwnerID, actionsCfg.AllowedCrossRepoIDs)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOwnerRepositoriesByIDs", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["AllowedRepos"] = allowedRepos
|
||||
ctx.Data["OwnerID"] = rCtx.OwnerID
|
||||
|
||||
if rCtx.IsOrg {
|
||||
ctx.HTML(http.StatusOK, tplOrgSettingsActionsGeneral)
|
||||
} else {
|
||||
ctx.HTML(http.StatusOK, tplUserSettingsActionsGeneral)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateGeneralSettings responses for actions general settings page
|
||||
func UpdateGeneralSettings(ctx *context.Context) {
|
||||
rCtx, err := getRunnersCtx(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("getRunnersCtx", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !rCtx.IsOrg && !rCtx.IsUser {
|
||||
ctx.NotFound(nil)
|
||||
return
|
||||
}
|
||||
|
||||
actionsCfg, err := actions_model.GetOwnerActionsConfig(ctx, rCtx.OwnerID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOwnerActionsConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.FormBool("cross_repo_add_target") {
|
||||
targetRepoName := ctx.FormString("cross_repo_add_target_name")
|
||||
if targetRepoName != "" {
|
||||
targetRepo, err := repo_model.GetRepositoryByName(ctx, rCtx.OwnerID, targetRepoName)
|
||||
if err != nil {
|
||||
if repo_model.IsErrRepoNotExist(err) {
|
||||
ctx.JSONError("Repository doesn't exist")
|
||||
return
|
||||
}
|
||||
ctx.ServerError("GetRepositoryByName", err)
|
||||
return
|
||||
}
|
||||
if !slices.Contains(actionsCfg.AllowedCrossRepoIDs, targetRepo.ID) {
|
||||
actionsCfg.AllowedCrossRepoIDs = append(actionsCfg.AllowedCrossRepoIDs, targetRepo.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if crossRepoRemoveTargetID := ctx.FormInt64("cross_repo_remove_target_id"); crossRepoRemoveTargetID != 0 {
|
||||
actionsCfg.AllowedCrossRepoIDs = util.SliceRemoveAll(actionsCfg.AllowedCrossRepoIDs, crossRepoRemoveTargetID)
|
||||
}
|
||||
|
||||
// Update Token Permission Mode
|
||||
tokenPermissionMode, tokenPermissionModeValid := util.EnumValue(repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")))
|
||||
if tokenPermissionModeValid {
|
||||
actionsCfg.TokenPermissionMode = tokenPermissionMode
|
||||
enableMaxPermissions := ctx.FormBool("enable_max_permissions")
|
||||
// Update Maximum Permissions (radio buttons: none/read/write)
|
||||
if enableMaxPermissions {
|
||||
actionsCfg.MaxTokenPermissions = ParseMaxTokenPermissions(ctx)
|
||||
} else {
|
||||
actionsCfg.MaxTokenPermissions = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := actions_model.SetOwnerActionsConfig(ctx, rCtx.OwnerID, actionsCfg); err != nil {
|
||||
ctx.ServerError("SetOwnerActionsConfig", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.saved_successfully"))
|
||||
ctx.JSONRedirect("") // use JSONRedirect because frontend uses form-fetch-action
|
||||
}
|
||||
@@ -5,6 +5,7 @@ package actions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
@@ -58,8 +59,7 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
|
||||
|
||||
if ctx.Data["PageIsOrgSettings"] == true {
|
||||
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||
ctx.ServerError("RenderUserOrgHeader", err)
|
||||
return nil, nil
|
||||
return nil, fmt.Errorf("RenderUserOrgHeader: %w", err)
|
||||
}
|
||||
return &runnersCtx{
|
||||
RepoID: 0,
|
||||
@@ -159,7 +159,7 @@ func Runners(ctx *context.Context) {
|
||||
ctx.Data["RunnerRepoID"] = opts.RepoID
|
||||
ctx.Data["SortType"] = opts.Sort
|
||||
|
||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
||||
pager := context.NewPagination(count, opts.PageSize, opts.Page, 5)
|
||||
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
@@ -220,7 +220,7 @@ func RunnersEdit(ctx *context.Context) {
|
||||
}
|
||||
|
||||
ctx.Data["Tasks"] = tasks
|
||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
|
||||
pager := context.NewPagination(count, opts.PageSize, opts.Page, 5)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
ctx.HTML(http.StatusOK, rCtx.RunnerEditTemplate)
|
||||
@@ -321,6 +321,47 @@ func RunnerDeletePost(ctx *context.Context) {
|
||||
ctx.JSONRedirect(successRedirectTo)
|
||||
}
|
||||
|
||||
func RunnerUpdatePost(ctx *context.Context) {
|
||||
rCtx, err := getRunnersCtx(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("getRunnersCtx", err)
|
||||
return
|
||||
}
|
||||
|
||||
runner := findActionsRunner(ctx, rCtx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if !runner.EditableInContext(rCtx.OwnerID, rCtx.RepoID) {
|
||||
ctx.NotFound(util.NewPermissionDeniedErrorf("no permission to edit this runner"))
|
||||
return
|
||||
}
|
||||
|
||||
isDisabled := ctx.FormOptionalBool("disabled")
|
||||
if !isDisabled.Has() {
|
||||
ctx.HTTPError(http.StatusBadRequest, "missing 'disabled' parameter")
|
||||
return
|
||||
}
|
||||
|
||||
successKey := "actions.runners.enable_runner_success"
|
||||
failedKey := "actions.runners.enable_runner_failed"
|
||||
if isDisabled.Value() {
|
||||
successKey = "actions.runners.disable_runner_success"
|
||||
failedKey = "actions.runners.disable_runner_failed"
|
||||
}
|
||||
|
||||
if err := actions_model.SetRunnerDisabled(ctx, runner, isDisabled.Value()); err != nil {
|
||||
log.Warn("RunnerUpdatePost.SetRunnerDisabled failed: %v, url: %s", err, ctx.Req.URL)
|
||||
ctx.Flash.Error(ctx.Tr(failedKey))
|
||||
ctx.JSONRedirect("")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr(successKey))
|
||||
ctx.JSONRedirect("")
|
||||
}
|
||||
|
||||
func RedirectToDefaultSetting(ctx *context.Context) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/settings/actions/runners")
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
||||
if ctx.Data["PageIsOrgSettings"] == true {
|
||||
if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil {
|
||||
ctx.ServerError("RenderUserOrgHeader", err)
|
||||
return nil, nil
|
||||
return nil, nil //nolint:nilnil // error is already handled by ctx.ServerError
|
||||
}
|
||||
return &variablesCtx{
|
||||
OwnerID: ctx.ContextUser.ID,
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package mention
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
)
|
||||
|
||||
// Mention is the JSON structure returned by mention autocomplete endpoints.
|
||||
type Mention struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"fullname"`
|
||||
Avatar string `json:"avatar"`
|
||||
}
|
||||
|
||||
// Collector builds a deduplicated list of Mention entries.
|
||||
type Collector struct {
|
||||
seen map[string]bool
|
||||
Result []Mention
|
||||
}
|
||||
|
||||
// NewCollector creates a new Collector.
|
||||
func NewCollector() *Collector {
|
||||
return &Collector{seen: make(map[string]bool)}
|
||||
}
|
||||
|
||||
// AddUsers adds user mentions, skipping duplicates.
|
||||
func (c *Collector) AddUsers(ctx context.Context, users []*user_model.User) {
|
||||
for _, u := range users {
|
||||
if !c.seen[u.Name] {
|
||||
c.seen[u.Name] = true
|
||||
c.Result = append(c.Result, Mention{
|
||||
Key: u.Name + " " + u.FullName,
|
||||
Value: u.Name,
|
||||
Name: u.Name,
|
||||
FullName: u.FullName,
|
||||
Avatar: u.AvatarLink(ctx),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddMentionableTeams loads and adds team mentions for the given owner (if it's an org).
|
||||
func (c *Collector) AddMentionableTeams(ctx context.Context, doer, owner *user_model.User) error {
|
||||
if doer == nil || !owner.IsOrganization() {
|
||||
return nil
|
||||
}
|
||||
|
||||
org := organization.OrgFromUser(owner)
|
||||
isAdmin := doer.IsAdmin
|
||||
if !isAdmin {
|
||||
var err error
|
||||
isAdmin, err = org.IsOwnedBy(ctx, doer.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var teams []*organization.Team
|
||||
var err error
|
||||
if isAdmin {
|
||||
teams, err = org.LoadTeams(ctx)
|
||||
} else {
|
||||
teams, err = org.GetUserTeams(ctx, doer.ID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, team := range teams {
|
||||
key := owner.Name + "/" + team.Name
|
||||
if !c.seen[key] {
|
||||
c.seen[key] = true
|
||||
c.Result = append(c.Result, Mention{
|
||||
Key: key,
|
||||
Value: key,
|
||||
Name: key,
|
||||
Avatar: owner.AvatarLink(ctx),
|
||||
})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -29,7 +29,7 @@ func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) {
|
||||
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
|
||||
form := web.GetForm(ctx).(*forms.AddSecretForm)
|
||||
|
||||
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data), form.Description)
|
||||
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.NormalizeStringEOL(form.Data), form.Description)
|
||||
if err != nil {
|
||||
log.Error("CreateOrUpdateSecret failed: %v", err)
|
||||
ctx.JSONError(ctx.Tr("secrets.save_failed"))
|
||||
|
||||
@@ -101,7 +101,7 @@ func FindOwnerProfileReadme(ctx *context.Context, doer *user_model.User, optProf
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer)
|
||||
perm, err := access_model.GetDoerRepoPermission(ctx, profileDbRepo, doer)
|
||||
if err != nil {
|
||||
log.Error("FindOwnerProfileReadme failed to GetRepositoryByName: %v", err)
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user