Skip to content

Commit d3d583f

Browse files
committed
Merge remote-tracking branch 'upstream/main'
* upstream/main: feat(API): update and delete secret for managing organization secrets (go-gitea#26660) Remove ref name in PR commits page (go-gitea#25876) Modify the content format of the Feishu webhook (go-gitea#25106) Handle "comment form combo editor init" more gracefully (go-gitea#26688) Prefer variables over subprocesses (go-gitea#26690) Fix archived unix time when archiving the label (go-gitea#26681) Make "link-action" backend code respond correct JSON content (go-gitea#26680) Fix doubled box-shadow in branch dropdown menu (go-gitea#26678) Refactor toast module (go-gitea#26677)
2 parents 95a1333 + b62c8e7 commit d3d583f

File tree

28 files changed

+422
-61
lines changed

28 files changed

+422
-61
lines changed

docs/content/usage/actions/act-runner.en-us.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ docker run --entrypoint="" --rm -it gitea/act_runner:latest act_runner generate-
8181
When you are using the docker image, you can specify the configuration file by using the `CONFIG_FILE` environment variable. Make sure that the file is mounted into the container as a volume:
8282

8383
```bash
84-
docker run -v $(pwd)/config.yaml:/config.yaml -e CONFIG_FILE=/config.yaml ...
84+
docker run -v $PWD/config.yaml:/config.yaml -e CONFIG_FILE=/config.yaml ...
8585
```
8686

8787
You may notice the commands above are both incomplete, because it is not the time to run the act runner yet.
@@ -157,8 +157,8 @@ If you are using the docker image, behaviour will be slightly different. Registr
157157

158158
```bash
159159
docker run \
160-
-v $(pwd)/config.yaml:/config.yaml \
161-
-v $(pwd)/data:/data \
160+
-v $PWD/config.yaml:/config.yaml \
161+
-v $PWD/data:/data \
162162
-v /var/run/docker.sock:/var/run/docker.sock \
163163
-e CONFIG_FILE=/config.yaml \
164164
-e GITEA_INSTANCE_URL=<instance_url> \

models/issues/label.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,11 @@ func (l *Label) CalOpenIssues() {
113113

114114
// SetArchived set the label as archived
115115
func (l *Label) SetArchived(isArchived bool) {
116-
if isArchived && l.ArchivedUnix.IsZero() {
117-
l.ArchivedUnix = timeutil.TimeStampNow()
118-
} else {
116+
if !isArchived {
119117
l.ArchivedUnix = timeutil.TimeStamp(0)
118+
} else if isArchived && l.ArchivedUnix.IsZero() {
119+
// Only change the date when it is newly archived.
120+
l.ArchivedUnix = timeutil.TimeStampNow()
120121
}
121122
}
122123

models/secret/secret.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ package secret
66
import (
77
"context"
88
"errors"
9+
"fmt"
910
"strings"
1011

1112
"code.gitea.io/gitea/models/db"
1213
secret_module "code.gitea.io/gitea/modules/secret"
1314
"code.gitea.io/gitea/modules/setting"
1415
"code.gitea.io/gitea/modules/timeutil"
16+
"code.gitea.io/gitea/modules/util"
1517

1618
"xorm.io/builder"
1719
)
@@ -26,6 +28,25 @@ type Secret struct {
2628
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
2729
}
2830

31+
// ErrSecretNotFound represents a "secret not found" error.
32+
type ErrSecretNotFound struct {
33+
Name string
34+
}
35+
36+
// IsErrSecretNotFound checks if an error is a ErrSecretNotFound.
37+
func IsErrSecretNotFound(err error) bool {
38+
_, ok := err.(ErrSecretNotFound)
39+
return ok
40+
}
41+
42+
func (err ErrSecretNotFound) Error() string {
43+
return fmt.Sprintf("secret was not found [name: %s]", err.Name)
44+
}
45+
46+
func (err ErrSecretNotFound) Unwrap() error {
47+
return util.ErrNotExist
48+
}
49+
2950
// newSecret Creates a new already encrypted secret
3051
func newSecret(ownerID, repoID int64, name, data string) *Secret {
3152
return &Secret{
@@ -93,3 +114,49 @@ func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error
93114
func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) {
94115
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret))
95116
}
117+
118+
// UpdateSecret changes org or user reop secret.
119+
func UpdateSecret(ctx context.Context, orgID, repoID int64, name, data string) error {
120+
sc := new(Secret)
121+
name = strings.ToUpper(name)
122+
has, err := db.GetEngine(ctx).
123+
Where("owner_id=?", orgID).
124+
And("repo_id=?", repoID).
125+
And("name=?", name).
126+
Get(sc)
127+
if err != nil {
128+
return err
129+
} else if !has {
130+
return ErrSecretNotFound{Name: name}
131+
}
132+
133+
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
134+
if err != nil {
135+
return err
136+
}
137+
138+
sc.Data = encrypted
139+
_, err = db.GetEngine(ctx).ID(sc.ID).Cols("data").Update(sc)
140+
return err
141+
}
142+
143+
// DeleteSecret deletes secret from an organization.
144+
func DeleteSecret(ctx context.Context, orgID, repoID int64, name string) error {
145+
sc := new(Secret)
146+
has, err := db.GetEngine(ctx).
147+
Where("owner_id=?", orgID).
148+
And("repo_id=?", repoID).
149+
And("name=?", strings.ToUpper(name)).
150+
Get(sc)
151+
if err != nil {
152+
return err
153+
} else if !has {
154+
return ErrSecretNotFound{Name: name}
155+
}
156+
157+
if _, err := db.GetEngine(ctx).ID(sc.ID).Delete(new(Secret)); err != nil {
158+
return fmt.Errorf("Delete: %w", err)
159+
}
160+
161+
return nil
162+
}

modules/structs/secret.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,12 @@ type CreateSecretOption struct {
2525
// Data of the secret to create
2626
Data string `json:"data" binding:"Required"`
2727
}
28+
29+
// UpdateSecretOption options when updating secret
30+
// swagger:model
31+
type UpdateSecretOption struct {
32+
// Data of the secret to update
33+
//
34+
// required: true
35+
Data string `json:"data" binding:"Required"`
36+
}

routers/api/v1/api.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,9 @@ func Routes() *web.Route {
13011301
m.Group("/actions/secrets", func() {
13021302
m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets)
13031303
m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateSecretOption{}), org.CreateOrgSecret)
1304+
m.Combo("/{secretname}").
1305+
Put(reqToken(), reqOrgOwnership(), bind(api.UpdateSecretOption{}), org.UpdateOrgSecret).
1306+
Delete(reqToken(), reqOrgOwnership(), org.DeleteOrgSecret)
13041307
})
13051308
m.Group("/public_members", func() {
13061309
m.Get("", org.ListPublicMembers)

routers/api/v1/org/action.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ func CreateOrgSecret(ctx *context.APIContext) {
103103
// "403":
104104
// "$ref": "#/responses/forbidden"
105105
opt := web.GetForm(ctx).(*api.CreateSecretOption)
106+
if err := actions.NameRegexMatch(opt.Name); err != nil {
107+
ctx.Error(http.StatusBadRequest, "CreateOrgSecret", err)
108+
return
109+
}
106110
s, err := secret_model.InsertEncryptedSecret(
107111
ctx, ctx.Org.Organization.ID, 0, opt.Name, actions.ReserveLineBreakForTextarea(opt.Data),
108112
)
@@ -113,3 +117,90 @@ func CreateOrgSecret(ctx *context.APIContext) {
113117

114118
ctx.JSON(http.StatusCreated, convert.ToSecret(s))
115119
}
120+
121+
// UpdateOrgSecret update one secret of the organization
122+
func UpdateOrgSecret(ctx *context.APIContext) {
123+
// swagger:operation PUT /orgs/{org}/actions/secrets/{secretname} organization updateOrgSecret
124+
// ---
125+
// summary: Update a secret value in an organization
126+
// consumes:
127+
// - application/json
128+
// produces:
129+
// - application/json
130+
// parameters:
131+
// - name: org
132+
// in: path
133+
// description: name of organization
134+
// type: string
135+
// required: true
136+
// - name: secretname
137+
// in: path
138+
// description: name of the secret
139+
// type: string
140+
// required: true
141+
// - name: body
142+
// in: body
143+
// schema:
144+
// "$ref": "#/definitions/UpdateSecretOption"
145+
// responses:
146+
// "204":
147+
// description: update one secret of the organization
148+
// "403":
149+
// "$ref": "#/responses/forbidden"
150+
secretName := ctx.Params(":secretname")
151+
opt := web.GetForm(ctx).(*api.UpdateSecretOption)
152+
err := secret_model.UpdateSecret(
153+
ctx, ctx.Org.Organization.ID, 0, secretName, opt.Data,
154+
)
155+
if secret_model.IsErrSecretNotFound(err) {
156+
ctx.NotFound(err)
157+
return
158+
}
159+
if err != nil {
160+
ctx.Error(http.StatusInternalServerError, "UpdateSecret", err)
161+
return
162+
}
163+
164+
ctx.Status(http.StatusNoContent)
165+
}
166+
167+
// DeleteOrgSecret delete one secret of the organization
168+
func DeleteOrgSecret(ctx *context.APIContext) {
169+
// swagger:operation DELETE /orgs/{org}/actions/secrets/{secretname} organization deleteOrgSecret
170+
// ---
171+
// summary: Delete a secret in an organization
172+
// consumes:
173+
// - application/json
174+
// produces:
175+
// - application/json
176+
// parameters:
177+
// - name: org
178+
// in: path
179+
// description: name of organization
180+
// type: string
181+
// required: true
182+
// - name: secretname
183+
// in: path
184+
// description: name of the secret
185+
// type: string
186+
// required: true
187+
// responses:
188+
// "204":
189+
// description: delete one secret of the organization
190+
// "403":
191+
// "$ref": "#/responses/forbidden"
192+
secretName := ctx.Params(":secretname")
193+
err := secret_model.DeleteSecret(
194+
ctx, ctx.Org.Organization.ID, 0, secretName,
195+
)
196+
if secret_model.IsErrSecretNotFound(err) {
197+
ctx.NotFound(err)
198+
return
199+
}
200+
if err != nil {
201+
ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
202+
return
203+
}
204+
205+
ctx.Status(http.StatusNoContent)
206+
}

routers/api/v1/swagger/options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,7 @@ type swaggerParameterBodies struct {
190190

191191
// in:body
192192
CreateSecretOption api.CreateSecretOption
193+
194+
// in:body
195+
UpdateSecretOption api.UpdateSecretOption
193196
}

routers/web/admin/users.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,5 +480,5 @@ func DeleteAvatar(ctx *context.Context) {
480480
ctx.Flash.Error(err.Error())
481481
}
482482

483-
ctx.Redirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
483+
ctx.JSONRedirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
484484
}

routers/web/org/setting.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ func SettingsDeleteAvatar(ctx *context.Context) {
156156
ctx.Flash.Error(err.Error())
157157
}
158158

159-
ctx.Redirect(ctx.Org.OrgLink + "/settings")
159+
ctx.JSONRedirect(ctx.Org.OrgLink + "/settings")
160160
}
161161

162162
// SettingsDelete response for deleting an organization

routers/web/repo/commit.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ func Commits(ctx *context.Context) {
8181
ctx.Data["Username"] = ctx.Repo.Owner.Name
8282
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
8383
ctx.Data["CommitCount"] = commitsCount
84-
ctx.Data["RefName"] = ctx.Repo.RefName
8584

8685
pager := context.NewPagination(int(commitsCount), pageSize, page, 5)
8786
pager.SetDefaultParams(ctx)
@@ -157,7 +156,7 @@ func Graph(ctx *context.Context) {
157156
ctx.Data["Username"] = ctx.Repo.Owner.Name
158157
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
159158
ctx.Data["CommitCount"] = commitsCount
160-
ctx.Data["RefName"] = ctx.Repo.RefName
159+
161160
paginator := context.NewPagination(int(graphCommitsCount), setting.UI.GraphMaxCommitNum, page, 5)
162161
paginator.AddParam(ctx, "mode", "Mode")
163162
paginator.AddParam(ctx, "hide-pr-refs", "HidePRRefs")
@@ -203,7 +202,6 @@ func SearchCommits(ctx *context.Context) {
203202
}
204203
ctx.Data["Username"] = ctx.Repo.Owner.Name
205204
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
206-
ctx.Data["RefName"] = ctx.Repo.RefName
207205
ctx.HTML(http.StatusOK, tplCommits)
208206
}
209207

@@ -247,7 +245,6 @@ func FileHistory(ctx *context.Context) {
247245
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
248246
ctx.Data["FileName"] = fileName
249247
ctx.Data["CommitCount"] = commitsCount
250-
ctx.Data["RefName"] = ctx.Repo.RefName
251248

252249
pager := context.NewPagination(int(commitsCount), setting.Git.CommitsRangeSize, page, 5)
253250
pager.SetDefaultParams(ctx)

routers/web/repo/setting/avatar.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,5 @@ func SettingsDeleteAvatar(ctx *context.Context) {
7272
if err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository); err != nil {
7373
ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err))
7474
}
75-
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
75+
ctx.JSONRedirect(ctx.Repo.RepoLink + "/settings")
7676
}

routers/web/user/setting/profile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func DeleteAvatar(ctx *context.Context) {
194194
ctx.Flash.Error(err.Error())
195195
}
196196

197-
ctx.Redirect(setting.AppSubURL + "/user/settings")
197+
ctx.JSONRedirect(setting.AppSubURL + "/user/settings")
198198
}
199199

200200
// Organization render all the organization of the user

services/webhook/feishu.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,40 @@ func (f *FeishuPayload) Push(p *api.PushPayload) (api.Payloader, error) {
9797

9898
// Issue implements PayloadConvertor Issue method
9999
func (f *FeishuPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
100-
text, issueTitle, attachmentText, _ := getIssuesPayloadInfo(p, noneLinkFormatter, true)
101-
102-
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
100+
title, link, by, operator, result, assignees := getIssuesInfo(p)
101+
var res api.Payloader
102+
if assignees != "" {
103+
if p.Action == api.HookIssueAssigned || p.Action == api.HookIssueUnassigned || p.Action == api.HookIssueMilestoned {
104+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, result, assignees, p.Issue.Body))
105+
} else {
106+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, assignees, p.Issue.Body))
107+
}
108+
} else {
109+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.Issue.Body))
110+
}
111+
return res, nil
103112
}
104113

105114
// IssueComment implements PayloadConvertor IssueComment method
106115
func (f *FeishuPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
107-
text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
108-
109-
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + p.Comment.Body), nil
116+
title, link, by, operator := getIssuesCommentInfo(p)
117+
return newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.Comment.Body)), nil
110118
}
111119

112120
// PullRequest implements PayloadConvertor PullRequest method
113121
func (f *FeishuPayload) PullRequest(p *api.PullRequestPayload) (api.Payloader, error) {
114-
text, issueTitle, attachmentText, _ := getPullRequestPayloadInfo(p, noneLinkFormatter, true)
115-
116-
return newFeishuTextPayload(issueTitle + "\r\n" + text + "\r\n\r\n" + attachmentText), nil
122+
title, link, by, operator, result, assignees := getPullRequestInfo(p)
123+
var res api.Payloader
124+
if assignees != "" {
125+
if p.Action == api.HookIssueAssigned || p.Action == api.HookIssueUnassigned || p.Action == api.HookIssueMilestoned {
126+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, result, assignees, p.PullRequest.Body))
127+
} else {
128+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, assignees, p.PullRequest.Body))
129+
}
130+
} else {
131+
res = newFeishuTextPayload(fmt.Sprintf("%s\n%s\n%s\n%s\n\n%s", title, link, by, operator, p.PullRequest.Body))
132+
}
133+
return res, nil
117134
}
118135

119136
// Review implements PayloadConvertor Review method

0 commit comments

Comments
 (0)