Skip to content

Commit d934c0f

Browse files
committed
Merge upstream/main into config
2 parents 848a475 + 5407382 commit d934c0f

Some content is hidden

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

77 files changed

+530
-169
lines changed

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Gitea DevContainer",
3-
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
3+
"image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm",
44
"features": {
55
// installs nodejs into container
66
"ghcr.io/devcontainers/features/node:1": {

cmd/admin_auth_ldap.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,34 @@ var (
127127
&cli.UintFlag{
128128
Name: "page-size",
129129
Usage: "Search page size.",
130+
},
131+
&cli.BoolFlag{
132+
Name: "enable-groups",
133+
Usage: "Enable LDAP groups",
134+
},
135+
&cli.StringFlag{
136+
Name: "group-search-base-dn",
137+
Usage: "The LDAP base DN at which group accounts will be searched for",
138+
},
139+
&cli.StringFlag{
140+
Name: "group-member-attribute",
141+
Usage: "Group attribute containing list of users",
142+
},
143+
&cli.StringFlag{
144+
Name: "group-user-attribute",
145+
Usage: "User attribute listed in group",
146+
},
147+
&cli.StringFlag{
148+
Name: "group-filter",
149+
Usage: "Verify group membership in LDAP",
150+
},
151+
&cli.StringFlag{
152+
Name: "group-team-map",
153+
Usage: "Map LDAP groups to Organization teams",
154+
},
155+
&cli.BoolFlag{
156+
Name: "group-team-map-removal",
157+
Usage: "Remove users from synchronized teams if user does not belong to corresponding LDAP group",
130158
})
131159

132160
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
@@ -273,6 +301,27 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
273301
if c.IsSet("skip-local-2fa") {
274302
config.SkipLocalTwoFA = c.Bool("skip-local-2fa")
275303
}
304+
if c.IsSet("enable-groups") {
305+
config.GroupsEnabled = c.Bool("enable-groups")
306+
}
307+
if c.IsSet("group-search-base-dn") {
308+
config.GroupDN = c.String("group-search-base-dn")
309+
}
310+
if c.IsSet("group-member-attribute") {
311+
config.GroupMemberUID = c.String("group-member-attribute")
312+
}
313+
if c.IsSet("group-user-attribute") {
314+
config.UserUID = c.String("group-user-attribute")
315+
}
316+
if c.IsSet("group-filter") {
317+
config.GroupFilter = c.String("group-filter")
318+
}
319+
if c.IsSet("group-team-map") {
320+
config.GroupTeamMap = c.String("group-team-map")
321+
}
322+
if c.IsSet("group-team-map-removal") {
323+
config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
324+
}
276325
return nil
277326
}
278327

cmd/admin_auth_ldap_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ func TestAddLdapBindDn(t *testing.T) {
5151
"--attributes-in-bind",
5252
"--synchronize-users",
5353
"--page-size", "99",
54+
"--enable-groups",
55+
"--group-search-base-dn", "ou=group,dc=full-domain-bind,dc=org",
56+
"--group-member-attribute", "memberUid",
57+
"--group-user-attribute", "uid",
58+
"--group-filter", "(|(cn=gitea_users)(cn=admins))",
59+
"--group-team-map", `{"cn=my-group,cn=groups,dc=example,dc=org": {"MyGiteaOrganization": ["MyGiteaTeam1", "MyGiteaTeam2"]}}`,
60+
"--group-team-map-removal",
5461
},
5562
source: &auth.Source{
5663
Type: auth.LDAP,
@@ -78,6 +85,13 @@ func TestAddLdapBindDn(t *testing.T) {
7885
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
7986
RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
8087
Enabled: true,
88+
GroupsEnabled: true,
89+
GroupDN: "ou=group,dc=full-domain-bind,dc=org",
90+
GroupMemberUID: "memberUid",
91+
UserUID: "uid",
92+
GroupFilter: "(|(cn=gitea_users)(cn=admins))",
93+
GroupTeamMap: `{"cn=my-group,cn=groups,dc=example,dc=org": {"MyGiteaOrganization": ["MyGiteaTeam1", "MyGiteaTeam2"]}}`,
94+
GroupTeamMapRemoval: true,
8195
},
8296
},
8397
},
@@ -510,6 +524,13 @@ func TestUpdateLdapBindDn(t *testing.T) {
510524
"--bind-password", "secret-bind-full",
511525
"--synchronize-users",
512526
"--page-size", "99",
527+
"--enable-groups",
528+
"--group-search-base-dn", "ou=group,dc=full-domain-bind,dc=org",
529+
"--group-member-attribute", "memberUid",
530+
"--group-user-attribute", "uid",
531+
"--group-filter", "(|(cn=gitea_users)(cn=admins))",
532+
"--group-team-map", `{"cn=my-group,cn=groups,dc=example,dc=org": {"MyGiteaOrganization": ["MyGiteaTeam1", "MyGiteaTeam2"]}}`,
533+
"--group-team-map-removal",
513534
},
514535
id: 23,
515536
existingAuthSource: &auth.Source{
@@ -545,6 +566,13 @@ func TestUpdateLdapBindDn(t *testing.T) {
545566
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
546567
RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-bind,dc=org)",
547568
Enabled: true,
569+
GroupsEnabled: true,
570+
GroupDN: "ou=group,dc=full-domain-bind,dc=org",
571+
GroupMemberUID: "memberUid",
572+
UserUID: "uid",
573+
GroupFilter: "(|(cn=gitea_users)(cn=admins))",
574+
GroupTeamMap: `{"cn=my-group,cn=groups,dc=example,dc=org": {"MyGiteaOrganization": ["MyGiteaTeam1", "MyGiteaTeam2"]}}`,
575+
GroupTeamMapRemoval: true,
548576
},
549577
},
550578
},

