mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
feat: backend DB model for fine-grained repo access tokens
This commit is contained in:
parent
2d4a3e5658
commit
a1eff6f0dc
13 changed files with 166 additions and 1 deletions
|
|
@ -0,0 +1,9 @@
|
|||
- token_id: 3
|
||||
repo_id: 1
|
||||
created_unix: 1772158384
|
||||
- token_id: 3
|
||||
repo_id: 2
|
||||
created_unix: 1772158384
|
||||
- token_id: 3
|
||||
repo_id: 3
|
||||
created_unix: 1772158384
|
||||
|
|
@ -73,6 +73,8 @@ type AccessToken struct {
|
|||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
|
||||
ResourceAllRepos bool `xorm:"NOT NULL DEFAULT TRUE"` // flag for whether AccessTokenResourceRepo instances will limit the resources this access token can access (false) or won't limit them (true).
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
|
|
|
|||
36
models/auth/access_token_resource.go
Normal file
36
models/auth/access_token_resource.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/modules/timeutil"
|
||||
)
|
||||
|
||||
// Represents a many-to-many join table which indicates specific repositories (RepoID) that can be accessed by an access
|
||||
// token (TokenID). An access token's ResourceAllRepos field must be false for records in this table to become active.
|
||||
type AccessTokenResourceRepo struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
TokenID int64 `xorm:"NOT NULL REFERENCES(access_token, id)"` // needs to be shortened from "AccessTokenID" for the index to fit MySQL table identifier length restrictions
|
||||
RepoID int64 `xorm:"NOT NULL REFERENCES(repository, id)"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(AccessTokenResourceRepo))
|
||||
}
|
||||
|
||||
func GetRepositoriesAccessibleWithToken(ctx context.Context, accessTokenID int64) ([]*AccessTokenResourceRepo, error) {
|
||||
var resources []*AccessTokenResourceRepo
|
||||
err := db.GetEngine(ctx).
|
||||
Where("token_id = ?", accessTokenID).
|
||||
Find(&resources)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
41
models/auth/access_token_resource_test.go
Normal file
41
models/auth/access_token_resource_test.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
auth_model "forgejo.org/models/auth"
|
||||
"forgejo.org/models/db"
|
||||
"forgejo.org/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetRepositoriesAccessibleWithToken(t *testing.T) {
|
||||
defer unittest.OverrideFixtures("models/auth/TestGetRepositoriesAccessibleWithToken")()
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
t.Run("No Resources", func(t *testing.T) {
|
||||
resources, err := auth_model.GetRepositoriesAccessibleWithToken(db.DefaultContext, 999)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, resources)
|
||||
})
|
||||
|
||||
t.Run("Has Resources", func(t *testing.T) {
|
||||
resources, err := auth_model.GetRepositoriesAccessibleWithToken(db.DefaultContext, 3)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resources, 3)
|
||||
|
||||
// Verify all expected repo IDs are present
|
||||
repoIDs := make([]int64, len(resources))
|
||||
for i, res := range resources {
|
||||
repoIDs[i] = res.RepoID
|
||||
}
|
||||
assert.Contains(t, repoIDs, int64(1))
|
||||
assert.Contains(t, repoIDs, int64(2))
|
||||
assert.Contains(t, repoIDs, int64(3))
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMigration(&Migration{
|
||||
Description: "add resource_all_owned_repositories to table access_token",
|
||||
Upgrade: addAllOwnedRepositoriesToAccessToken,
|
||||
})
|
||||
}
|
||||
|
||||
func addAllOwnedRepositoriesToAccessToken(x *xorm.Engine) error {
|
||||
type AccessToken struct {
|
||||
ResourceAllRepos bool `xorm:"NOT NULL DEFAULT TRUE"`
|
||||
}
|
||||
_, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, new(AccessToken))
|
||||
return err
|
||||
}
|
||||
29
models/forgejo_migrations/v15b_add-access_token_resource.go
Normal file
29
models/forgejo_migrations/v15b_add-access_token_resource.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forgejo_migrations
|
||||
|
||||
import (
|
||||
"forgejo.org/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMigration(&Migration{
|
||||
Description: "add access_token_resource table",
|
||||
Upgrade: addAccessTokenResource,
|
||||
})
|
||||
}
|
||||
|
||||
func addAccessTokenResource(x *xorm.Engine) error {
|
||||
type AccessTokenResourceRepo struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
TokenID int64 `xorm:"NOT NULL REFERENCES(access_token, id)"` // needs to be shortened from "AccessTokenID" for the index to fit MySQL table identifier length restrictions
|
||||
RepoID int64 `xorm:"NOT NULL REFERENCES(repository, id)"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
|
||||
}
|
||||
_, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, new(AccessTokenResourceRepo))
|
||||
return err
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue