Skip to content

Commit 0f0c0be

Browse files
committed
Merge branch 'main' into lunny/link_package
2 parents 023197c + 01bf8da commit 0f0c0be

File tree

220 files changed

+5562
-2071
lines changed

Some content is hidden

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

220 files changed

+5562
-2071
lines changed

.eslintrc.cjs

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const vitestPlugin = require('@vitest/eslint-plugin');
12
const restrictedSyntax = ['WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression'];
23

34
module.exports = {
@@ -37,15 +38,20 @@ module.exports = {
3738
'eslint-plugin-regexp',
3839
'eslint-plugin-sonarjs',
3940
'eslint-plugin-unicorn',
40-
'eslint-plugin-vitest',
41-
'eslint-plugin-vitest-globals',
4241
'eslint-plugin-wc',
4342
],
4443
env: {
4544
es2024: true,
4645
node: true,
4746
},
4847
overrides: [
48+
{
49+
files: ['**/*.cjs'],
50+
rules: {
51+
'import-x/no-commonjs': [0],
52+
'@typescript-eslint/no-require-imports': [0],
53+
},
54+
},
4955
{
5056
files: ['web_src/**/*'],
5157
globals: {
@@ -82,59 +88,58 @@ module.exports = {
8288
},
8389
{
8490
files: ['**/*.test.*', 'web_src/js/test/setup.ts'],
85-
env: {
86-
'vitest-globals/env': true,
87-
},
91+
plugins: ['@vitest/eslint-plugin'],
92+
globals: vitestPlugin.environments.env.globals,
8893
rules: {
89-
'vitest/consistent-test-filename': [0],
90-
'vitest/consistent-test-it': [0],
91-
'vitest/expect-expect': [0],
92-
'vitest/max-expects': [0],
93-
'vitest/max-nested-describe': [0],
94-
'vitest/no-alias-methods': [0],
95-
'vitest/no-commented-out-tests': [0],
96-
'vitest/no-conditional-expect': [0],
97-
'vitest/no-conditional-in-test': [0],
98-
'vitest/no-conditional-tests': [0],
99-
'vitest/no-disabled-tests': [0],
100-
'vitest/no-done-callback': [0],
101-
'vitest/no-duplicate-hooks': [0],
102-
'vitest/no-focused-tests': [0],
103-
'vitest/no-hooks': [0],
104-
'vitest/no-identical-title': [2],
105-
'vitest/no-interpolation-in-snapshots': [0],
106-
'vitest/no-large-snapshots': [0],
107-
'vitest/no-mocks-import': [0],
108-
'vitest/no-restricted-matchers': [0],
109-
'vitest/no-restricted-vi-methods': [0],
110-
'vitest/no-standalone-expect': [0],
111-
'vitest/no-test-prefixes': [0],
112-
'vitest/no-test-return-statement': [0],
113-
'vitest/prefer-called-with': [0],
114-
'vitest/prefer-comparison-matcher': [0],
115-
'vitest/prefer-each': [0],
116-
'vitest/prefer-equality-matcher': [0],
117-
'vitest/prefer-expect-resolves': [0],
118-
'vitest/prefer-hooks-in-order': [0],
119-
'vitest/prefer-hooks-on-top': [2],
120-
'vitest/prefer-lowercase-title': [0],
121-
'vitest/prefer-mock-promise-shorthand': [0],
122-
'vitest/prefer-snapshot-hint': [0],
123-
'vitest/prefer-spy-on': [0],
124-
'vitest/prefer-strict-equal': [0],
125-
'vitest/prefer-to-be': [0],
126-
'vitest/prefer-to-be-falsy': [0],
127-
'vitest/prefer-to-be-object': [0],
128-
'vitest/prefer-to-be-truthy': [0],
129-
'vitest/prefer-to-contain': [0],
130-
'vitest/prefer-to-have-length': [0],
131-
'vitest/prefer-todo': [0],
132-
'vitest/require-hook': [0],
133-
'vitest/require-to-throw-message': [0],
134-
'vitest/require-top-level-describe': [0],
135-
'vitest/valid-describe-callback': [2],
136-
'vitest/valid-expect': [2],
137-
'vitest/valid-title': [2],
94+
'@vitest/consistent-test-filename': [0],
95+
'@vitest/consistent-test-it': [0],
96+
'@vitest/expect-expect': [0],
97+
'@vitest/max-expects': [0],
98+
'@vitest/max-nested-describe': [0],
99+
'@vitest/no-alias-methods': [0],
100+
'@vitest/no-commented-out-tests': [0],
101+
'@vitest/no-conditional-expect': [0],
102+
'@vitest/no-conditional-in-test': [0],
103+
'@vitest/no-conditional-tests': [0],
104+
'@vitest/no-disabled-tests': [0],
105+
'@vitest/no-done-callback': [0],
106+
'@vitest/no-duplicate-hooks': [0],
107+
'@vitest/no-focused-tests': [0],
108+
'@vitest/no-hooks': [0],
109+
'@vitest/no-identical-title': [2],
110+
'@vitest/no-interpolation-in-snapshots': [0],
111+
'@vitest/no-large-snapshots': [0],
112+
'@vitest/no-mocks-import': [0],
113+
'@vitest/no-restricted-matchers': [0],
114+
'@vitest/no-restricted-vi-methods': [0],
115+
'@vitest/no-standalone-expect': [0],
116+
'@vitest/no-test-prefixes': [0],
117+
'@vitest/no-test-return-statement': [0],
118+
'@vitest/prefer-called-with': [0],
119+
'@vitest/prefer-comparison-matcher': [0],
120+
'@vitest/prefer-each': [0],
121+
'@vitest/prefer-equality-matcher': [0],
122+
'@vitest/prefer-expect-resolves': [0],
123+
'@vitest/prefer-hooks-in-order': [0],
124+
'@vitest/prefer-hooks-on-top': [2],
125+
'@vitest/prefer-lowercase-title': [0],
126+
'@vitest/prefer-mock-promise-shorthand': [0],
127+
'@vitest/prefer-snapshot-hint': [0],
128+
'@vitest/prefer-spy-on': [0],
129+
'@vitest/prefer-strict-equal': [0],
130+
'@vitest/prefer-to-be': [0],
131+
'@vitest/prefer-to-be-falsy': [0],
132+
'@vitest/prefer-to-be-object': [0],
133+
'@vitest/prefer-to-be-truthy': [0],
134+
'@vitest/prefer-to-contain': [0],
135+
'@vitest/prefer-to-have-length': [0],
136+
'@vitest/prefer-todo': [0],
137+
'@vitest/require-hook': [0],
138+
'@vitest/require-to-throw-message': [0],
139+
'@vitest/require-top-level-describe': [0],
140+
'@vitest/valid-describe-callback': [2],
141+
'@vitest/valid-expect': [2],
142+
'@vitest/valid-title': [2],
138143
},
139144
},
140145
{
@@ -163,7 +168,7 @@ module.exports = {
163168
{
164169
files: ['tests/e2e/**'],
165170
plugins: [
166-
'eslint-plugin-playwright'
171+
'eslint-plugin-playwright',
167172
],
168173
extends: [
169174
'plugin:playwright/recommended',

.github/workflows/cron-licenses.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name: cron-licenses
22

33
on:
4-
schedule:
5-
- cron: "7 0 * * 1" # every Monday at 00:07 UTC
4+
# schedule:
5+
# - cron: "7 0 * * 1" # every Monday at 00:07 UTC
66
workflow_dispatch:
77

88
jobs:

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage
2-
FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
2+
FROM docker.io/library/golang:1.24-alpine3.21 AS build-env
33

44
ARG GOPROXY
55
ENV GOPROXY=${GOPROXY:-direct}

Dockerfile.rootless

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build stage
2-
FROM docker.io/library/golang:1.23-alpine3.21 AS build-env
2+
FROM docker.io/library/golang:1.24-alpine3.21 AS build-env
33

44
ARG GOPROXY
55
ENV GOPROXY=${GOPROXY:-direct}

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,4 @@ Kemal Zebari <[email protected]> (@kemzeb)
6363
Rowan Bohde <[email protected]> (@bohde)
6464
hiifong <[email protected]> (@hiifong)
6565
metiftikci <[email protected]> (@metiftikci)
66+
Christopher Homberger <[email protected]> (@ChristopherHX)

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ SHASUM ?= shasum -a 256
2323
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
2424
COMMA := ,
2525

26-
XGO_VERSION := go-1.23.x
26+
XGO_VERSION := go-1.24.x
2727

2828
AIR_PACKAGE ?= github.com/air-verse/air@v1
2929
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/[email protected]
@@ -144,7 +144,7 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
144144
GO_DIRS := build cmd models modules routers services tests
145145
WEB_DIRS := web_src/js web_src/css
146146

147-
ESLINT_FILES := web_src/js tools *.js *.ts tests/e2e
147+
ESLINT_FILES := web_src/js tools *.js *.ts *.cjs tests/e2e
148148
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
149149
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.js *.md *.yml *.yaml *.toml))
150150
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
@@ -393,7 +393,7 @@ lint-templates: .venv node_modules ## lint template files
393393

394394
.PHONY: lint-yaml
395395
lint-yaml: .venv ## lint yaml files
396-
@poetry run yamllint .
396+
@poetry run yamllint -s .
397397

398398
.PHONY: watch
399399
watch: ## watch everything and continuously rebuild

cmd/admin_user_create.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ var microcmdUserCreate = &cli.Command{
3131
Name: "username",
3232
Usage: "Username",
3333
},
34+
&cli.StringFlag{
35+
Name: "user-type",
36+
Usage: "Set user's type: individual or bot",
37+
Value: "individual",
38+
},
3439
&cli.StringFlag{
3540
Name: "password",
3641
Usage: "User password",
@@ -77,6 +82,22 @@ func runCreateUser(c *cli.Context) error {
7782
return err
7883
}
7984

85+
userTypes := map[string]user_model.UserType{
86+
"individual": user_model.UserTypeIndividual,
87+
"bot": user_model.UserTypeBot,
88+
}
89+
userType, ok := userTypes[c.String("user-type")]
90+
if !ok {
91+
return fmt.Errorf("invalid user type: %s", c.String("user-type"))
92+
}
93+
if userType != user_model.UserTypeIndividual {
94+
// Some other commands like "change-password" also only support individual users.
95+
// It needs to clarify the "password" behavior for bot users in the future.
96+
// At the moment, we do not allow setting password for bot users.
97+
if c.IsSet("password") || c.IsSet("random-password") {
98+
return errors.New("password can only be set for individual users")
99+
}
100+
}
80101
if c.IsSet("name") && c.IsSet("username") {
81102
return errors.New("cannot set both --name and --username flags")
82103
}
@@ -118,16 +139,19 @@ func runCreateUser(c *cli.Context) error {
118139
return err
119140
}
120141
fmt.Printf("generated random password is '%s'\n", password)
121-
} else {
142+
} else if userType == user_model.UserTypeIndividual {
122143
return errors.New("must set either password or random-password flag")
123144
}
124145

125146
isAdmin := c.Bool("admin")
126147
mustChangePassword := true // always default to true
127148
if c.IsSet("must-change-password") {
149+
if userType != user_model.UserTypeIndividual {
150+
return errors.New("must-change-password flag can only be set for individual users")
151+
}
128152
// if the flag is set, use the value provided by the user
129153
mustChangePassword = c.Bool("must-change-password")
130-
} else {
154+
} else if userType == user_model.UserTypeIndividual {
131155
// check whether there are users in the database
132156
hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{})
133157
if err != nil {
@@ -151,8 +175,9 @@ func runCreateUser(c *cli.Context) error {
151175
u := &user_model.User{
152176
Name: username,
153177
Email: c.String("email"),
154-
Passwd: password,
155178
IsAdmin: isAdmin,
179+
Type: userType,
180+
Passwd: password,
156181
MustChangePassword: mustChangePassword,
157182
Visibility: visibility,
158183
}

cmd/admin_user_create_test.go

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,54 @@ import (
1313
user_model "code.gitea.io/gitea/models/user"
1414

1515
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
1617
)
1718

1819
func TestAdminUserCreate(t *testing.T) {
1920
app := NewMainApp(AppVersion{})
2021

2122
reset := func() {
22-
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
23-
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
23+
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
24+
require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
2425
}
2526

26-
type createCheck struct{ IsAdmin, MustChangePassword bool }
27-
createUser := func(name, args string) createCheck {
28-
assert.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %[email protected] %s --password foobar", name, name, args))))
29-
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
30-
return createCheck{u.IsAdmin, u.MustChangePassword}
31-
}
32-
reset()
33-
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u", ""), "first non-admin user doesn't need to change password")
34-
35-
reset()
36-
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u", "--admin"), "first admin user doesn't need to change password")
37-
38-
reset()
39-
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u", "--admin --must-change-password"))
40-
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u2", "--admin"))
41-
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u3", "--admin --must-change-password=false"))
42-
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: true}, createUser("u4", ""))
43-
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u5", "--must-change-password=false"))
27+
t.Run("MustChangePassword", func(t *testing.T) {
28+
type check struct {
29+
IsAdmin bool
30+
MustChangePassword bool
31+
}
32+
createCheck := func(name, args string) check {
33+
require.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %[email protected] %s --password foobar", name, name, args))))
34+
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
35+
return check{IsAdmin: u.IsAdmin, MustChangePassword: u.MustChangePassword}
36+
}
37+
reset()
38+
assert.Equal(t, check{IsAdmin: false, MustChangePassword: false}, createCheck("u", ""), "first non-admin user doesn't need to change password")
39+
40+
reset()
41+
assert.Equal(t, check{IsAdmin: true, MustChangePassword: false}, createCheck("u", "--admin"), "first admin user doesn't need to change password")
42+
43+
reset()
44+
assert.Equal(t, check{IsAdmin: true, MustChangePassword: true}, createCheck("u", "--admin --must-change-password"))
45+
assert.Equal(t, check{IsAdmin: true, MustChangePassword: true}, createCheck("u2", "--admin"))
46+
assert.Equal(t, check{IsAdmin: true, MustChangePassword: false}, createCheck("u3", "--admin --must-change-password=false"))
47+
assert.Equal(t, check{IsAdmin: false, MustChangePassword: true}, createCheck("u4", ""))
48+
assert.Equal(t, check{IsAdmin: false, MustChangePassword: false}, createCheck("u5", "--must-change-password=false"))
49+
})
50+
51+
t.Run("UserType", func(t *testing.T) {
52+
createUser := func(name, args string) error {
53+
return app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %[email protected] %s", name, name, args)))
54+
}
55+
56+
reset()
57+
assert.ErrorContains(t, createUser("u", "--user-type invalid"), "invalid user type")
58+
assert.ErrorContains(t, createUser("u", "--user-type bot --password 123"), "can only be set for individual users")
59+
assert.ErrorContains(t, createUser("u", "--user-type bot --must-change-password"), "can only be set for individual users")
60+
61+
assert.NoError(t, createUser("u", "--user-type bot"))
62+
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: "u"})
63+
assert.Equal(t, user_model.UserTypeBot, u.Type)
64+
assert.Equal(t, "", u.Passwd)
65+
})
4466
}

flake.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@
2929
poetry
3030

3131
# backend
32-
go_1_23
32+
go_1_24
3333
gofumpt
3434
sqlite
3535
];
3636
shellHook = ''
37-
export GO="${pkgs.go_1_23}/bin/go"
38-
export GOROOT="${pkgs.go_1_23}/share/go"
37+
export GO="${pkgs.go_1_24}/bin/go"
38+
export GOROOT="${pkgs.go_1_24}/share/go"
3939
'';
4040
};
4141
}

0 commit comments

Comments
 (0)