Skip to content

Commit bc4c13b

Browse files
authored
Merge branch 'main' into go-gitea#15981-resolve-conversation-without-page-reload
2 parents 54776c9 + e75e9a0 commit bc4c13b

File tree

199 files changed

+1160
-1167
lines changed

Some content is hidden

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

199 files changed

+1160
-1167
lines changed

.markdownlint.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
commands-show-output: false
22
fenced-code-language: false
33
first-line-h1: false
4-
header-increment: false
4+
heading-increment: false
55
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1}
66
no-alt-text: false
77
no-bare-urls: false
88
no-blanks-blockquote: false
9-
no-emphasis-as-header: false
9+
no-emphasis-as-heading: false
1010
no-empty-links: false
1111
no-hard-tabs: {code_blocks: false}
1212
no-inline-html: false

.stylelintrc.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ rules:
7474
keyframe-declaration-no-important: true
7575
keyframe-selector-notation: null
7676
keyframes-name-pattern: null
77-
length-zero-no-unit: true
77+
length-zero-no-unit: [true, ignore: [custom-properties], ignoreFunctions: [var]]
7878
max-nesting-depth: null
7979
media-feature-name-allowed-list: null
8080
media-feature-name-disallowed-list: null

custom/conf/app.example.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,10 @@ LEVEL = Info
12441244
;; Change the sort type of the explore pages.
12451245
;; Default is "recentupdate", but you also have "alphabetically", "reverselastlogin", "newest", "oldest".
12461246
;EXPLORE_PAGING_DEFAULT_SORT = recentupdate
1247+
;;
1248+
;; The tense all timestamps should be rendered in. Possible values are `absolute` time (i.e. 1970-01-01, 11:59) and `mixed`.
1249+
;; `mixed` means most timestamps are rendered in relative time (i.e. 2 days ago).
1250+
;PREFERRED_TIMESTAMP_TENSE = mixed
12471251

12481252
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12491253
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1525,6 +1529,10 @@ LEVEL = Info
15251529
;; userid = use the userid / sub attribute
15261530
;; nickname = use the nickname attribute
15271531
;; email = use the username part of the email attribute
1532+
;; Note: `nickname` and `email` options will normalize input strings using the following criteria:
1533+
;; - diacritics are removed
1534+
;; - the characters in the set `['´\x60]` are removed
1535+
;; - the characters in the set `[\s~+]` are replaced with `-`
15281536
;USERNAME = nickname
15291537
;;
15301538
;; Update avatar if available from oauth2 provider.

docs/content/administration/config-cheat-sheet.en-us.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
231231
- `ONLY_SHOW_RELEVANT_REPOS`: **false**: Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
232232
A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
233233
- `EXPLORE_PAGING_DEFAULT_SORT`: **recentupdate**: Change the sort type of the explore pages. Valid values are "recentupdate", "alphabetically", "reverselastlogin", "newest" and "oldest"
234+
- `PREFERRED_TIMESTAMP_TENSE`: **mixed**: The tense all timestamps should be rendered in. Possible values are `absolute` time (i.e. 1970-01-01, 11:59) and `mixed`. `mixed` means most timestamps are rendered in relative time (i.e. 2 days ago).
234235

235236
### UI - Admin (`ui.admin`)
236237

@@ -595,9 +596,13 @@ And the following unique queues:
595596
- `OPENID_CONNECT_SCOPES`: **_empty_**: List of additional openid connect scopes. (`openid` is implicitly added)
596597
- `ENABLE_AUTO_REGISTRATION`: **false**: Automatically create user accounts for new oauth2 users.
597598
- `USERNAME`: **nickname**: The source of the username for new oauth2 accounts:
598-
- userid - use the userid / sub attribute
599-
- nickname - use the nickname attribute
600-
- email - use the username part of the email attribute
599+
- `userid` - use the userid / sub attribute
600+
- `nickname` - use the nickname attribute
601+
- `email` - use the username part of the email attribute
602+
- Note: `nickname` and `email` options will normalize input strings using the following criteria:
603+
- diacritics are removed
604+
- the characters in the set `['´\x60]` are removed
605+
- the characters in the set `[\s~+]` are replaced with `-`
601606
- `UPDATE_AVATAR`: **false**: Update avatar if available from oauth2 provider. Update will be performed on each login.
602607
- `ACCOUNT_LINKING`: **login**: How to handle if an account / email already exists:
603608
- disabled - show an error

