mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-28 16:47:01 +09:00
refactor: carry the API token on the doer (#39690)
The token a request authenticated with now lives on the doer, so permission and visibility checks apply its scope from the doer alone. Replaces https://github.com/go-gitea/gitea/pull/39167, following https://github.com/go-gitea/gitea/pull/39167#issuecomment-6063839619. 1. Public-only tokens get 404 instead of 403 for hidden users, orgs and repos, like GitHub. 2. Org ownership, site admin, repo and org creation, generation and transfer endpoints reject public-only tokens. 3. API pull request responses set `head.repo` to `null` and `head.repo_id` to `-1` when the caller cannot see the head repository. 4. Public-only tokens see org memberships like anonymous callers, so concealed members stay hidden. 5. Site admin access in activity feeds, follower lists, org members, Actions run lists and packages needs a session or an `all`-scoped token. Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
1 parent
7e62dda791
commit
5264304a34
96 files changed
+583
-686
No files matched your search
@@ -424,6 +424,9 @@ func GetDoerRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
// In most request paths, callers should use GetDoerRepoPermission instead.
|
||||
// Unlike GetDoerRepoPermission, this helper does not resolve Actions task users.
|
||||
func GetIndividualUserRepoPermission(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (perm Permission, err error) {
|
||||
if !repo_model.DoerTokenAllowsRepo(ctx, user, repo) {
|
||||
return PermissionNoAccess(), nil
|
||||
}
|
||||
defer func() {
|
||||
if err == nil {
|
||||
finalProcessRepoUnitPermission(user, &perm)
|
||||
@@ -675,10 +678,14 @@ func PermissionNoAccess() Permission {
|
||||
// permission on a repository. Producers and consumers must agree on it, so it lives here.
|
||||
func RepoUserPermissionCacheKey(repoID int64, doer *user_model.User) string {
|
||||
var doerID int64
|
||||
var doerExtData string
|
||||
if doer != nil {
|
||||
doerID = doer.ID
|
||||
if doer.ExtDoerData != nil {
|
||||
doerExtData = doer.ExtDoerData.EncodeToString()
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%d-%d", repoID, doerID)
|
||||
return fmt.Sprintf("%d-%d-%s", repoID, doerID, doerExtData)
|
||||
}
|
||||
|
||||
// CanReadWorkflowCrossRepo checks whether the run can read workflow files from targetRepo.
|
||||
|
||||
@@ -272,4 +272,21 @@ func testGetDoerRepoPermission(t *testing.T) {
|
||||
individualPerm, err := GetIndividualUserRepoPermission(ctx, repo1, regularUser)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, individualPerm, doerPerm)
|
||||
|
||||
t.Run("PublicOnlyTokenReachesOnlyPublicReposOfPublicOwners", func(t *testing.T) {
|
||||
publicOnlyUser := *regularUser
|
||||
publicOnlyUser.ExtDoerData = user_model.NewTokenExtDoerData(user_model.CredentialAccessToken, 1, "public-only,write:repository")
|
||||
publicOnlyAdmin := *unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
publicOnlyAdmin.ExtDoerData = publicOnlyUser.ExtDoerData
|
||||
for _, repoID := range []int64{2, 38} {
|
||||
perm, err := GetDoerRepoPermission(ctx, unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}), &publicOnlyAdmin)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, perm.HasAnyUnitAccessOrPublicAccess(), "repo %d", repoID)
|
||||
}
|
||||
|
||||
perm, err := GetDoerRepoPermission(ctx, repo1, &publicOnlyUser)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, perm.CanWrite(unit.TypeCode))
|
||||
assert.NotEqual(t, RepoUserPermissionCacheKey(repo1.ID, regularUser), RepoUserPermissionCacheKey(repo1.ID, &publicOnlyUser))
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user