From 89d1140aad553665398fc478b7745b85dc6c0558 Mon Sep 17 00:00:00 2001 From: harryzcy Date: Fri, 26 Aug 2022 14:09:18 -0400 Subject: [PATCH] Add token scope helper functions --- models/auth/token.go | 2 +- models/token_scope.go | 148 +++++++++++++++++++++++++++++++++++++ models/token_scope_test.go | 27 +++++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 models/token_scope.go create mode 100644 models/token_scope_test.go diff --git a/models/auth/token.go b/models/auth/token.go index 86e3830d71..0401175ae8 100644 --- a/models/auth/token.go +++ b/models/auth/token.go @@ -59,7 +59,7 @@ type AccessToken struct { TokenHash string `xorm:"UNIQUE"` // sha256 of token TokenSalt string TokenLastEight string `xorm:"token_last_eight"` - Scope string + Scope AccessTokenScope CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` diff --git a/models/token_scope.go b/models/token_scope.go new file mode 100644 index 0000000000..565c52d83d --- /dev/null +++ b/models/token_scope.go @@ -0,0 +1,148 @@ +package models + +import ( + "fmt" + "strings" +) + +type AccessTokenScope string + +const ( + AccessTokenScopeRepo = "repo" + AccessTokenScopeRepoStatus = "repo:status" + AccessTokenScopePublicRepo = "public_repo" + + AccessTokenScopeAdminOrg = "admin:org" + AccessTokenScopeWriteOrg = "write:org" + AccessTokenScopeReadOrg = "read:org" + + AccessTokenScopeAdminPublicKey = "admin:public_key" + AccessTokenScopeWritePublicKey = "write:public_key" + AccessTokenScopeReadPublicKey = "read:public_key" + + AccessTokenScopeAdminRepoHook = "admin:repo_hook" + AccessTokenScopeWriteRepoHook = "write:repo_hook" + AccessTokenScopeReadRepoHook = "read:repo_hook" + + AccessTokenScopeAdminOrgHook = "admin:org_hook" + + AccessTokenScopeNotification = "notification" + + AccessTokenScopeUser = "user" + AccessTokenScopeReadUser = "read:user" + AccessTokenScopeUserEmail = "user:email" + AccessTokenScopeUserFollow = "user:follow" + + AccessTokenScopeDeleteRepo = "delete_repo" + + AccessTokenScopePackage = "package" + AccessTokenScopeWritePackage = "write:package" + AccessTokenScopeReadPackage = "read:package" + AccessTokenScopeDeletePackage = "delete:package" + + AccessTokenScopeAdminGPGKey = "admin:gpg_key" + AccessTokenScopeWriteGPGKey = "write:gpg_key" + AccessTokenScopeReadGPGKey = "read:gpg_key" +) + +// AllAccessTokenScopes contains all access token scopes. +// The order is important: parent scope must precedes child scopes. +var AllAccessTokenScopes = []string{ + AccessTokenScopeRepo, AccessTokenScopeRepoStatus, AccessTokenScopePublicRepo, + AccessTokenScopeAdminOrg, AccessTokenScopeWriteOrg, AccessTokenScopeReadOrg, + AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey, + AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook, + AccessTokenScopeAdminOrgHook, + AccessTokenScopeNotification, + AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow, + AccessTokenScopeDeleteRepo, + AccessTokenScopePackage, AccessTokenScopeWritePackage, AccessTokenScopeReadPackage, AccessTokenScopeDeletePackage, + AccessTokenScopeAdminGPGKey, AccessTokenScopeWriteGPGKey, AccessTokenScopeReadGPGKey, +} + +func (s AccessTokenScope) Parse() (AccessTokenScopeBitmap, error) { + list := strings.Split(string(s), ",") + + var bitmap AccessTokenScopeBitmap + for _, v := range list { + if v == "" { + continue + } + + idx := sliceIndex(AllAccessTokenScopes, v) + if idx < 0 { + return 0, fmt.Errorf("invalid access token scope: %s", v) + } + bitmap |= 1 << uint(idx) + } + return bitmap, nil +} + +func (s AccessTokenScope) Normalize() (AccessTokenScope, error) { + bitmap, err := s.Parse() + if err != nil { + return "", err + } + + return bitmap.ToScope(), nil +} + +type AccessTokenScopeBitmap uint64 + +func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope { + var scopes []string + + groupedScope := make(map[string]struct{}) + for i, v := range AllAccessTokenScopes { + if bitmap&(1<