Skip to content

Commit 2095f08

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Set pre-step status to `skipped` if job is skipped (go-gitea#29489) Use a predictiable fork URL to allow forking repositories without providing a repo ID (go-gitea#29519) Adding back missing options to app.example.ini (go-gitea#29511) Refactor the "attachments" sub-template data key to RenderedContent (go-gitea#29517) Rename Str2html to SanitizeHTML and clarify its behavior (go-gitea#29516) Add admin API route for managing user's badges (go-gitea#23106) Refactor some Str2html code (go-gitea#29397) Move migration functions to services layer (go-gitea#29497)
2 parents fe2d7b0 + cee08f6 commit 2095f08

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+946
-384
lines changed

custom/conf/app.example.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,12 @@ LEVEL = Info
956956
;GO_GET_CLONE_URL_PROTOCOL = https
957957
;;
958958
;; Close issues as long as a commit on any branch marks it as fixed
959+
;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
960+
;;
961+
;; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
962+
;ENABLE_PUSH_CREATE_USER = false
963+
;ENABLE_PUSH_CREATE_ORG = false
964+
;;
959965
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
960966
;DISABLED_REPO_UNITS =
961967
;;

docs/content/administration/mail-templates.en-us.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ Please check [Gitea's logs](administration/logging-config.md) for error messages
224224
{{if not (eq .Body "")}}
225225
<h3>Message content</h3>
226226
<hr>
227-
{{.Body | Str2html}}
227+
{{.Body | SanitizeHTML}}
228228
{{end}}
229229
</p>
230230
<hr>
@@ -260,19 +260,19 @@ The template system contains several functions that can be used to further proce
260260
the messages. Here's a list of some of them:
261261

262262
| Name | Parameters | Available | Usage |
263-
| ---------------- | ----------- | --------- | --------------------------------------------------------------------------- |
263+
| ---------------- | ----------- | --------- |-----------------------------------------------------------------------------|
264264
| `AppUrl` | - | Any | Gitea's URL |
265265
| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" |
266266
| `AppDomain` | - | Any | Gitea's host name |
267267
| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed |
268-
| `Str2html` | string | Body only | Sanitizes text by removing any HTML tags from it. |
268+
| `SanitizeHTML` | string | Body only | Sanitizes text by removing any dangerous HTML tags from it. |
269269
| `SafeHTML` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. |
270270

271271
These are _functions_, not metadata, so they have to be used:
272272

273273
```html
274-
Like this: {{Str2html "Escape<my>text"}}
275-
Or this: {{"Escape<my>text" | Str2html}}
274+
Like this: {{SanitizeHTML "Escape<my>text"}}
275+
Or this: {{"Escape<my>text" | SanitizeHTML}}
276276
Or this: {{AppUrl}}
277277
But not like this: {{.AppUrl}}
278278
```

docs/content/administration/mail-templates.zh-cn.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
207207
{{if not (eq .Body "")}}
208208
<h3>消息内容:</h3>
209209
<hr>
210-
{{.Body | Str2html}}
210+
{{.Body | SanitizeHTML}}
211211
{{end}}
212212
</p>
213213
<hr>
@@ -242,20 +242,20 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
242242

243243
模板系统包含一些函数,可用于进一步处理和格式化消息。以下是其中一些函数的列表:
244244

245-
| 函数名 | 参数 | 可用于 | 用法 |
246-
|------------------| ----------- | ------------ | --------------------------------------------------------------------------------- |
247-
| `AppUrl` | - | 任何地方 | Gitea 的 URL |
248-
| `AppName` | - | 任何地方 |`app.ini` 中设置,通常为 "Gitea" |
249-
| `AppDomain` | - | 任何地方 | Gitea 的主机名 |
250-
| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 |
251-
| `Str2html` | string | 仅正文部分 | 通过删除其中的 HTML 标签对文本进行清理 |
252-
| `SafeHTML` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于 `.ReviewComments.RenderedContent` 等字段 |
245+
| 函数名 | 参数 | 可用于 | 用法 |
246+
|------------------| ----------- | ------------ |---------------------------------------------------------|
247+
| `AppUrl` | - | 任何地方 | Gitea 的 URL |
248+
| `AppName` | - | 任何地方 |`app.ini` 中设置,通常为 "Gitea" |
249+
| `AppDomain` | - | 任何地方 | Gitea 的主机名 |
250+
| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 |
251+
| `SanitizeHTML` | string | 仅正文部分 | 通过删除其中的危险 HTML 标签对文本进行清理 |
252+
| `SafeHTML` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于 `.ReviewComments.RenderedContent` 等字段 |
253253

254254
这些都是 _函数_,而不是元数据,因此必须按以下方式使用:
255255

256256
```html
257-
像这样使用: {{Str2html "Escape<my>text"}}
258-
或者这样使用: {{"Escape<my>text" | Str2html}}
257+
像这样使用: {{SanitizeHTML "Escape<my>text"}}
258+
或者这样使用: {{"Escape<my>text" | SanitizeHTML}}
259259
或者这样使用: {{AppUrl}}
260260
但不要像这样使用: {{.AppUrl}}
261261
```

models/issues/comment.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package issues
88
import (
99
"context"
1010
"fmt"
11+
"html/template"
1112
"strconv"
1213
"unicode/utf8"
1314

@@ -259,8 +260,8 @@ type Comment struct {
259260
CommitID int64
260261
Line int64 // - previous line / + proposed line
261262
TreePath string
262-
Content string `xorm:"LONGTEXT"`
263-
RenderedContent string `xorm:"-"`
263+
Content string `xorm:"LONGTEXT"`
264+
RenderedContent template.HTML `xorm:"-"`
264265

265266
// Path represents the 4 lines of code cemented by this comment
266267
Patch string `xorm:"-"`

models/issues/issue.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package issues
77
import (
88
"context"
99
"fmt"
10+
"html/template"
1011
"regexp"
1112
"slices"
1213

@@ -105,7 +106,7 @@ type Issue struct {
105106
OriginalAuthorID int64 `xorm:"index"`
106107
Title string `xorm:"name"`
107108
Content string `xorm:"LONGTEXT"`
108-
RenderedContent string `xorm:"-"`
109+
RenderedContent template.HTML `xorm:"-"`
109110
Labels []*Label `xorm:"-"`
110111
MilestoneID int64 `xorm:"INDEX"`
111112
Milestone *Milestone `xorm:"-"`

models/issues/milestone.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package issues
66
import (
77
"context"
88
"fmt"
9+
"html/template"
910
"strings"
1011

1112
"code.gitea.io/gitea/models/db"
@@ -47,8 +48,8 @@ type Milestone struct {
4748
RepoID int64 `xorm:"INDEX"`
4849
Repo *repo_model.Repository `xorm:"-"`
4950
Name string
50-
Content string `xorm:"TEXT"`
51-
RenderedContent string `xorm:"-"`
51+
Content string `xorm:"TEXT"`
52+
RenderedContent template.HTML `xorm:"-"`
5253
IsClosed bool
5354
NumIssues int
5455
NumClosedIssues int

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ var migrations = []Migration{
558558
NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
559559
// v286 -> v287
560560
NewMigration("Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
561+
// v287 -> v288
562+
NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
561563
}
562564

563565
// GetCurrentDBVersion returns the current db version

models/migrations/v1_22/v287.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_22 //nolint
5+
6+
import (
7+
"xorm.io/xorm"
8+
)
9+
10+
type BadgeUnique struct {
11+
ID int64 `xorm:"pk autoincr"`
12+
Slug string `xorm:"UNIQUE"`
13+
}
14+
15+
func (BadgeUnique) TableName() string {
16+
return "badge"
17+
}
18+
19+
func UseSlugInsteadOfIDForBadges(x *xorm.Engine) error {
20+
type Badge struct {
21+
Slug string
22+
}
23+
24+
err := x.Sync(new(Badge))
25+
if err != nil {
26+
return err
27+
}
28+
29+
sess := x.NewSession()
30+
defer sess.Close()
31+
if err := sess.Begin(); err != nil {
32+
return err
33+
}
34+
35+
_, err = sess.Exec("UPDATE `badge` SET `slug` = `id` Where `slug` IS NULL")
36+
if err != nil {
37+
return err
38+
}
39+
40+
err = sess.Sync(new(BadgeUnique))
41+
if err != nil {
42+
return err
43+
}
44+
45+
return sess.Commit()
46+
}

models/migrations/v1_22/v287_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_22 //nolint
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
10+
"code.gitea.io/gitea/models/migrations/base"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func Test_UpdateBadgeColName(t *testing.T) {
16+
type Badge struct {
17+
ID int64 `xorm:"pk autoincr"`
18+
Description string
19+
ImageURL string
20+
}
21+
22+
// Prepare and load the testing database
23+
x, deferable := base.PrepareTestEnv(t, 0, new(BadgeUnique), new(Badge))
24+
defer deferable()
25+
if x == nil || t.Failed() {
26+
return
27+
}
28+
29+
oldBadges := []Badge{
30+
{ID: 1, Description: "Test Badge 1", ImageURL: "https://example.com/badge1.png"},
31+
{ID: 2, Description: "Test Badge 2", ImageURL: "https://example.com/badge2.png"},
32+
{ID: 3, Description: "Test Badge 3", ImageURL: "https://example.com/badge3.png"},
33+
}
34+
35+
for _, badge := range oldBadges {
36+
_, err := x.Insert(&badge)
37+
assert.NoError(t, err)
38+
}
39+
40+
if err := UseSlugInsteadOfIDForBadges(x); err != nil {
41+
assert.NoError(t, err)
42+
return
43+
}
44+
45+
got := []BadgeUnique{}
46+
if err := x.Table("badge").Asc("id").Find(&got); !assert.NoError(t, err) {
47+
return
48+
}
49+
50+
for i, e := range oldBadges {
51+
got := got[i]
52+
assert.Equal(t, e.ID, got.ID)
53+
assert.Equal(t, fmt.Sprintf("%d", e.ID), got.Slug)
54+
}
55+
56+
// TODO: check if badges have been updated
57+
}

models/project/project.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package project
66
import (
77
"context"
88
"fmt"
9+
"html/template"
910

1011
"code.gitea.io/gitea/models/db"
1112
repo_model "code.gitea.io/gitea/models/repo"
@@ -100,7 +101,7 @@ type Project struct {
100101
CardType CardType
101102
Type Type
102103

103-
RenderedContent string `xorm:"-"`
104+
RenderedContent template.HTML `xorm:"-"`
104105

105106
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
106107
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

models/repo/release.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package repo
77
import (
88
"context"
99
"fmt"
10+
"html/template"
1011
"net/url"
1112
"sort"
1213
"strconv"
@@ -80,7 +81,7 @@ type Release struct {
8081
NumCommits int64
8182
NumCommitsBehind int64 `xorm:"-"`
8283
Note string `xorm:"TEXT"`
83-
RenderedNote string `xorm:"-"`
84+
RenderedNote template.HTML `xorm:"-"`
8485
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
8586
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
8687
IsTag bool `xorm:"NOT NULL DEFAULT false"` // will be true only if the record is a tag and has no related releases

models/user/badge.go

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ package user
55

66
import (
77
"context"
8+
"fmt"
89

910
"code.gitea.io/gitea/models/db"
1011
)
1112

1213
// Badge represents a user badge
1314
type Badge struct {
14-
ID int64 `xorm:"pk autoincr"`
15+
ID int64 `xorm:"pk autoincr"`
16+
Slug string `xorm:"UNIQUE"`
1517
Description string
1618
ImageURL string
1719
}
@@ -39,3 +41,84 @@ func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
3941
count, err := sess.FindAndCount(&badges)
4042
return badges, count, err
4143
}
44+
45+
// CreateBadge creates a new badge.
46+
func CreateBadge(ctx context.Context, badge *Badge) error {
47+
_, err := db.GetEngine(ctx).Insert(badge)
48+
return err
49+
}
50+
51+
// GetBadge returns a badge
52+
func GetBadge(ctx context.Context, slug string) (*Badge, error) {
53+
badge := new(Badge)
54+
has, err := db.GetEngine(ctx).Where("slug=?", slug).Get(badge)
55+
if !has {
56+
return nil, err
57+
}
58+
return badge, err
59+
}
60+
61+
// UpdateBadge updates a badge based on its slug.
62+
func UpdateBadge(ctx context.Context, badge *Badge) error {
63+
_, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Update(badge)
64+
return err
65+
}
66+
67+
// DeleteBadge deletes a badge.
68+
func DeleteBadge(ctx context.Context, badge *Badge) error {
69+
_, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Delete(badge)
70+
return err
71+
}
72+
73+
// AddUserBadge adds a badge to a user.
74+
func AddUserBadge(ctx context.Context, u *User, badge *Badge) error {
75+
return AddUserBadges(ctx, u, []*Badge{badge})
76+
}
77+
78+
// AddUserBadges adds badges to a user.
79+
func AddUserBadges(ctx context.Context, u *User, badges []*Badge) error {
80+
return db.WithTx(ctx, func(ctx context.Context) error {
81+
for _, badge := range badges {
82+
// hydrate badge and check if it exists
83+
has, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Get(badge)
84+
if err != nil {
85+
return err
86+
} else if !has {
87+
return fmt.Errorf("badge with slug %s doesn't exist", badge.Slug)
88+
}
89+
if err := db.Insert(ctx, &UserBadge{
90+
BadgeID: badge.ID,
91+
UserID: u.ID,
92+
}); err != nil {
93+
return err
94+
}
95+
}
96+
return nil
97+
})
98+
}
99+
100+
// RemoveUserBadge removes a badge from a user.
101+
func RemoveUserBadge(ctx context.Context, u *User, badge *Badge) error {
102+
return RemoveUserBadges(ctx, u, []*Badge{badge})
103+
}
104+
105+
// RemoveUserBadges removes badges from a user.
106+
func RemoveUserBadges(ctx context.Context, u *User, badges []*Badge) error {
107+
return db.WithTx(ctx, func(ctx context.Context) error {
108+
for _, badge := range badges {
109+
if _, err := db.GetEngine(ctx).
110+
Join("INNER", "badge", "badge.id = `user_badge`.badge_id").
111+
Where("`user_badge`.user_id=? AND `badge`.slug=?", u.ID, badge.Slug).
112+
Delete(&UserBadge{}); err != nil {
113+
return err
114+
}
115+
}
116+
return nil
117+
})
118+
}
119+
120+
// RemoveAllUserBadges removes all badges from a user.
121+
func RemoveAllUserBadges(ctx context.Context, u *User) error {
122+
_, err := db.GetEngine(ctx).Where("user_id=?", u.ID).Delete(&UserBadge{})
123+
return err
124+
}

0 commit comments

Comments
 (0)