Skip to content

Commit b758321

Browse files
authored
Merge branch 'main' into fullname-search
2 parents aded8c1 + ac8d71f commit b758321

33 files changed

+817
-369
lines changed

models/issues/pull.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,10 +660,10 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest,
660660

661661
// GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request
662662
// By poster id.
663-
func GetAllUnmergedAgitPullRequestByPoster(uid int64) ([]*PullRequest, error) {
663+
func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*PullRequest, error) {
664664
pulls := make([]*PullRequest, 0, 10)
665665

666-
err := db.GetEngine(db.DefaultContext).
666+
err := db.GetEngine(ctx).
667667
Where("has_merged=? AND flow = ? AND issue.is_closed=? AND issue.poster_id=?",
668668
false, PullRequestFlowAGit, false, uid).
669669
Join("INNER", "issue", "issue.id=pull_request.issue_id").

models/user/user.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -753,13 +753,13 @@ func VerifyUserActiveCode(code string) (user *User) {
753753
}
754754

755755
// ChangeUserName changes all corresponding setting from old user name to new one.
756-
func ChangeUserName(u *User, newUserName string) (err error) {
756+
func ChangeUserName(ctx context.Context, u *User, newUserName string) (err error) {
757757
oldUserName := u.Name
758758
if err = IsUsableUsername(newUserName); err != nil {
759759
return err
760760
}
761761

762-
ctx, committer, err := db.TxContext(db.DefaultContext)
762+
ctx, committer, err := db.TxContext(ctx)
763763
if err != nil {
764764
return err
765765
}

modules/actions/workflows.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,32 @@ func ListWorkflows(commit *git.Commit) (git.Entries, error) {
4444
return ret, nil
4545
}
4646

47+
func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) {
48+
f, err := entry.Blob().DataAsync()
49+
if err != nil {
50+
return nil, err
51+
}
52+
content, err := io.ReadAll(f)
53+
_ = f.Close()
54+
if err != nil {
55+
return nil, err
56+
}
57+
return content, nil
58+
}
59+
60+
func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
61+
workflow, err := model.ReadWorkflow(bytes.NewReader(content))
62+
if err != nil {
63+
return nil, err
64+
}
65+
events, err := jobparser.ParseRawOn(&workflow.RawOn)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
return events, nil
71+
}
72+
4773
func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) (map[string][]byte, error) {
4874
entries, err := ListWorkflows(commit)
4975
if err != nil {
@@ -52,21 +78,11 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
5278

5379
workflows := make(map[string][]byte, len(entries))
5480
for _, entry := range entries {
55-
f, err := entry.Blob().DataAsync()
56-
if err != nil {
57-
return nil, err
58-
}
59-
content, err := io.ReadAll(f)
60-
_ = f.Close()
81+
content, err := GetContentFromEntry(entry)
6182
if err != nil {
6283
return nil, err
6384
}
64-
workflow, err := model.ReadWorkflow(bytes.NewReader(content))
65-
if err != nil {
66-
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
67-
continue
68-
}
69-
events, err := jobparser.ParseRawOn(&workflow.RawOn)
85+
events, err := GetEventsFromContent(content)
7086
if err != nil {
7187
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
7288
continue

modules/structs/user.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,12 @@ type UserSettingsOptions struct {
9393
HideEmail *bool `json:"hide_email"`
9494
HideActivity *bool `json:"hide_activity"`
9595
}
96+
97+
// RenameUserOption options when renaming a user
98+
type RenameUserOption struct {
99+
// New username for this user. This name cannot be in use yet by any other user.
100+
//
101+
// required: true
102+
// unique: true
103+
NewName string `json:"new_username" binding:"Required"`
104+
}

modules/structs/user_email.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2015 The Gogs Authors. All rights reserved.
2+
// Copyright 2023 The Gitea Authors. All rights reserved.
23
// SPDX-License-Identifier: MIT
34

45
package structs
@@ -9,6 +10,8 @@ type Email struct {
910
Email string `json:"email"`
1011
Verified bool `json:"verified"`
1112
Primary bool `json:"primary"`
13+
UserID int64 `json:"user_id"`
14+
UserName string `json:"username"`
1215
}
1316

1417
// CreateEmailOption options when creating email addresses

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,5 +3360,7 @@ runs.open_tab = %d Open
33603360
runs.closed_tab = %d Closed
33613361
runs.commit = Commit
33623362
runs.pushed_by = Pushed by
3363+
runs.valid_workflow_helper = Workflow config file is valid.
3364+
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
33633365
33643366
need_approval_desc = Need approval to run workflows for fork pull request.

routers/api/v1/admin/email.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package admin
5+
6+
import (
7+
"net/http"
8+
9+
user_model "code.gitea.io/gitea/models/user"
10+
"code.gitea.io/gitea/modules/context"
11+
api "code.gitea.io/gitea/modules/structs"
12+
"code.gitea.io/gitea/routers/api/v1/utils"
13+
"code.gitea.io/gitea/services/convert"
14+
)
15+
16+
// GetAllEmails
17+
func GetAllEmails(ctx *context.APIContext) {
18+
// swagger:operation GET /admin/emails admin adminGetAllEmails
19+
// ---
20+
// summary: List all emails
21+
// produces:
22+
// - application/json
23+
// parameters:
24+
// - name: page
25+
// in: query
26+
// description: page number of results to return (1-based)
27+
// type: integer
28+
// - name: limit
29+
// in: query
30+
// description: page size of results
31+
// type: integer
32+
// responses:
33+
// "200":
34+
// "$ref": "#/responses/EmailList"
35+
// "403":
36+
// "$ref": "#/responses/forbidden"
37+
38+
listOptions := utils.GetListOptions(ctx)
39+
40+
emails, maxResults, err := user_model.SearchEmails(&user_model.SearchEmailOptions{
41+
Keyword: ctx.Params(":email"),
42+
ListOptions: listOptions,
43+
})
44+
if err != nil {
45+
ctx.Error(http.StatusInternalServerError, "GetAllEmails", err)
46+
return
47+
}
48+
49+
results := make([]*api.Email, len(emails))
50+
for i := range emails {
51+
results[i] = convert.ToEmailSearch(emails[i])
52+
}
53+
54+
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
55+
ctx.SetTotalCountHeader(maxResults)
56+
ctx.JSON(http.StatusOK, &results)
57+
}
58+
59+
// SearchEmail
60+
func SearchEmail(ctx *context.APIContext) {
61+
// swagger:operation GET /admin/emails/search admin adminSearchEmails
62+
// ---
63+
// summary: Search all emails
64+
// produces:
65+
// - application/json
66+
// parameters:
67+
// - name: q
68+
// in: query
69+
// description: keyword
70+
// type: string
71+
// - name: page
72+
// in: query
73+
// description: page number of results to return (1-based)
74+
// type: integer
75+
// - name: limit
76+
// in: query
77+
// description: page size of results
78+
// type: integer
79+
// responses:
80+
// "200":
81+
// "$ref": "#/responses/EmailList"
82+
// "403":
83+
// "$ref": "#/responses/forbidden"
84+
85+
ctx.SetParams(":email", ctx.FormTrim("q"))
86+
GetAllEmails(ctx)
87+
}

routers/api/v1/admin/user.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,3 +461,61 @@ func GetAllUsers(ctx *context.APIContext) {
461461
ctx.SetTotalCountHeader(maxResults)
462462
ctx.JSON(http.StatusOK, &results)
463463
}
464+
465+
// RenameUser api for renaming a user
466+
func RenameUser(ctx *context.APIContext) {
467+
// swagger:operation POST /admin/users/{username}/rename admin adminRenameUser
468+
// ---
469+
// summary: Rename a user
470+
// produces:
471+
// - application/json
472+
// parameters:
473+
// - name: username
474+
// in: path
475+
// description: existing username of user
476+
// type: string
477+
// required: true
478+
// - name: body
479+
// in: body
480+
// required: true
481+
// schema:
482+
// "$ref": "#/definitions/RenameUserOption"
483+
// responses:
484+
// "204":
485+
// "$ref": "#/responses/empty"
486+
// "403":
487+
// "$ref": "#/responses/forbidden"
488+
// "422":
489+
// "$ref": "#/responses/validationError"
490+
491+
if ctx.ContextUser.IsOrganization() {
492+
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("%s is an organization not a user", ctx.ContextUser.Name))
493+
return
494+
}
495+
496+
newName := web.GetForm(ctx).(*api.RenameUserOption).NewName
497+
498+
if strings.EqualFold(newName, ctx.ContextUser.Name) {
499+
// Noop as username is not changed
500+
ctx.Status(http.StatusNoContent)
501+
return
502+
}
503+
504+
// Check if user name has been changed
505+
if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil {
506+
switch {
507+
case user_model.IsErrUserAlreadyExist(err):
508+
ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken"))
509+
case db.IsErrNameReserved(err):
510+
ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName))
511+
case db.IsErrNamePatternNotAllowed(err):
512+
ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_pattern_not_allowed", newName))
513+
case db.IsErrNameCharsNotAllowed(err):
514+
ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_chars_not_allowed", newName))
515+
default:
516+
ctx.ServerError("ChangeUserName", err)
517+
}
518+
return
519+
}
520+
ctx.Status(http.StatusNoContent)
521+
}

routers/api/v1/api.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,13 @@ func Routes(ctx gocontext.Context) *web.Route {
12571257
m.Get("/orgs", org.ListUserOrgs)
12581258
m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg)
12591259
m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo)
1260+
m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser)
12601261
}, context_service.UserAssignmentAPI())
12611262
})
1263+
m.Group("/emails", func() {
1264+
m.Get("", admin.GetAllEmails)
1265+
m.Get("/search", admin.SearchEmail)
1266+
})
12621267
m.Group("/unadopted", func() {
12631268
m.Get("", admin.ListUnadoptedRepositories)
12641269
m.Post("/{username}/{reponame}", admin.AdoptRepository)

routers/api/v1/swagger/options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ type swaggerParameterBodies struct {
4848
// in:body
4949
CreateKeyOption api.CreateKeyOption
5050

51+
// in:body
52+
RenameUserOption api.RenameUserOption
53+
5154
// in:body
5255
CreateLabelOption api.CreateLabelOption
5356
// in:body

routers/web/org/setting.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func SettingsPost(ctx *context.Context) {
7979
ctx.Data["OrgName"] = true
8080
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form)
8181
return
82-
} else if err = user_model.ChangeUserName(org.AsUser(), form.Name); err != nil {
82+
} else if err = user_model.ChangeUserName(ctx, org.AsUser(), form.Name); err != nil {
8383
switch {
8484
case db.IsErrNameReserved(err):
8585
ctx.Data["OrgName"] = true

routers/web/repo/actions/actions.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ const (
2323
tplViewActions base.TplName = "repo/actions/view"
2424
)
2525

26+
type Workflow struct {
27+
Entry git.TreeEntry
28+
IsInvalid bool
29+
ErrMsg string
30+
}
31+
2632
// MustEnableActions check if actions are enabled in settings
2733
func MustEnableActions(ctx *context.Context) {
2834
if !setting.Actions.Enabled {
@@ -47,7 +53,7 @@ func List(ctx *context.Context) {
4753
ctx.Data["Title"] = ctx.Tr("actions.actions")
4854
ctx.Data["PageIsActions"] = true
4955

50-
var workflows git.Entries
56+
var workflows []Workflow
5157
if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil {
5258
ctx.Error(http.StatusInternalServerError, err.Error())
5359
return
@@ -62,13 +68,27 @@ func List(ctx *context.Context) {
6268
ctx.Error(http.StatusInternalServerError, err.Error())
6369
return
6470
}
65-
workflows, err = actions.ListWorkflows(commit)
71+
entries, err := actions.ListWorkflows(commit)
6672
if err != nil {
6773
ctx.Error(http.StatusInternalServerError, err.Error())
6874
return
6975
}
76+
workflows = make([]Workflow, 0, len(entries))
77+
for _, entry := range entries {
78+
workflow := Workflow{Entry: *entry}
79+
content, err := actions.GetContentFromEntry(entry)
80+
if err != nil {
81+
ctx.Error(http.StatusInternalServerError, err.Error())
82+
return
83+
}
84+
_, err = actions.GetEventsFromContent(content)
85+
if err != nil {
86+
workflow.IsInvalid = true
87+
workflow.ErrMsg = err.Error()
88+
}
89+
workflows = append(workflows, workflow)
90+
}
7091
}
71-
7292
ctx.Data["workflows"] = workflows
7393
ctx.Data["RepoLink"] = ctx.Repo.Repository.Link()
7494

0 commit comments

Comments
 (0)