Skip to content

Commit 74ace80

Browse files
committed
Merge branch 'main' into oidc-provider
2 parents 3ac43c6 + bf9500b commit 74ace80

File tree

52 files changed

+1951
-1179
lines changed

Some content is hidden

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

52 files changed

+1951
-1179
lines changed

models/actions/run_job.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"code.gitea.io/gitea/models/db"
13+
repo_model "code.gitea.io/gitea/models/repo"
1314
"code.gitea.io/gitea/modules/timeutil"
1415
"code.gitea.io/gitea/modules/util"
1516

@@ -19,11 +20,12 @@ import (
1920
// ActionRunJob represents a job of a run
2021
type ActionRunJob struct {
2122
ID int64
22-
RunID int64 `xorm:"index"`
23-
Run *ActionRun `xorm:"-"`
24-
RepoID int64 `xorm:"index"`
25-
OwnerID int64 `xorm:"index"`
26-
CommitSHA string `xorm:"index"`
23+
RunID int64 `xorm:"index"`
24+
Run *ActionRun `xorm:"-"`
25+
RepoID int64 `xorm:"index"`
26+
Repo *repo_model.Repository `xorm:"-"`
27+
OwnerID int64 `xorm:"index"`
28+
CommitSHA string `xorm:"index"`
2729
IsForkPullRequest bool
2830
Name string `xorm:"VARCHAR(255)"`
2931
Attempt int64
@@ -59,6 +61,17 @@ func (job *ActionRunJob) LoadRun(ctx context.Context) error {
5961
return nil
6062
}
6163

64+
func (job *ActionRunJob) LoadRepo(ctx context.Context) error {
65+
if job.Repo == nil {
66+
repo, err := repo_model.GetRepositoryByID(ctx, job.RepoID)
67+
if err != nil {
68+
return err
69+
}
70+
job.Repo = repo
71+
}
72+
return nil
73+
}
74+
6275
// LoadAttributes load Run if not loaded
6376
func (job *ActionRunJob) LoadAttributes(ctx context.Context) error {
6477
if job == nil {
@@ -88,7 +101,7 @@ func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) {
88101
return &job, nil
89102
}
90103

91-
func GetRunJobsByRunID(ctx context.Context, runID int64) ([]*ActionRunJob, error) {
104+
func GetRunJobsByRunID(ctx context.Context, runID int64) (ActionJobList, error) {
92105
var jobs []*ActionRunJob
93106
if err := db.GetEngine(ctx).Where("run_id=?", runID).OrderBy("id").Find(&jobs); err != nil {
94107
return nil, err

models/actions/run_job_list.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88

99
"code.gitea.io/gitea/models/db"
10+
repo_model "code.gitea.io/gitea/models/repo"
1011
"code.gitea.io/gitea/modules/container"
1112
"code.gitea.io/gitea/modules/timeutil"
1213

@@ -21,7 +22,33 @@ func (jobs ActionJobList) GetRunIDs() []int64 {
2122
})
2223
}
2324

25+
func (jobs ActionJobList) LoadRepos(ctx context.Context) error {
26+
repoIDs := container.FilterSlice(jobs, func(j *ActionRunJob) (int64, bool) {
27+
return j.RepoID, j.RepoID != 0 && j.Repo == nil
28+
})
29+
if len(repoIDs) == 0 {
30+
return nil
31+
}
32+
33+
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
34+
if err := db.GetEngine(ctx).In("id", repoIDs).Find(&repos); err != nil {
35+
return err
36+
}
37+
for _, j := range jobs {
38+
if j.RepoID > 0 && j.Repo == nil {
39+
j.Repo = repos[j.RepoID]
40+
}
41+
}
42+
return nil
43+
}
44+
2445
func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {
46+
if withRepo {
47+
if err := jobs.LoadRepos(ctx); err != nil {
48+
return err
49+
}
50+
}
51+
2552
runIDs := jobs.GetRunIDs()
2653
runs := make(map[int64]*ActionRun, len(runIDs))
2754
if err := db.GetEngine(ctx).In("id", runIDs).Find(&runs); err != nil {
@@ -30,15 +57,9 @@ func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {
3057
for _, j := range jobs {
3158
if j.RunID > 0 && j.Run == nil {
3259
j.Run = runs[j.RunID]
60+
j.Run.Repo = j.Repo
3361
}
3462
}
35-
if withRepo {
36-
var runsList RunList = make([]*ActionRun, 0, len(runs))
37-
for _, r := range runs {
38-
runsList = append(runsList, r)
39-
}
40-
return runsList.LoadRepos(ctx)
41-
}
4263
return nil
4364
}
4465

models/migrations/migrations.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ func prepareMigrationTasks() []*migration {
378378
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
379379
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
380380
newMigration(317, "Add new index for action for heatmap", v1_24.AddNewIndexForUserDashboard),
381-
newMigration(318, "Add Permissions to Actions Task", v1_24.AddPermissions),
381+
newMigration(318, "Add anonymous_access_mode for repo_unit", v1_24.AddRepoUnitAnonymousAccessMode),
382+
newMigration(319, "Add Permissions to Actions Task", v1_24.AddPermissions),
382383
}
383384
return preparedMigrations
384385
}

models/migrations/v1_24/v318.go

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,14 @@
44
package v1_24 //nolint
55

66
import (
7-
"xorm.io/xorm"
8-
)
7+
"code.gitea.io/gitea/models/perm"
98

10-
// Permission copied from models.actions.Permission
11-
type Permission int
12-
13-
const (
14-
PermissionUnspecified Permission = iota
15-
PermissionNone
16-
PermissionRead
17-
PermissionWrite
9+
"xorm.io/xorm"
1810
)
1911

20-
// Permissions copied from models.actions.Permissions
21-
type Permissions struct {
22-
Actions Permission `yaml:"actions"`
23-
Checks Permission `yaml:"checks"`
24-
Contents Permission `yaml:"contents"`
25-
Deployments Permission `yaml:"deployments"`
26-
IDToken Permission `yaml:"id-token"`
27-
Issues Permission `yaml:"issues"`
28-
Discussions Permission `yaml:"discussions"`
29-
Packages Permission `yaml:"packages"`
30-
Pages Permission `yaml:"pages"`
31-
PullRequests Permission `yaml:"pull-requests"`
32-
RepositoryProjects Permission `yaml:"repository-projects"`
33-
SecurityEvents Permission `yaml:"security-events"`
34-
Statuses Permission `yaml:"statuses"`
35-
}
36-
37-
func AddPermissions(x *xorm.Engine) error {
38-
type ActionRunJob struct {
39-
Permissions Permissions `xorm:"JSON TEXT"`
12+
func AddRepoUnitAnonymousAccessMode(x *xorm.Engine) error {
13+
type RepoUnit struct { //revive:disable-line:exported
14+
AnonymousAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
4015
}
41-
42-
return x.Sync(new(ActionRunJob))
16+
return x.Sync(&RepoUnit{})
4317
}

models/migrations/v1_24/v319.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
// Permission copied from models.actions.Permission
11+
type Permission int
12+
13+
const (
14+
PermissionUnspecified Permission = iota
15+
PermissionNone
16+
PermissionRead
17+
PermissionWrite
18+
)
19+
20+
// Permissions copied from models.actions.Permissions
21+
type Permissions struct {
22+
Actions Permission `yaml:"actions"`
23+
Checks Permission `yaml:"checks"`
24+
Contents Permission `yaml:"contents"`
25+
Deployments Permission `yaml:"deployments"`
26+
IDToken Permission `yaml:"id-token"`
27+
Issues Permission `yaml:"issues"`
28+
Discussions Permission `yaml:"discussions"`
29+
Packages Permission `yaml:"packages"`
30+
Pages Permission `yaml:"pages"`
31+
PullRequests Permission `yaml:"pull-requests"`
32+
RepositoryProjects Permission `yaml:"repository-projects"`
33+
SecurityEvents Permission `yaml:"security-events"`
34+
Statuses Permission `yaml:"statuses"`
35+
}
36+
37+
func AddPermissions(x *xorm.Engine) error {
38+
type ActionRunJob struct {
39+
Permissions Permissions `xorm:"JSON TEXT"`
40+
}
41+
42+
return x.Sync(new(ActionRunJob))
43+
}

models/perm/access/repo_permission.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ type Permission struct {
2525
units []*repo_model.RepoUnit
2626
unitsMode map[unit.Type]perm_model.AccessMode
2727

28-
everyoneAccessMode map[unit.Type]perm_model.AccessMode
28+
everyoneAccessMode map[unit.Type]perm_model.AccessMode // the unit's minimal access mode for every signed-in user
29+
anonymousAccessMode map[unit.Type]perm_model.AccessMode // the unit's minimal access mode for anonymous (non-signed-in) user
2930
}
3031

3132
// IsOwner returns true if current user is the owner of repository.
@@ -39,7 +40,7 @@ func (p *Permission) IsAdmin() bool {
3940
}
4041

4142
// HasAnyUnitAccess returns true if the user might have at least one access mode to any unit of this repository.
42-
// It doesn't count the "everyone access mode".
43+
// It doesn't count the "public(anonymous/everyone) access mode".
4344
func (p *Permission) HasAnyUnitAccess() bool {
4445
for _, v := range p.unitsMode {
4546
if v >= perm_model.AccessModeRead {
@@ -49,7 +50,12 @@ func (p *Permission) HasAnyUnitAccess() bool {
4950
return p.AccessMode >= perm_model.AccessModeRead
5051
}
5152

52-
func (p *Permission) HasAnyUnitAccessOrEveryoneAccess() bool {
53+
func (p *Permission) HasAnyUnitAccessOrPublicAccess() bool {
54+
for _, v := range p.anonymousAccessMode {
55+
if v >= perm_model.AccessModeRead {
56+
return true
57+
}
58+
}
5359
for _, v := range p.everyoneAccessMode {
5460
if v >= perm_model.AccessModeRead {
5561
return true
@@ -73,14 +79,16 @@ func (p *Permission) GetFirstUnitRepoID() int64 {
7379
}
7480

7581
// UnitAccessMode returns current user access mode to the specify unit of the repository
76-
// It also considers "everyone access mode"
82+
// It also considers "public (anonymous/everyone) access mode"
7783
func (p *Permission) UnitAccessMode(unitType unit.Type) perm_model.AccessMode {
7884
// if the units map contains the access mode, use it, but admin/owner mode could override it
7985
if m, ok := p.unitsMode[unitType]; ok {
8086
return util.Iif(p.AccessMode >= perm_model.AccessModeAdmin, p.AccessMode, m)
8187
}
8288
// if the units map does not contain the access mode, return the default access mode if the unit exists
83-
unitDefaultAccessMode := max(p.AccessMode, p.everyoneAccessMode[unitType])
89+
unitDefaultAccessMode := p.AccessMode
90+
unitDefaultAccessMode = max(unitDefaultAccessMode, p.anonymousAccessMode[unitType])
91+
unitDefaultAccessMode = max(unitDefaultAccessMode, p.everyoneAccessMode[unitType])
8492
hasUnit := slices.ContainsFunc(p.units, func(u *repo_model.RepoUnit) bool { return u.Type == unitType })
8593
return util.Iif(hasUnit, unitDefaultAccessMode, perm_model.AccessModeNone)
8694
}
@@ -171,27 +179,38 @@ func (p *Permission) LogString() string {
171179
format += "\n\tunitsMode[%-v]: %-v"
172180
args = append(args, key.LogString(), value.LogString())
173181
}
182+
format += "\n\tanonymousAccessMode: %-v"
183+
args = append(args, p.anonymousAccessMode)
174184
format += "\n\teveryoneAccessMode: %-v"
175185
args = append(args, p.everyoneAccessMode)
176186
format += "\n\t]>"
177187
return fmt.Sprintf(format, args...)
178188
}
179189

190+
func applyPublicAccessPermission(unitType unit.Type, accessMode perm_model.AccessMode, modeMap *map[unit.Type]perm_model.AccessMode) {
191+
if accessMode >= perm_model.AccessModeRead && accessMode > (*modeMap)[unitType] {
192+
if *modeMap == nil {
193+
*modeMap = make(map[unit.Type]perm_model.AccessMode)
194+
}
195+
(*modeMap)[unitType] = accessMode
196+
}
197+
}
198+
180199
func finalProcessRepoUnitPermission(user *user_model.User, perm *Permission) {
200+
// apply public (anonymous) access permissions
201+
for _, u := range perm.units {
202+
applyPublicAccessPermission(u.Type, u.AnonymousAccessMode, &perm.anonymousAccessMode)
203+
}
204+
181205
if user == nil || user.ID <= 0 {
182206
// for anonymous access, it could be:
183207
// AccessMode is None or Read, units has repo units, unitModes is nil
184208
return
185209
}
186210

187-
// apply everyone access permissions
211+
// apply public (everyone) access permissions
188212
for _, u := range perm.units {
189-
if u.EveryoneAccessMode >= perm_model.AccessModeRead && u.EveryoneAccessMode > perm.everyoneAccessMode[u.Type] {
190-
if perm.everyoneAccessMode == nil {
191-
perm.everyoneAccessMode = make(map[unit.Type]perm_model.AccessMode)
192-
}
193-
perm.everyoneAccessMode[u.Type] = u.EveryoneAccessMode
194-
}
213+
applyPublicAccessPermission(u.Type, u.EveryoneAccessMode, &perm.everyoneAccessMode)
195214
}
196215

197216
if perm.unitsMode == nil {
@@ -209,6 +228,11 @@ func finalProcessRepoUnitPermission(user *user_model.User, perm *Permission) {
209228
break
210229
}
211230
}
231+
for t := range perm.anonymousAccessMode {
232+
if shouldKeep = shouldKeep || u.Type == t; shouldKeep {
233+
break
234+
}
235+
}
212236
for t := range perm.everyoneAccessMode {
213237
if shouldKeep = shouldKeep || u.Type == t; shouldKeep {
214238
break

models/perm/access/repo_permission_test.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,21 @@ func TestHasAnyUnitAccess(t *testing.T) {
2222
units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
2323
}
2424
assert.False(t, perm.HasAnyUnitAccess())
25-
assert.False(t, perm.HasAnyUnitAccessOrEveryoneAccess())
25+
assert.False(t, perm.HasAnyUnitAccessOrPublicAccess())
2626

2727
perm = Permission{
2828
units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
2929
everyoneAccessMode: map[unit.Type]perm_model.AccessMode{unit.TypeIssues: perm_model.AccessModeRead},
3030
}
3131
assert.False(t, perm.HasAnyUnitAccess())
32-
assert.True(t, perm.HasAnyUnitAccessOrEveryoneAccess())
32+
assert.True(t, perm.HasAnyUnitAccessOrPublicAccess())
33+
34+
perm = Permission{
35+
units: []*repo_model.RepoUnit{{Type: unit.TypeWiki}},
36+
anonymousAccessMode: map[unit.Type]perm_model.AccessMode{unit.TypeIssues: perm_model.AccessModeRead},
37+
}
38+
assert.False(t, perm.HasAnyUnitAccess())
39+
assert.True(t, perm.HasAnyUnitAccessOrPublicAccess())
3340

3441
perm = Permission{
3542
AccessMode: perm_model.AccessModeRead,
@@ -43,7 +50,7 @@ func TestHasAnyUnitAccess(t *testing.T) {
4350
assert.True(t, perm.HasAnyUnitAccess())
4451
}
4552

46-
func TestApplyEveryoneRepoPermission(t *testing.T) {
53+
func TestApplyPublicAccessRepoPermission(t *testing.T) {
4754
perm := Permission{
4855
AccessMode: perm_model.AccessModeNone,
4956
units: []*repo_model.RepoUnit{
@@ -53,6 +60,15 @@ func TestApplyEveryoneRepoPermission(t *testing.T) {
5360
finalProcessRepoUnitPermission(nil, &perm)
5461
assert.False(t, perm.CanRead(unit.TypeWiki))
5562

63+
perm = Permission{
64+
AccessMode: perm_model.AccessModeNone,
65+
units: []*repo_model.RepoUnit{
66+
{Type: unit.TypeWiki, AnonymousAccessMode: perm_model.AccessModeRead},
67+
},
68+
}
69+
finalProcessRepoUnitPermission(nil, &perm)
70+
assert.True(t, perm.CanRead(unit.TypeWiki))
71+
5672
perm = Permission{
5773
AccessMode: perm_model.AccessModeNone,
5874
units: []*repo_model.RepoUnit{

models/repo/repo_unit.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ func (err ErrUnitTypeNotExist) Unwrap() error {
4242

4343
// RepoUnit describes all units of a repository
4444
type RepoUnit struct { //revive:disable-line:exported
45-
ID int64
46-
RepoID int64 `xorm:"INDEX(s)"`
47-
Type unit.Type `xorm:"INDEX(s)"`
48-
Config convert.Conversion `xorm:"TEXT"`
49-
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
50-
EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
45+
ID int64
46+
RepoID int64 `xorm:"INDEX(s)"`
47+
Type unit.Type `xorm:"INDEX(s)"`
48+
Config convert.Conversion `xorm:"TEXT"`
49+
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
50+
AnonymousAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
51+
EveryoneAccessMode perm.AccessMode `xorm:"NOT NULL DEFAULT 0"`
5152
}
5253

5354
func init() {

0 commit comments

Comments
 (0)