models/actions/variable.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package actions
66
import (
77
"context"
88
"strings"
9+
"unicode/utf8"
910

1011
"code.gitea.io/gitea/models/db"
1112
"code.gitea.io/gitea/modules/log"
1213
"code.gitea.io/gitea/modules/timeutil"
14+
"code.gitea.io/gitea/modules/util"
1315

1416
"xorm.io/builder"
1517
)
@@ -32,26 +34,39 @@ type ActionVariable struct {
3234
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"`
3335
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
3436
Data string `xorm:"LONGTEXT NOT NULL"`
37+
Description string `xorm:"TEXT"`
3538
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
3639
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
3740
}
3841

42+
const (
43+
VariableDataMaxLength = 65536
44+
VariableDescriptionMaxLength = 4096
45+
)
46+
3947
func init() {
4048
db.RegisterModel(new(ActionVariable))
4149
}
4250

43-
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) {
51+
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*ActionVariable, error) {
4452
if ownerID != 0 && repoID != 0 {
4553
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
4654
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
4755
ownerID = 0
4856
}
4957

58+
if utf8.RuneCountInString(data) > VariableDataMaxLength {
59+
return nil, util.NewInvalidArgumentErrorf("data too long")
60+
}
61+
62+
description = util.TruncateRunes(description, VariableDescriptionMaxLength)
63+
5064
variable := &ActionVariable{
51-
OwnerID: ownerID,
52-
RepoID: repoID,
53-
Name: strings.ToUpper(name),
54-
Data: data,
65+
OwnerID: ownerID,
66+
RepoID: repoID,
67+
Name: strings.ToUpper(name),
68+
Data: data,
69+
Description: description,
5570
}
5671
return variable, db.Insert(ctx, variable)
5772
}
@@ -96,6 +111,12 @@ func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariab
96111
}
97112

