Skip to content

Commit 97ecd37

Browse files
authored
Merge branch 'main' into fix-stopwatch-toggle-bug
2 parents 5ed71e7 + 63fb253 commit 97ecd37

File tree

22 files changed

+175
-66
lines changed

22 files changed

+175
-66
lines changed

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ ifeq ($(RACE_ENABLED),true)
8181
endif
8282

8383
STORED_VERSION_FILE := VERSION
84-
HUGO_VERSION ?= 0.111.3
8584

8685
GITHUB_REF_TYPE ?= branch
8786
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)

models/actions/run_job.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,10 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
185185
return StatusSuccess
186186
case hasCancelled:
187187
return StatusCancelled
188-
case hasFailure:
189-
return StatusFailure
190188
case hasRunning:
191189
return StatusRunning
190+
case hasFailure:
191+
return StatusFailure
192192
case hasWaiting:
193193
return StatusWaiting
194194
case hasBlocked:

models/actions/run_job_status_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ func TestAggregateJobStatus(t *testing.T) {
5858
{[]Status{StatusCancelled, StatusRunning}, StatusCancelled},
5959
{[]Status{StatusCancelled, StatusBlocked}, StatusCancelled},
6060

61-
// failure with other status, fail fast
62-
// Should "running" win? Maybe no: old code does make "running" win, but GitHub does fail fast.
61+
// failure with other status, usually fail fast, but "running" wins to match GitHub's behavior
62+
// another reason that we can't make "failure" wins over "running": it would cause a weird behavior that user cannot cancel a workflow or get current running workflows correctly by filter after a job fail.
6363
{[]Status{StatusFailure}, StatusFailure},
6464
{[]Status{StatusFailure, StatusSuccess}, StatusFailure},
6565
{[]Status{StatusFailure, StatusSkipped}, StatusFailure},
6666
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
6767
{[]Status{StatusFailure, StatusWaiting}, StatusFailure},
68-
{[]Status{StatusFailure, StatusRunning}, StatusFailure},
68+
{[]Status{StatusFailure, StatusRunning}, StatusRunning},
6969
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
7070

7171
// skipped with other status

models/git/protected_branch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
518518
return currentWhitelist, nil
519519
}
520520

521-
teams, err := organization.GetTeamsWithAccessToRepo(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead)
521+
teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests)
522522
if err != nil {
523523
return nil, fmt.Errorf("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
524524
}

models/organization/org.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,3 @@ func getUserTeamIDsQueryBuilder(orgID, userID int64) *builder.Builder {
602602
"team_user.uid": userID,
603603
})
604604
}
605-
606-
// TeamsWithAccessToRepo returns all teams that have given access level to the repository.
607-
func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) {
608-
return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode)
609-
}

models/organization/team_repo.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"code.gitea.io/gitea/models/db"
1010
"code.gitea.io/gitea/models/perm"
1111
"code.gitea.io/gitea/models/unit"
12+
13+
"xorm.io/builder"
1214
)
1315

1416
// TeamRepo represents an team-repository relation.
@@ -48,26 +50,27 @@ func RemoveTeamRepo(ctx context.Context, teamID, repoID int64) error {
4850
return err
4951
}
5052

