feat: vendor gitea 1.16.2
This commit is contained in:
@@ -141,7 +141,7 @@ func home(ctx *context.Context, viewRepositories bool) {
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["Total"] = count
|
||||
|
||||
pager := context.NewPagination(int(count), setting.UI.User.RepoPagingNum, page, 5)
|
||||
pager := context.NewPagination(count, setting.UI.User.RepoPagingNum, page, 5)
|
||||
pager.AddParamFromRequest(ctx.Req)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
shared_user "code.gitea.io/gitea/routers/web/shared/user"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
org_service "code.gitea.io/gitea/services/org"
|
||||
@@ -56,7 +58,7 @@ func Members(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
|
||||
pager := context.NewPagination(total, setting.UI.MembersPagingNum, page, 5)
|
||||
opts.ListOptions.Page = page
|
||||
opts.ListOptions.PageSize = setting.UI.MembersPagingNum
|
||||
members, membersIsPublic, err := organization.FindOrgMembers(ctx, opts)
|
||||
@@ -76,11 +78,11 @@ func Members(ctx *context.Context) {
|
||||
// MembersAction response for operation to a member of organization
|
||||
func MembersAction(ctx *context.Context) {
|
||||
member, err := user_model.GetUserByID(ctx, ctx.FormInt64("uid"))
|
||||
if err != nil {
|
||||
log.Error("GetUserByID: %v", err)
|
||||
}
|
||||
if member == nil {
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/members")
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
ctx.HTTPError(http.StatusNotFound)
|
||||
return
|
||||
} else if err != nil {
|
||||
ctx.ServerError("GetUserByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,40 +107,25 @@ func MembersAction(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
err = org_service.RemoveOrgUser(ctx, org, member)
|
||||
if organization.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
ctx.JSONRedirect(ctx.Org.OrgLink + "/members")
|
||||
return
|
||||
}
|
||||
case "leave":
|
||||
err = org_service.RemoveOrgUser(ctx, org, ctx.Doer)
|
||||
if err == nil {
|
||||
ctx.Flash.Success(ctx.Tr("form.organization_leave_success", org.DisplayName()))
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"redirect": "", // keep the user stay on current page, in case they want to do other operations.
|
||||
})
|
||||
} else if organization.IsErrLastOrgOwner(err) {
|
||||
ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
|
||||
ctx.JSONRedirect(ctx.Org.OrgLink + "/members")
|
||||
} else {
|
||||
log.Error("RemoveOrgUser(%d,%d): %v", org.ID, ctx.Doer.ID, err)
|
||||
ctx.JSONRedirect(setting.AppSubURL + "/")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
ctx.JSONOK()
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Error("Action(%s): %v", ctx.PathParam("action"), err)
|
||||
ctx.JSON(http.StatusOK, map[string]any{
|
||||
"ok": false,
|
||||
"err": err.Error(),
|
||||
})
|
||||
if organization.IsErrLastOrgOwner(err) {
|
||||
ctx.JSONError(ctx.Tr("form.last_org_owner"))
|
||||
return
|
||||
}
|
||||
|
||||
redirect := ctx.Org.OrgLink + "/members"
|
||||
if ctx.PathParam("action") == "leave" {
|
||||
redirect = setting.AppSubURL + "/"
|
||||
}
|
||||
|
||||
ctx.JSONRedirect(redirect)
|
||||
log.Error("Action(%s): %v", ctx.PathParam("action"), err)
|
||||
ctx.JSONError(err.Error()) // FIXME: legacy logic, errors are handled together, it's not right, need to distinguish between different errors
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package org
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
shared_mention "code.gitea.io/gitea/routers/web/shared/mention"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
// GetMentionsInOwner returns JSON data for mention autocomplete on owner-level pages.
|
||||
func GetMentionsInOwner(ctx *context.Context) {
|
||||
// for individual users, we don't have a concept of "mentionable" users or teams, so just return an empty list
|
||||
if !ctx.ContextUser.IsOrganization() {
|
||||
ctx.JSON(http.StatusOK, []shared_mention.Mention{})
|
||||
return
|
||||
}
|
||||
|
||||
// for org, return members and teams
|
||||
c := shared_mention.NewCollector()
|
||||
org := organization.OrgFromUser(ctx.ContextUser)
|
||||
|
||||
// Get org members
|
||||
members, _, err := org.GetMembers(ctx, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetMembers", err)
|
||||
return
|
||||
}
|
||||
c.AddUsers(ctx, members)
|
||||
|
||||
// Get mentionable teams
|
||||
if err := c.AddMentionableTeams(ctx, ctx.Doer, ctx.ContextUser); err != nil {
|
||||
ctx.ServerError("AddMentionableTeams", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, util.SliceNilAsEmpty(c.Result))
|
||||
}
|
||||
@@ -65,13 +65,13 @@ func CreatePost(ctx *context.Context) {
|
||||
ctx.Data["Err_OrgName"] = true
|
||||
switch {
|
||||
case user_model.IsErrUserAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.org_name_been_taken"), tplCreateOrg, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.org_name_been_taken"), tplCreateOrg, &form)
|
||||
case db.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(db.ErrNameReserved).Name), tplCreateOrg, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("org.form.name_reserved", err.(db.ErrNameReserved).Name), tplCreateOrg, &form)
|
||||
case db.IsErrNamePatternNotAllowed(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
|
||||
case organization.IsErrUserNotAllowedCreateOrg(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
|
||||
default:
|
||||
ctx.ServerError("CreateOrganization", err)
|
||||
}
|
||||
|
||||
@@ -11,9 +11,8 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
org_model "code.gitea.io/gitea/models/organization"
|
||||
project_model "code.gitea.io/gitea/models/project"
|
||||
attachment_model "code.gitea.io/gitea/models/repo"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
@@ -25,6 +24,8 @@ import (
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
project_service "code.gitea.io/gitea/services/projects"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -112,12 +113,7 @@ func Projects(ctx *context.Context) {
|
||||
project.RenderedContent = renderUtils.MarkdownToHtml(project.Description)
|
||||
}
|
||||
|
||||
numPages := 0
|
||||
if total > 0 {
|
||||
numPages = (int(total) - 1/setting.UI.IssuePagingNum)
|
||||
}
|
||||
|
||||
pager := context.NewPagination(int(total), setting.UI.IssuePagingNum, page, numPages)
|
||||
pager := context.NewPagination(total, setting.UI.IssuePagingNum, page, 5)
|
||||
pager.AddParamFromRequest(ctx.Req)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
@@ -332,12 +328,26 @@ func ViewProject(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
assigneeID := ctx.FormString("assignee")
|
||||
milestoneID := ctx.FormInt64("milestone")
|
||||
|
||||
// Prepare milestone IDs for filtering
|
||||
var milestoneIDs []int64
|
||||
if milestoneID > 0 {
|
||||
milestoneIDs = []int64{milestoneID}
|
||||
} else if milestoneID == db.NoConditionID {
|
||||
milestoneIDs = []int64{db.NoConditionID}
|
||||
}
|
||||
|
||||
opts := issues_model.IssuesOptions{
|
||||
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||
AssigneeID: assigneeID,
|
||||
Owner: project.Owner,
|
||||
Doer: ctx.Doer,
|
||||
LabelIDs: preparedLabelFilter.SelectedLabelIDs,
|
||||
AssigneeID: assigneeID,
|
||||
MilestoneIDs: milestoneIDs,
|
||||
Owner: project.Owner,
|
||||
}
|
||||
if ctx.Doer != nil {
|
||||
opts.Doer = ctx.Doer
|
||||
} else {
|
||||
opts.AllPublic = true
|
||||
}
|
||||
|
||||
issuesMap, err := project_service.LoadIssuesFromProject(ctx, project, &opts)
|
||||
@@ -350,10 +360,10 @@ func ViewProject(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if project.CardType != project_model.CardTypeTextOnly {
|
||||
issuesAttachmentMap := make(map[int64][]*attachment_model.Attachment)
|
||||
issuesAttachmentMap := make(map[int64][]*repo_model.Attachment)
|
||||
for _, issuesList := range issuesMap {
|
||||
for _, issue := range issuesList {
|
||||
if issueAttachment, err := attachment_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil {
|
||||
if issueAttachment, err := repo_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil {
|
||||
issuesAttachmentMap[issue.ID] = issueAttachment
|
||||
}
|
||||
}
|
||||
@@ -411,10 +421,46 @@ func ViewProject(ctx *context.Context) {
|
||||
ctx.Data["Labels"] = labels
|
||||
ctx.Data["NumLabels"] = len(labels)
|
||||
|
||||
// Get milestones for filtering
|
||||
// For organization projects, we need to get milestones from all repos the user has access to
|
||||
var milestones issues_model.MilestoneList
|
||||
if project.RepoID > 0 {
|
||||
// Repo-specific project
|
||||
milestones, err = db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
|
||||
RepoID: project.RepoID,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepoMilestones", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Organization-wide project - get milestones from all organization repos
|
||||
// but only from repositories the current user can access.
|
||||
// Use RepoCond with a subquery to avoid materializing all repo IDs in memory
|
||||
// which can hit SQL parameter limits for orgs with many repos.
|
||||
accessCond := repo_model.AccessibleRepositoryCondition(ctx.Doer, unit.TypeIssues)
|
||||
repoCond := builder.And(
|
||||
builder.Eq{"owner_id": project.OwnerID},
|
||||
accessCond,
|
||||
)
|
||||
milestones, err = db.Find[issues_model.Milestone](ctx, issues_model.FindMilestoneOptions{
|
||||
RepoCond: repoCond,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOrgMilestones", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
openMilestones, closedMilestones := milestones.SplitByOpenClosed()
|
||||
ctx.Data["OpenMilestones"] = openMilestones
|
||||
ctx.Data["ClosedMilestones"] = closedMilestones
|
||||
ctx.Data["MilestoneID"] = milestoneID
|
||||
|
||||
// Get assignees.
|
||||
assigneeUsers, err := org_model.GetOrgAssignees(ctx, project.OwnerID)
|
||||
assigneeUsers, err := project_service.LoadIssuesAssigneesForProject(ctx, issuesMap)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRepoAssignees", err)
|
||||
ctx.ServerError("LoadIssuesAssigneesForProject", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Assignees"] = shared_user.MakeSelfOnTop(ctx.Doer, assigneeUsers)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package org
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
@@ -69,24 +70,25 @@ func SettingsPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
org := ctx.Org.Organization
|
||||
|
||||
if form.Email != "" {
|
||||
if err := user_service.ReplacePrimaryEmailAddress(ctx, org.AsUser(), form.Email); err != nil {
|
||||
if err := org_service.UpdateOrgEmailAddress(ctx, org, form.Email); err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) {
|
||||
ctx.Data["Err_Email"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplSettingsOptions, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.email_invalid"), tplSettingsOptions, &form)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("UpdateOrgEmailAddress", err)
|
||||
return
|
||||
}
|
||||
|
||||
opts := &user_service.UpdateOptions{
|
||||
FullName: optional.Some(form.FullName),
|
||||
Description: optional.Some(form.Description),
|
||||
Website: optional.Some(form.Website),
|
||||
Location: optional.Some(form.Location),
|
||||
RepoAdminChangeTeamAccess: optional.Some(form.RepoAdminChangeTeamAccess),
|
||||
FullName: optional.FromPtr(form.FullName),
|
||||
Description: optional.FromPtr(form.Description),
|
||||
Website: optional.FromPtr(form.Website),
|
||||
Location: optional.FromPtr(form.Location),
|
||||
RepoAdminChangeTeamAccess: optional.FromPtr(form.RepoAdminChangeTeamAccess),
|
||||
}
|
||||
if ctx.Doer.IsAdmin {
|
||||
opts.MaxRepoCreation = optional.Some(form.MaxRepoCreation)
|
||||
opts.MaxRepoCreation = optional.FromPtr(form.MaxRepoCreation)
|
||||
}
|
||||
|
||||
if err := user_service.UpdateUser(ctx, org.AsUser(), opts); err != nil {
|
||||
@@ -213,7 +215,7 @@ func SettingsRenamePost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := user_service.RenameUser(ctx, ctx.Org.Organization.AsUser(), newOrgName); err != nil {
|
||||
if err := user_service.RenameUser(ctx, ctx.Org.Organization.AsUser(), newOrgName, ctx.Doer); err != nil {
|
||||
if user_model.IsErrUserAlreadyExist(err) {
|
||||
ctx.JSONError(ctx.Tr("org.form.name_been_taken", newOrgName))
|
||||
} else if db.IsErrNameReserved(err) {
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
func RedirectToDefaultSetting(ctx *context.Context) {
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/settings/actions/runners")
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func OAuth2ApplicationEdit(ctx *context.Context) {
|
||||
|
||||
// OAuthApplicationsRegenerateSecret handles the post request for regenerating the secret
|
||||
func OAuthApplicationsRegenerateSecret(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["Title"] = ctx.Tr("settings_title")
|
||||
ctx.Data["PageIsOrgSettings"] = true
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ func NewTeamPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if t.AccessMode < perm.AccessModeAdmin && len(unitPerms) == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ func NewTeamPost(ctx *context.Context) {
|
||||
ctx.Data["Err_TeamName"] = true
|
||||
switch {
|
||||
case org_model.IsErrTeamAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||
default:
|
||||
ctx.ServerError("NewTeam", err)
|
||||
}
|
||||
@@ -536,7 +536,7 @@ func EditTeamPost(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if t.AccessMode < perm.AccessModeAdmin && len(unitPerms) == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.team_no_units_error"), tplTeamNew, &form)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -544,7 +544,7 @@ func EditTeamPost(ctx *context.Context) {
|
||||
ctx.Data["Err_TeamName"] = true
|
||||
switch {
|
||||
case org_model.IsErrTeamAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("form.team_name_been_taken"), tplTeamNew, &form)
|
||||
default:
|
||||
ctx.ServerError("UpdateTeam", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user