Skip to content
21 changes: 17 additions & 4 deletions models/auth/access_token_scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
AccessTokenScopeCategoryIssue
AccessTokenScopeCategoryRepository
AccessTokenScopeCategoryUser
AccessTokenScopeCategoryCommitStatus
)

// AllAccessTokenScopeCategories contains all access token scope categories
Expand All @@ -37,6 +38,7 @@ var AllAccessTokenScopeCategories = []AccessTokenScopeCategory{
AccessTokenScopeCategoryIssue,
AccessTokenScopeCategoryRepository,
AccessTokenScopeCategoryUser,
AccessTokenScopeCategoryCommitStatus,
}

// AccessTokenScopeLevel represents the access levels without a given scope category
Expand Down Expand Up @@ -82,6 +84,9 @@ const (

AccessTokenScopeReadUser AccessTokenScope = "read:user"
AccessTokenScopeWriteUser AccessTokenScope = "write:user"

AccessTokenScopeReadCommitStatus AccessTokenScope = "read:commitstatus"
AccessTokenScopeWriteCommitStatus AccessTokenScope = "write:commitstatus"
)

// accessTokenScopeBitmap represents a bitmap of access token scopes.
Expand All @@ -93,7 +98,7 @@ const (
accessTokenScopeAllBits accessTokenScopeBitmap = accessTokenScopeWriteActivityPubBits |
accessTokenScopeWriteAdminBits | accessTokenScopeWriteMiscBits | accessTokenScopeWriteNotificationBits |
accessTokenScopeWriteOrganizationBits | accessTokenScopeWritePackageBits | accessTokenScopeWriteIssueBits |
accessTokenScopeWriteRepositoryBits | accessTokenScopeWriteUserBits
accessTokenScopeWriteRepositoryBits | accessTokenScopeWriteUserBits | accessTokenScopeWriteCommitStatusBits

accessTokenScopePublicOnlyBits accessTokenScopeBitmap = 1 << iota

Expand All @@ -118,12 +123,15 @@ const (
accessTokenScopeReadIssueBits accessTokenScopeBitmap = 1 << iota
accessTokenScopeWriteIssueBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadIssueBits

accessTokenScopeReadRepositoryBits accessTokenScopeBitmap = 1 << iota
accessTokenScopeWriteRepositoryBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadRepositoryBits
accessTokenScopeReadRepositoryBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadCommitStatusBits
accessTokenScopeWriteRepositoryBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadRepositoryBits | accessTokenScopeWriteCommitStatusBits

accessTokenScopeReadUserBits accessTokenScopeBitmap = 1 << iota
accessTokenScopeWriteUserBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadUserBits

accessTokenScopeReadCommitStatusBits accessTokenScopeBitmap = 1 << iota
accessTokenScopeWriteCommitStatusBits accessTokenScopeBitmap = 1<<iota | accessTokenScopeReadCommitStatusBits

// The current implementation only supports up to 64 token scopes.
// If we need to support > 64 scopes,
// refactoring the whole implementation in this file (and only this file) is needed.
Expand All @@ -142,6 +150,7 @@ var allAccessTokenScopes = []AccessTokenScope{
AccessTokenScopeWriteIssue, AccessTokenScopeReadIssue,
AccessTokenScopeWriteRepository, AccessTokenScopeReadRepository,
AccessTokenScopeWriteUser, AccessTokenScopeReadUser,
AccessTokenScopeWriteCommitStatus, AccessTokenScopeReadCommitStatus,
}

// allAccessTokenScopeBits contains all access token scopes.
Expand All @@ -166,6 +175,8 @@ var allAccessTokenScopeBits = map[AccessTokenScope]accessTokenScopeBitmap{
AccessTokenScopeWriteRepository: accessTokenScopeWriteRepositoryBits,
AccessTokenScopeReadUser: accessTokenScopeReadUserBits,
AccessTokenScopeWriteUser: accessTokenScopeWriteUserBits,
AccessTokenScopeReadCommitStatus: accessTokenScopeReadCommitStatusBits,
AccessTokenScopeWriteCommitStatus: accessTokenScopeWriteCommitStatusBits,
}

// readAccessTokenScopes maps a scope category to the read permission scope
Expand All @@ -180,6 +191,7 @@ var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]A
AccessTokenScopeCategoryIssue: AccessTokenScopeReadIssue,
AccessTokenScopeCategoryRepository: AccessTokenScopeReadRepository,
AccessTokenScopeCategoryUser: AccessTokenScopeReadUser,
AccessTokenScopeCategoryCommitStatus: AccessTokenScopeReadCommitStatus,
},
Write: {
AccessTokenScopeCategoryActivityPub: AccessTokenScopeWriteActivityPub,
Expand All @@ -191,6 +203,7 @@ var accessTokenScopes = map[AccessTokenScopeLevel]map[AccessTokenScopeCategory]A
AccessTokenScopeCategoryIssue: AccessTokenScopeWriteIssue,
AccessTokenScopeCategoryRepository: AccessTokenScopeWriteRepository,
AccessTokenScopeCategoryUser: AccessTokenScopeWriteUser,
AccessTokenScopeCategoryCommitStatus: AccessTokenScopeWriteCommitStatus,
},
}

Expand Down Expand Up @@ -370,7 +383,7 @@ func (bitmap accessTokenScopeBitmap) toScope() AccessTokenScope {
scope := AccessTokenScope(strings.Join(scopes, ","))
scope = AccessTokenScope(strings.ReplaceAll(
string(scope),
"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user",
"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,write:commitstatus",
"all",
))
return scope
Expand Down
6 changes: 3 additions & 3 deletions models/auth/access_token_scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ type scopeTestNormalize struct {
}

func TestAccessTokenScope_Normalize(t *testing.T) {
assert.Equal(t, []string{"activitypub", "admin", "issue", "misc", "notification", "organization", "package", "repository", "user"}, GetAccessTokenCategories())
assert.Equal(t, []string{"activitypub", "admin", "commitstatus", "issue", "misc", "notification", "organization", "package", "repository", "user"}, GetAccessTokenCategories())
tests := []scopeTestNormalize{
{"", "", nil},
{"write:misc,write:notification,read:package,write:notification,public-only", "public-only,write:misc,write:notification,read:package", nil},
{"all", "all", nil},
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user", "all", nil},
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,public-only", "public-only,all", nil},
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,write:commitstatus", "all", nil},
{"write:activitypub,write:admin,write:misc,write:notification,write:organization,write:package,write:issue,write:repository,write:user,write:commitstatus,public-only", "public-only,all", nil},
}

for _, scope := range GetAccessTokenCategories() {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ func Routes() *web.Router {
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
m.Group("/statuses", func() {
m.Combo("/{sha}").Get(repo.GetCommitStatuses).
Post(reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
Post(reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryCommitStatus), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
}, reqRepoReader(unit.TypeCode))
m.Group("/commits", func() {
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)
Expand Down
Loading