51-
// GetTeamsWithAccessToRepo returns all teams in an organization that have given access level to the repository.
52-
func GetTeamsWithAccessToRepo(ctx context.Context, orgID, repoID int64, mode perm.AccessMode) ([]*Team, error) {
53+
// GetTeamsWithAccessToAnyRepoUnit returns all teams in an organization that have given access level to the repository special unit.
54+
// This function is only used for finding some teams that can be used as branch protection allowlist or reviewers, it isn't really used for access control.
55+
// FIXME: TEAM-UNIT-PERMISSION this logic is not complete, search the fixme keyword to see more details
56+
func GetTeamsWithAccessToAnyRepoUnit(ctx context.Context, orgID, repoID int64, mode perm.AccessMode, unitType unit.Type, unitTypesMore ...unit.Type) ([]*Team, error) {
5357
teams := make([]*Team, 0, 5)
54-
return teams, db.GetEngine(ctx).Where("team.authorize >= ?", mode).
55-
Join("INNER", "team_repo", "team_repo.team_id = team.id").
56-
And("team_repo.org_id = ?", orgID).
57-
And("team_repo.repo_id = ?", repoID).
58-
OrderBy("name").
59-
Find(&teams)
60-
}
6158

62-
// GetTeamsWithAccessToRepoUnit returns all teams in an organization that have given access level to the repository special unit.
63-
func GetTeamsWithAccessToRepoUnit(ctx context.Context, orgID, repoID int64, mode perm.AccessMode, unitType unit.Type) ([]*Team, error) {
64-
teams := make([]*Team, 0, 5)
65-
return teams, db.GetEngine(ctx).Where("team_unit.access_mode >= ?", mode).
59+
sub := builder.Select("team_id").From("team_unit").
60+
Where(builder.Expr("team_unit.team_id = team.id")).
61+
And(builder.In("team_unit.type", append([]unit.Type{unitType}, unitTypesMore...))).
62+
And(builder.Expr("team_unit.access_mode >= ?", mode))
63+
64+
err := db.GetEngine(ctx).
6665
Join("INNER", "team_repo", "team_repo.team_id = team.id").
67-
Join("INNER", "team_unit", "team_unit.team_id = team.id").
6866
And("team_repo.org_id = ?", orgID).
6967
And("team_repo.repo_id = ?", repoID).
70-
And("team_unit.type = ?", unitType).
68+
And(builder.Or(
69+
builder.Expr("team.authorize >= ?", mode),
70+
builder.In("team.id", sub),
71+
)).
7172
OrderBy("name").
7273
Find(&teams)
74+
75+
return teams, err
7376
}

models/organization/team_repo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestGetTeamsWithAccessToRepoUnit(t *testing.T) {
2222
org41 := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 41})
2323
repo61 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 61})
2424

25-
teams, err := organization.GetTeamsWithAccessToRepoUnit(db.DefaultContext, org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests)
25+
teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(db.DefaultContext, org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests)
2626
assert.NoError(t, err)
2727
if assert.Len(t, teams, 2) {
2828
assert.EqualValues(t, 21, teams[0].ID)

models/perm/access/repo_permission.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
267267
perm.units = repo.Units
268268

269269
// anonymous user visit private repo.
270-
// TODO: anonymous user visit public unit of private repo???
271270
if user == nil && repo.IsPrivate {
272271
perm.AccessMode = perm_model.AccessModeNone
273272
return perm, nil
@@ -286,7 +285,8 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
286285
}
287286

288287
// Prevent strangers from checking out public repo of private organization/users
289-
// Allow user if they are collaborator of a repo within a private user or a private organization but not a member of the organization itself
288+
// Allow user if they are a collaborator of a repo within a private user or a private organization but not a member of the organization itself
289+
// TODO: rename it to "IsOwnerVisibleToDoer"
290290
if !organization.HasOrgOrUserVisible(ctx, repo.Owner, user) && !isCollaborator {
291291
perm.AccessMode = perm_model.AccessModeNone
292292
return perm, nil
@@ -304,7 +304,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
304304
return perm, nil
305305
}
306306

307-
// plain user
307+
// plain user TODO: this check should be replaced, only need to check collaborator access mode
308308
perm.AccessMode, err = accessLevel(ctx, user, repo)
309309
if err != nil {
310310
return perm, err
@@ -314,6 +314,19 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
314314
return perm, nil
315315
}
316316

317+
// now: the owner is visible to doer, if the repo is public, then the min access mode is read
318+
minAccessMode := util.Iif(!repo.IsPrivate && !user.IsRestricted, perm_model.AccessModeRead, perm_model.AccessModeNone)
319+
perm.AccessMode = max(perm.AccessMode, minAccessMode)
320+
321+
// get units mode from teams
322+
teams, err := organization.GetUserRepoTeams(ctx, repo.OwnerID, user.ID, repo.ID)
323+
if err != nil {
324+
return perm, err
325+
}
326+
if len(teams) == 0 {
327+
return perm, nil
328+
}
329+
317330
perm.unitsMode = make(map[unit.Type]perm_model.AccessMode)
318331

319332
// Collaborators on organization
@@ -323,12 +336,6 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
323336
}
324337
}
325338

