fix(packages): restrict/limited/token-scope access (#39041, #39043, #39044, #39047, #39046) (#39058)

This commit is contained in:
Giteabot
2026-08-27 09:34:49 -07:00
committed by GitHub
parent 068355cabd
commit 1dab66b83c
21 changed files with 219 additions and 74 deletions
+8
View File
@@ -91,6 +91,14 @@ func (org *Organization) IsOwnedBy(ctx context.Context, uid int64) (bool, error)
return IsOrganizationOwner(ctx, org.ID, uid)
}
// CanChangeRepoTeamAccess reports whether a repository administrator can change team access.
func (org *Organization) CanChangeRepoTeamAccess(ctx context.Context, doer *user_model.User) (bool, error) {
if org.RepoAdminChangeTeamAccess || doer.IsAdmin {
return true, nil
}
return org.IsOwnedBy(ctx, doer.ID)
}
// IsOrgAdmin returns true if given user is in the owner team or an admin team.
func (org *Organization) IsOrgAdmin(ctx context.Context, uid int64) (bool, error) {
return IsOrganizationAdmin(ctx, org.ID, uid)
+3
View File
@@ -89,6 +89,9 @@ func DoerViewOtherVisibility(doer, other *user_model.User) structs.VisibleType {
if doer.IsAdmin || doer.ID == other.ID {
return structs.VisibleTypePrivate
}
if doer.IsRestricted {
return structs.VisibleTypePublic
}
return structs.VisibleTypeLimited
}
+9 -3
View File
@@ -77,8 +77,14 @@ func testLoadOrgListTeams(t *testing.T) {
}
func testDoerViewOtherVisibility(t *testing.T) {
viewer := &user_model.User{ID: 1}
other := &user_model.User{ID: 2}
restrictedViewer := &user_model.User{ID: 3, IsRestricted: true}
assert.Equal(t, structs.VisibleTypePublic, organization.DoerViewOtherVisibility(nil, nil))
assert.Equal(t, structs.VisibleTypeLimited, organization.DoerViewOtherVisibility(&user_model.User{ID: 1}, &user_model.User{ID: 2}))
assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(&user_model.User{ID: 1}, &user_model.User{ID: 1}))
assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(&user_model.User{ID: 1, IsAdmin: true}, &user_model.User{ID: 2}))
assert.Equal(t, structs.VisibleTypeLimited, organization.DoerViewOtherVisibility(viewer, other))
assert.Equal(t, structs.VisibleTypePublic, organization.DoerViewOtherVisibility(restrictedViewer, other))
assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(viewer, viewer))
assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(restrictedViewer, restrictedViewer))
assert.Equal(t, structs.VisibleTypePrivate, organization.DoerViewOtherVisibility(&user_model.User{ID: 4, IsAdmin: true, IsRestricted: true}, other))
}
+5 -1
View File
@@ -126,6 +126,10 @@ func IsBlobAccessibleForUser(ctx context.Context, blobID int64, user *user_model
if user.IsAdmin {
return true, nil
}
ownerVisibilities := []structs.VisibleType{structs.VisibleTypePublic}
if !user.IsRestricted {
ownerVisibilities = append(ownerVisibilities, structs.VisibleTypeLimited)
}
maxTeamAuthorize := builder.
Select("max(team.authorize)").
@@ -144,7 +148,7 @@ func IsBlobAccessibleForUser(ctx context.Context, blobID int64, user *user_model
// owner = user
builder.Eq{"`user`.id": user.ID}.
// user can see owner
Or(builder.Eq{"`user`.visibility": structs.VisibleTypePublic}.Or(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})).
Or(builder.In("`user`.visibility", ownerVisibilities)).
// owner is an organization and user has access to it
Or(builder.Eq{"`user`.type": user_model.UserTypeOrganization}.
And(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamAuthorize}.Or(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamUnitAccessMode}))),
+23
View File
@@ -7,6 +7,7 @@ import (
"testing"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -49,3 +50,25 @@ func TestGetOrInsertBlobConcurrent(t *testing.T) {
}
assert.Equal(t, numGoroutines-1, existedCount)
}
func TestIsBlobAccessibleForRestrictedUser(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 33})
pkg, err := TryInsertPackage(t.Context(), &Package{OwnerID: owner.ID, Type: TypeContainer, Name: "limited", LowerName: "limited"})
require.NoError(t, err)
version, err := GetOrInsertVersion(t.Context(), &PackageVersion{PackageID: pkg.ID, Version: "1", LowerVersion: "1"})
require.NoError(t, err)
blob, _, err := GetOrInsertBlob(t.Context(), &PackageBlob{Size: 1, HashMD5: "md5", HashSHA1: "sha1", HashSHA256: "sha256", HashSHA512: "sha512"})
require.NoError(t, err)
_, err = TryInsertFile(t.Context(), &PackageFile{VersionID: version.ID, BlobID: blob.ID, Name: "blob", LowerName: "blob"})
require.NoError(t, err)
accessible, err := IsBlobAccessibleForUser(t.Context(), blob.ID, unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}))
require.NoError(t, err)
assert.True(t, accessible)
accessible, err = IsBlobAccessibleForUser(t.Context(), blob.ID, unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}))
require.NoError(t, err)
assert.False(t, accessible)
}