docs/content/administration/config-cheat-sheet.zh-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ Gitea 创建以下非唯一队列:
987987
- `LAST_UPDATED_MORE_THAN_AGO`: **72h**: 只会尝试回收超过此时间(默认3天)没有尝试过回收的 LFSMetaObject。
988988
- `NUMBER_TO_CHECK_PER_REPO`: **100**: 每个仓库要检查的过期 LFSMetaObject 的最小数量。设置为 `0` 以始终检查所有。
989989

990-
# Git (`git`)
990+
## Git (`git`)
991991

992992
- `PATH`: **""**: Git可执行文件的路径。如果为空,Gitea将在PATH环境中搜索。
993993
- `HOME_PATH`: **%(APP_DATA_PATH)s/home**: Git的HOME目录。

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ require (
121121
mvdan.cc/xurls/v2 v2.5.0
122122
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
123123
xorm.io/builder v0.3.13
124-
xorm.io/xorm v1.3.4
124+
xorm.io/xorm v1.3.6
125125
)
126126

127127
require (

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,5 +1510,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:
15101510
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
15111511
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
15121512
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
1513-
xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI=
1514-
xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
1513+
xorm.io/xorm v1.3.6 h1:hfpWHkDIWWqUi8FRF2H2M9O8lO3Ov47rwFcS9gPzPkU=
1514+
xorm.io/xorm v1.3.6/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=

models/auth/source.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,12 @@ func (opts FindSourcesOptions) ToConds() builder.Cond {
261261
// IsSSPIEnabled returns true if there is at least one activated login
262262
// source of type LoginSSPI
263263
func IsSSPIEnabled(ctx context.Context) bool {
264-
if !db.HasEngine {
265-
return false
266-
}
267-
268264
exist, err := db.Exist[Source](ctx, FindSourcesOptions{
269265
IsActive: util.OptionalBoolTrue,
270266
LoginType: SSPI,
271267
}.ToConds())
272268
if err != nil {
273-
log.Error("Active SSPI Sources: %v", err)
269+
log.Error("IsSSPIEnabled: failed to query active SSPI sources: %v", err)
274270
return false
275271
}
276272
return exist

models/db/engine.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ var (
2727
x *xorm.Engine
2828
tables []any
2929
initFuncs []func() error
30-
31-
// HasEngine specifies if we have a xorm.Engine
32-
HasEngine bool
3330
)
3431

3532
// Engine represents a xorm engine or session.

models/issues/comment.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,14 +1161,9 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
11611161
// UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id
11621162
func UpdateCommentsMigrationsByType(ctx context.Context, tp structs.GitServiceType, originalAuthorID string, posterID int64) error {
11631163
_, err := db.GetEngine(ctx).Table("comment").
1164-
Where(builder.In("issue_id",
1165-
builder.Select("issue.id").
1166-
From("issue").
1167-
InnerJoin("repository", "issue.repo_id = repository.id").
1168-
Where(builder.Eq{
1169-
"repository.original_service_type": tp,
1170-
}),
1171-
)).
1164+
Join("INNER", "issue", "issue.id = comment.issue_id").
1165+
Join("INNER", "repository", "issue.repo_id = repository.id").
1166+
Where("repository.original_service_type = ?", tp).
11721167
And("comment.original_author_id = ?", originalAuthorID).
11731168
Update(map[string]any{
11741169
"poster_id": posterID,

models/migrations/v1_22/v283_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import (
77
"testing"
88

99
"code.gitea.io/gitea/models/migrations/base"
10+
11+
"github.com/stretchr/testify/assert"
1012
)
1113

1214
func Test_AddCombinedIndexToIssueUser(t *testing.T) {
13-
type IssueUser struct {
14-
UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID.
15-
IssueID int64 `xorm:"INDEX unique(uid_to_issue)"`
15+
type IssueUser struct { // old struct
16+
ID int64 `xorm:"pk autoincr"`
17+
UID int64 `xorm:"INDEX"` // User ID.
18+
IssueID int64 `xorm:"INDEX"`
19+
IsRead bool
20+
IsMentioned bool
1621
}
1722

1823
// Prepare and load the testing database
1924
x, deferable := base.PrepareTestEnv(t, 0, new(IssueUser))
2025
defer deferable()
21-
if x == nil || t.Failed() {
22-
return
23-
}
2426

25-
if err := AddCombinedIndexToIssueUser(x); err != nil {
26-
t.Fatal(err)
27-
}
27+
assert.NoError(t, AddCombinedIndexToIssueUser(x))
2828
}

models/user/user.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import (
1010
"fmt"
1111
"net/url"
1212
"path/filepath"
13+
"regexp"
1314
"strings"
1415
"time"
16+
"unicode"
1517

1618
_ "image/jpeg" // Needed for jpeg support
1719

@@ -29,6 +31,9 @@ import (
2931
"code.gitea.io/gitea/modules/util"
3032
"code.gitea.io/gitea/modules/validation"
3133

34+
"golang.org/x/text/runes"
35+
"golang.org/x/text/transform"
36+
"golang.org/x/text/unicode/norm"
3237
"xorm.io/builder"
3338
)
3439

@@ -515,6 +520,26 @@ func GetUserSalt() (string, error) {
515520
return hex.EncodeToString(rBytes), nil
516521
}
517522

523+
// Note: The set of characters here can safely expand without a breaking change,
524+
// but characters removed from this set can cause user account linking to break
525+
var (
526+
customCharsReplacement = strings.NewReplacer("Æ", "AE")
527+
removeCharsRE = regexp.MustCompile(`['´\x60]`)
528+
removeDiacriticsTransform = transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
529+
replaceCharsHyphenRE = regexp.MustCompile(`[\s~+]`)
530+
)
531+
532+
// normalizeUserName returns a string with single-quotes and diacritics
533+
// removed, and any other non-supported username characters replaced with
534+
// a `-` character
535+
func NormalizeUserName(s string) (string, error) {
536+
strDiacriticsRemoved, n, err := transform.String(removeDiacriticsTransform, customCharsReplacement.Replace(s))
537+
if err != nil {
538+
return "", fmt.Errorf("Failed to normalize character `%v` in provided username `%v`", s[n], s)
539+
}
540+
return replaceCharsHyphenRE.ReplaceAllLiteralString(removeCharsRE.ReplaceAllLiteralString(strDiacriticsRemoved, ""), "-"), nil
541+
}
542+
518543
var (
519544
reservedUsernames = []string{
520545
".",

models/user/user_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,3 +544,31 @@ func Test_ValidateUser(t *testing.T) {
544544
assert.EqualValues(t, expected, err == nil, fmt.Sprintf("case: %+v", kase))
545545
}
546546
}
547+
548+
func Test_NormalizeUserFromEmail(t *testing.T) {
549+
testCases := []struct {
550+
Input string
551+
Expected string
552+
IsNormalizedValid bool
553+
}{
554+
{"test", "test", true},
555+
{"Sinéad.O'Connor", "Sinead.OConnor", true},
556+
{"Æsir", "AEsir", true},
557+
// \u00e9\u0065\u0301
558+
{"éé", "ee", true},
559+
{"Awareness Hub", "Awareness-Hub", true},
560+
{"double__underscore", "double__underscore", false}, // We should consider squashing double non-alpha characters
561+
{".bad.", ".bad.", false},
562+
{"new😀user", "new😀user", false}, // No plans to support
563+
}
564+
for _, testCase := range testCases {
565+
normalizedName, err := user_model.NormalizeUserName(testCase.Input)
566+
assert.NoError(t, err)
567+
assert.EqualValues(t, testCase.Expected, normalizedName)
568+
if testCase.IsNormalizedValid {
569+
assert.NoError(t, user_model.IsUsableUsername(normalizedName))
570+
} else {
571+
assert.Error(t, user_model.IsUsableUsername(normalizedName))
572+
}
573+
}
574+
}

modules/markup/html.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -852,11 +852,14 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
852852
}
853853

854854
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
855-
// FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered?
856-
// The "mode" approach should be refactored to some other more clear&reliable way.
857-
if ctx.Metas == nil || (ctx.Metas["mode"] == "document" && !ctx.IsWiki) {
855+
if ctx.Metas == nil {
858856
return
859857
}
858+
859+
// FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered?
860+
// The "mode" approach should be refactored to some other more clear&reliable way.
861+
crossLinkOnly := (ctx.Metas["mode"] == "document" && !ctx.IsWiki)
862+
860863
var (
861864
found bool
862865
ref *references.RenderizableReference
@@ -870,7 +873,7 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
870873
// Repos with external issue trackers might still need to reference local PRs
871874
// We need to concern with the first one that shows up in the text, whichever it is
872875
isNumericStyle := ctx.Metas["style"] == "" || ctx.Metas["style"] == IssueNameStyleNumeric
873-
foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle)
876+
foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
874877

875878
switch ctx.Metas["style"] {
876879
case "", IssueNameStyleNumeric:

modules/markup/html_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,11 +561,16 @@ func TestPostProcess_RenderDocument(t *testing.T) {
561561
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
562562
}
563563

564-
// Issue index shouldn't be post processing in an document.
564+
// Issue index shouldn't be post processing in a document.
565565
test(
566566
"#1",
567567
"#1")
568568

569+
// But cross-referenced issue index should work.
570+
test(
571+
"go-gitea/gitea#12345",
572+
`<a href="`+util.URLJoin(markup.TestAppURL, "go-gitea", "gitea", "issues", "12345")+`" class="ref-issue">go-gitea/gitea#12345</a>`)
573+
569574
// Test that other post processing still works.
570575
test(
571576
":gitea:",

modules/references/references.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,11 @@ func FindAllIssueReferences(content string) []IssueReference {
331331
}
332332

333333
// FindRenderizableReferenceNumeric returns the first unvalidated reference found in a string.
334-
func FindRenderizableReferenceNumeric(content string, prOnly bool) (bool, *RenderizableReference) {
335-
match := issueNumericPattern.FindStringSubmatchIndex(content)
334+
func FindRenderizableReferenceNumeric(content string, prOnly, crossLinkOnly bool) (bool, *RenderizableReference) {
335+
var match []int
336+
if !crossLinkOnly {
337+
match = issueNumericPattern.FindStringSubmatchIndex(content)
338+
}
336339
if match == nil {
337340
if match = crossReferenceIssueNumericPattern.FindStringSubmatchIndex(content); match == nil {
338341
return false, nil

modules/setting/database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbsslMode s
168168
RawQuery: dbParam,
169169
}
170170
query := connURL.Query()
171-
if dbHost[0] == '/' { // looks like a unix socket
171+
if strings.HasPrefix(dbHost, "/") { // looks like a unix socket
172172
query.Add("host", dbHost)
173173
connURL.Host = ":" + port
174174
}

modules/setting/database_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ func Test_getPostgreSQLConnectionString(t *testing.T) {
6565
SSLMode string
6666
Output string
6767
}{
68+
{
69+
Host: "", // empty means default
70+
Output: "postgres://:@127.0.0.1:5432?sslmode=",
71+
},
6872
{
6973
Host: "/tmp/pg.sock",
7074
User: "testuser",

modules/setting/oauth2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const (
2121
OAuth2UsernameUserid OAuth2UsernameType = "userid"
2222
// OAuth2UsernameNickname oauth2 nickname field will be used as gitea name
2323
OAuth2UsernameNickname OAuth2UsernameType = "nickname"
24-
// OAuth2UsernameEmail username of oauth2 email filed will be used as gitea name
24+
// OAuth2UsernameEmail username of oauth2 email field will be used as gitea name
2525
OAuth2UsernameEmail OAuth2UsernameType = "email"
2626
)
2727

modules/setting/server.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
341341
LandingPageURL = LandingPageOrganizations
342342
case "login":
343343
LandingPageURL = LandingPageLogin
344-
case "":
345-
case "home":
344+
case "", "home":
346345
LandingPageURL = LandingPageHome
347346
default:
348347
LandingPageURL = LandingPage(landingPage)

0 commit comments

Comments
 (0)