326-
// get units mode from teams
327-
teams, err := organization.GetUserRepoTeams(ctx, repo.OwnerID, user.ID, repo.ID)
328-
if err != nil {
329-
return perm, err
330-
}
331-
332339
// if user in an owner team
333340
for _, team := range teams {
334341
if team.HasAdminAccess() {
@@ -339,19 +346,12 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
339346
}
340347

341348
for _, u := range repo.Units {
342-
var found bool
343349
for _, team := range teams {
350+
unitAccessMode := minAccessMode
344351
if teamMode, exist := team.UnitAccessModeEx(ctx, u.Type); exist {
345-
perm.unitsMode[u.Type] = max(perm.unitsMode[u.Type], teamMode)
346-
found = true
347-
}
348-
}
349-
350-
// for a public repo on an organization, a non-restricted user has read permission on non-team defined units.
351-
if !found && !repo.IsPrivate && !user.IsRestricted {
352-
if _, ok := perm.unitsMode[u.Type]; !ok {
353-
perm.unitsMode[u.Type] = perm_model.AccessModeRead
352+
unitAccessMode = max(perm.unitsMode[u.Type], unitAccessMode, teamMode)
354353
}
354+
perm.unitsMode[u.Type] = unitAccessMode
355355
}
356356
}
357357

models/perm/access/repo_permission_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ package access
66
import (
77
"testing"
88

9+
"code.gitea.io/gitea/models/db"
10+
"code.gitea.io/gitea/models/organization"
911
perm_model "code.gitea.io/gitea/models/perm"
1012
repo_model "code.gitea.io/gitea/models/repo"
1113
"code.gitea.io/gitea/models/unit"
14+
"code.gitea.io/gitea/models/unittest"
1215
user_model "code.gitea.io/gitea/models/user"
1316

1417
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
1519
)
1620

1721
func TestHasAnyUnitAccess(t *testing.T) {
@@ -152,3 +156,45 @@ func TestUnitAccessMode(t *testing.T) {
152156
}
153157
assert.Equal(t, perm_model.AccessModeRead, perm.UnitAccessMode(unit.TypeWiki), "has unit, and map, use map")
154158
}
159+
160+
func TestGetUserRepoPermission(t *testing.T) {
161+
assert.NoError(t, unittest.PrepareTestDatabase())
162+
ctx := t.Context()
163+
repo32 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32}) // org public repo
164+
require.NoError(t, repo32.LoadOwner(ctx))
165+
require.True(t, repo32.Owner.IsOrganization())
166+
167+
require.NoError(t, db.TruncateBeans(ctx, &organization.Team{}, &organization.TeamUser{}, &organization.TeamRepo{}, &organization.TeamUnit{}))
168+
org := repo32.Owner
169+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
170+
team := &organization.Team{OrgID: org.ID, LowerName: "test_team"}
171+
require.NoError(t, db.Insert(ctx, team))
172+
173+
t.Run("DoerInTeamWithNoRepo", func(t *testing.T) {
174+
require.NoError(t, db.Insert(ctx, &organization.TeamUser{OrgID: org.ID, TeamID: team.ID, UID: user.ID}))
175+
perm, err := GetUserRepoPermission(ctx, repo32, user)
176+
require.NoError(t, err)
177+
assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
178+
assert.Nil(t, perm.unitsMode) // doer in the team, but has no access to the repo
179+
})
180+
181+
require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: org.ID, TeamID: team.ID, RepoID: repo32.ID}))
182+
require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeNone}))
183+
t.Run("DoerWithTeamUnitAccessNone", func(t *testing.T) {
184+
perm, err := GetUserRepoPermission(ctx, repo32, user)
185+
require.NoError(t, err)
186+
assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
187+
assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeCode])
188+
assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
189+
})
190+
191+
require.NoError(t, db.TruncateBeans(ctx, &organization.TeamUnit{}))
192+
require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeWrite}))
193+
t.Run("DoerWithTeamUnitAccessWrite", func(t *testing.T) {
194+
perm, err := GetUserRepoPermission(ctx, repo32, user)
195+
require.NoError(t, err)
196+
assert.Equal(t, perm_model.AccessModeRead, perm.AccessMode)
197+
assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode])
198+
assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues])
199+
})
200+
}

modules/lfstransfer/backend/util.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ func newInternalRequestLFS(ctx context.Context, internalURL, method string, head
132132
return nil
133133
}
134134
req := private.NewInternalRequest(ctx, internalURL, method)
135+
req.SetReadWriteTimeout(0)
135136
for k, v := range headers {
136137
req.Header(k, v)
137138
}

0 commit comments

Comments
 (0)