mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-15 23:40:26 +00:00
Built on #12266; one commit added. Adds the ability to reduce the authorization scope of an authorized integration to public-only resources and repo-specific resources. Backend only -- no frontend created yet. ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests for Go changes - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I ran... - [x] `make pr-go` before pushing ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change. - [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12267 Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package authz
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"forgejo.org/models/perm"
|
|
repo_model "forgejo.org/models/repo"
|
|
"forgejo.org/modules/structs"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// For specific repositories listed in [AccessTokenResourceRepo] models, all access is permitted. For public
|
|
// repositories that aren't listed among the specific repos, read-only access is permitted. For all other repos, no
|
|
// access is permitted.
|
|
type SpecificReposAuthorizationReducer struct {
|
|
resourceRepos []RepoGetter
|
|
}
|
|
|
|
type RepoGetter interface {
|
|
GetTargetRepoID() int64
|
|
}
|
|
|
|
func (r *SpecificReposAuthorizationReducer) ReduceRepoAccess(ctx context.Context, repo *repo_model.Repository, accessMode perm.AccessMode) (perm.AccessMode, error) {
|
|
for _, tokenRepo := range r.resourceRepos {
|
|
if tokenRepo.GetTargetRepoID() == repo.ID {
|
|
// No restrictions as this repo is within the scope of the access token.
|
|
return accessMode, nil
|
|
}
|
|
}
|
|
|
|
if err := repo.LoadOwner(ctx); err != nil {
|
|
return 0, fmt.Errorf("failed to LoadOwner during ReduceRepoAccess: %w", err)
|
|
}
|
|
|
|
// Fine-grained access tokens remove access to any private repositories, or repository owned by non-public users,
|
|
// that aren't listed in their resource list.
|
|
if !repo.Owner.Visibility.IsPublic() || repo.IsPrivate {
|
|
return perm.AccessModeNone, nil
|
|
}
|
|
|
|
// Public repos will be reduced to read access.
|
|
return min(accessMode, perm.AccessModeRead), nil
|
|
}
|
|
|
|
func (r *SpecificReposAuthorizationReducer) RepoReadAccessFilter() builder.Cond {
|
|
repoIDs := make([]int64, len(r.resourceRepos))
|
|
for i, tokenRepo := range r.resourceRepos {
|
|
repoIDs[i] = tokenRepo.GetTargetRepoID()
|
|
}
|
|
targetRepos := builder.In("repository.id", repoIDs)
|
|
|
|
// We should also be able to see all non-private repositories that aren't in a private or limited organization.
|
|
return builder.Or(
|
|
targetRepos,
|
|
builder.And(
|
|
builder.Eq{"repository.is_private": false},
|
|
builder.NotIn("repository.owner_id", builder.Select("id").From("`user`").Where(
|
|
builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
|
|
))))
|
|
}
|
|
|
|
func (*SpecificReposAuthorizationReducer) AllowAdminOverride() bool {
|
|
return false
|
|
}
|