98113
func UpdateVariableCols(ctx context.Context, variable *ActionVariable, cols ...string) (bool, error) {
114+
if utf8.RuneCountInString(variable.Data) > VariableDataMaxLength {
115+
return false, util.NewInvalidArgumentErrorf("data too long")
116+
}
117+
118+
variable.Description = util.TruncateRunes(variable.Description, VariableDescriptionMaxLength)
119+
99120
variable.Name = strings.ToUpper(variable.Name)
100121
count, err := db.GetEngine(ctx).
101122
ID(variable.ID).

models/migrations/migrations.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ func prepareMigrationTasks() []*migration {
376376
newMigration(313, "Move PinOrder from issue table to a new table issue_pin", v1_24.MovePinOrderToTableIssuePin),
377377
newMigration(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
378378
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
379-
newMigration(316, "Migrate the configuration of the ui section of the ini configuration file to the system setting table.", v1_24.MigrateIniToDatabase),
379+
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
380+
newMigration(317, "Migrate the configuration of the ui section of the ini configuration file to the system setting table.", v1_24.MigrateIniToDatabase),
380381
}
381382
return preparedMigrations
382383
}

models/migrations/v1_24/v316.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_24 //nolint
5+
6+
import (
7+
"xorm.io/xorm"
8+
)
9+
10+
func AddDescriptionForSecretsAndVariables(x *xorm.Engine) error {
11+
type Secret struct {
12+
Description string `xorm:"TEXT"`
13+
}
14+
15+
type ActionVariable struct {
16+
Description string `xorm:"TEXT"`
17+
}
18+
19+
return x.Sync(new(Secret), new(ActionVariable))
20+
}

models/repo/repo.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,24 @@ func init() {
215215
db.RegisterModel(new(Repository))
216216
}
217217

218-
func (repo *Repository) GetName() string {
219-
return repo.Name
218+
func RelativePath(ownerName, repoName string) string {
219+
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
220220
}
221221

222-
func (repo *Repository) GetOwnerName() string {
223-
return repo.OwnerName
222+
// RelativePath should be an unix style path like username/reponame.git
223+
func (repo *Repository) RelativePath() string {
224+
return RelativePath(repo.OwnerName, repo.Name)
225+
}
226+
227+
type StorageRepo string
228+
229+
// RelativePath should be an unix style path like username/reponame.git
230+
func (sr StorageRepo) RelativePath() string {
231+
return string(sr)
232+
}
233+
234+
func (repo *Repository) WikiStorageRepo() StorageRepo {
235+
return StorageRepo(strings.ToLower(repo.OwnerName) + "/" + strings.ToLower(repo.Name) + ".wiki.git")
224236
}
225237

226238
// SanitizedOriginalURL returns a sanitized OriginalURL

models/secret/secret.go

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@ type Secret struct {
4040
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
4141
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
4242
Data string `xorm:"LONGTEXT"` // encrypted data
43+
Description string `xorm:"TEXT"`
4344
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
4445
}
4546

47+
const (
48+
SecretDataMaxLength = 65536
49+
SecretDescriptionMaxLength = 4096
50+
)
51+
4652
// ErrSecretNotFound represents a "secret not found" error.
4753
type ErrSecretNotFound struct {
4854
Name string
@@ -57,7 +63,7 @@ func (err ErrSecretNotFound) Unwrap() error {
5763
}
5864

5965
// InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
60-
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*Secret, error) {
66+
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*Secret, error) {
6167
if ownerID != 0 && repoID != 0 {
6268
// It's trying to create a secret that belongs to a repository, but OwnerID has been set accidentally.
6369
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
@@ -67,15 +73,23 @@ func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, dat
6773
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
6874
}
6975

76+
if len(data) > SecretDataMaxLength {
77+
return nil, util.NewInvalidArgumentErrorf("data too long")
78+
}
79+
80+
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
81+
7082
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
7183
if err != nil {
7284
return nil, err
7385
}
86+
7487
secret := &Secret{
75-
OwnerID: ownerID,
76-
RepoID: repoID,
77-
Name: strings.ToUpper(name),
78-
Data: encrypted,
88+
OwnerID: ownerID,
89+
RepoID: repoID,
90+
Name: strings.ToUpper(name),
91+
Data: encrypted,
92+
Description: description,
7993
}
8094
return secret, db.Insert(ctx, secret)
8195
}
@@ -114,16 +128,23 @@ func (opts FindSecretsOptions) ToConds() builder.Cond {
114128
}
115129

116130
// UpdateSecret changes org or user reop secret.
117-
func UpdateSecret(ctx context.Context, secretID int64, data string) error {
131+
func UpdateSecret(ctx context.Context, secretID int64, data, description string) error {
132+
if len(data) > SecretDataMaxLength {
133+
return util.NewInvalidArgumentErrorf("data too long")
134+
}
135+
136+
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
137+
118138
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
119139
if err != nil {
120140
return err
121141
}
122142

123143
s := &Secret{
124-
Data: encrypted,
144+
Data: encrypted,
145+
Description: description,
125146
}
126-
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data").Update(s)
147+
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data", "description").Update(s)
127148
if affected != 1 {
128149
return ErrSecretNotFound{}
129150
}

modules/git/command.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type Command struct {
4646
args []string
4747
globalArgsLength int
4848
brokenArgs []string
49+
cmd *exec.Cmd // for debug purpose only
4950
}
5051

5152
func logArgSanitize(arg string) string {
@@ -314,6 +315,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
314315
startTime := time.Now()
315316

316317
cmd := exec.CommandContext(ctx, c.prog, c.args...)
318+
c.cmd = cmd // for debug purpose only
317319
if opts.Env == nil {
318320
cmd.Env = os.Environ()
319321
} else {

0 commit comments

Comments
 (0)