forked from forgejo/forgejo
Support scoped access tokens (#20908)
This PR adds the support for scopes of access tokens, mimicking the design of GitHub OAuth scopes. The changes of the core logic are in `models/auth` that `AccessToken` struct will have a `Scope` field. The normalized (no duplication of scope), comma-separated scope string will be stored in `access_token` table in the database. In `services/auth`, the scope will be stored in context, which will be used by `reqToken` middleware in API calls. Only OAuth2 tokens will have granular token scopes, while others like BasicAuth will default to scope `all`. A large amount of work happens in `routers/api/v1/api.go` and the corresponding `tests/integration` tests, that is adding necessary scopes to each of the API calls as they fit. - [x] Add `Scope` field to `AccessToken` - [x] Add access control to all API endpoints - [x] Update frontend & backend for when creating tokens - [x] Add a database migration for `scope` column (enable 'all' access to past tokens) I'm aiming to complete it before Gitea 1.19 release. Fixes #4300
This commit is contained in:
parent
db2286bbb6
commit
de484e86bc
79 changed files with 1221 additions and 449 deletions
|
@ -12,6 +12,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
|
@ -47,7 +48,9 @@ func TestPushDeployKeyOnEmptyRepo(t *testing.T) {
|
|||
|
||||
func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
||||
// OK login
|
||||
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1")
|
||||
ctx := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo)
|
||||
ctxWithDeleteRepo := NewAPITestContext(t, "user2", "deploy-key-empty-repo-1", auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeDeleteRepo)
|
||||
|
||||
keyname := fmt.Sprintf("%s-push", ctx.Reponame)
|
||||
u.Path = ctx.GitPath()
|
||||
|
||||
|
@ -72,7 +75,7 @@ func testPushDeployKeyOnEmptyRepo(t *testing.T, u *url.URL) {
|
|||
|
||||
t.Run("CheckIsNotEmpty", doCheckRepositoryEmptyStatus(ctx, false))
|
||||
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctx))
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -89,10 +92,13 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
|||
keyname := fmt.Sprintf("%s-push", reponame)
|
||||
|
||||
// OK login
|
||||
ctx := NewAPITestContext(t, username, reponame)
|
||||
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey)
|
||||
ctxWithDeleteRepo := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeRepo, auth_model.AccessTokenScopeAdminPublicKey, auth_model.AccessTokenScopeDeleteRepo)
|
||||
|
||||
otherCtx := ctx
|
||||
otherCtx.Reponame = "ssh-key-test-repo-2"
|
||||
otherCtxWithDeleteRepo := ctxWithDeleteRepo
|
||||
otherCtxWithDeleteRepo.Reponame = otherCtx.Reponame
|
||||
|
||||
failCtx := ctx
|
||||
failCtx.ExpectedCode = http.StatusUnprocessableEntity
|
||||
|
@ -160,7 +166,7 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
|||
otherSSHURL := createSSHUrl(otherCtx.GitPath(), u)
|
||||
dstOtherPath := t.TempDir()
|
||||
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctx))
|
||||
t.Run("DeleteRepository", doAPIDeleteRepository(ctxWithDeleteRepo))
|
||||
|
||||
t.Run("FailToCreateUserKeyAsStillDeploy", doAPICreateUserKey(failCtx, keyname, keyFile))
|
||||
|
||||
|
@ -170,9 +176,9 @@ func testKeyOnlyOneType(t *testing.T, u *url.URL) {
|
|||
|
||||
t.Run("PushToOther", doGitPushTestRepository(dstOtherPath, "origin", "master"))
|
||||
|
||||
t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtx))
|
||||
t.Run("DeleteOtherRepository", doAPIDeleteRepository(otherCtxWithDeleteRepo))
|
||||
|
||||
t.Run("RecreateRepository", doAPICreateRepository(ctx, false))
|
||||
t.Run("RecreateRepository", doAPICreateRepository(ctxWithDeleteRepo, false))
|
||||
|
||||
t.Run("CreateUserKey", doAPICreateUserKey(ctx, keyname, keyFile, func(t *testing.T, publicKey api.PublicKey) {
|
||||
userKeyPublicKeyID = publicKey.ID
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue