Browse Source

all: unwrap `database.PermissionsStore` interface (#7701)

Joe Chen 11 months ago
parent
commit
5cf0189df1

+ 1 - 1
internal/cmd/serv.go

@@ -210,7 +210,7 @@ func runServ(c *cli.Context) error {
 				fail("Internal error", "Failed to get user by key ID '%d': %v", key.ID, err)
 			}
 
-			mode := database.Perms.AccessMode(ctx, user.ID, repo.ID,
+			mode := database.Handle.Permissions().AccessMode(ctx, user.ID, repo.ID,
 				database.AccessModeOptions{
 					OwnerID: repo.OwnerID,
 					Private: repo.IsPrivate,

+ 2 - 2
internal/context/repo.go

@@ -171,7 +171,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		if c.IsLogged && c.User.IsAdmin {
 			c.Repo.AccessMode = database.AccessModeOwner
 		} else {
-			c.Repo.AccessMode = database.Perms.AccessMode(c.Req.Context(), c.UserID(), repo.ID,
+			c.Repo.AccessMode = database.Handle.Permissions().AccessMode(c.Req.Context(), c.UserID(), repo.ID,
 				database.AccessModeOptions{
 					OwnerID: repo.OwnerID,
 					Private: repo.IsPrivate,
@@ -182,7 +182,7 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		// If the authenticated user has no direct access, see if the repository is a fork
 		// and whether the user has access to the base repository.
 		if c.Repo.AccessMode == database.AccessModeNone && repo.BaseRepo != nil {
-			mode := database.Perms.AccessMode(c.Req.Context(), c.UserID(), repo.BaseRepo.ID,
+			mode := database.Handle.Permissions().AccessMode(c.Req.Context(), c.UserID(), repo.BaseRepo.ID,
 				database.AccessModeOptions{
 					OwnerID: repo.BaseRepo.OwnerID,
 					Private: repo.BaseRepo.IsPrivate,

+ 4 - 1
internal/database/database.go

@@ -123,7 +123,6 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
 	}
 
 	// Initialize stores, sorted in alphabetical order.
-	Perms = NewPermsStore(db)
 	Repos = NewReposStore(db)
 	TwoFactors = &twoFactorsStore{DB: db}
 	Users = NewUsersStore(db)
@@ -176,3 +175,7 @@ func (db *DB) Notices() *NoticesStore {
 func (db *DB) Organizations() *OrganizationsStore {
 	return newOrganizationsStoreStore(db.db)
 }
+
+func (db *DB) Permissions() *PermissionsStore {
+	return newPermissionsStore(db.db)
+}

+ 0 - 8
internal/database/mocks.go

@@ -8,14 +8,6 @@ import (
 	"testing"
 )
 
-func SetMockPermsStore(t *testing.T, mock PermsStore) {
-	before := Perms
-	Perms = mock
-	t.Cleanup(func() {
-		Perms = before
-	})
-}
-
 func SetMockReposStore(t *testing.T, mock ReposStore) {
 	before := Repos
 	Repos = mock

+ 17 - 28
internal/database/perms.go → internal/database/permissions.go

@@ -7,24 +7,11 @@ package database
 import (
 	"context"
 
+	"github.com/pkg/errors"
 	"gorm.io/gorm"
 	log "unknwon.dev/clog/v2"
 )
 
-// PermsStore is the persistent interface for permissions.
-type PermsStore interface {
-	// AccessMode returns the access mode of given user has to the repository.
-	AccessMode(ctx context.Context, userID, repoID int64, opts AccessModeOptions) AccessMode
-	// Authorize returns true if the user has as good as desired access mode to the
-	// repository.
-	Authorize(ctx context.Context, userID, repoID int64, desired AccessMode, opts AccessModeOptions) bool
-	// SetRepoPerms does a full update to which users have which level of access to
-	// given repository. Keys of the "accessMap" are user IDs.
-	SetRepoPerms(ctx context.Context, repoID int64, accessMap map[int64]AccessMode) error
-}
-
-var Perms PermsStore
-
 // Access represents the highest access level of a user has to a repository. The
 // only access type that is not in this table is the real owner of a repository.
 // In case of an organization repository, the members of the owners team are in
@@ -74,16 +61,13 @@ func ParseAccessMode(permission string) AccessMode {
 	}
 }
 
-var _ PermsStore = (*permsStore)(nil)
-
-type permsStore struct {
-	*gorm.DB
+// PermissionsStore is the storage layer for repository permissions.
+type PermissionsStore struct {
+	db *gorm.DB
 }
 
-// NewPermsStore returns a persistent interface for permissions with given
-// database connection.
-func NewPermsStore(db *gorm.DB) PermsStore {
-	return &permsStore{DB: db}
+func newPermissionsStore(db *gorm.DB) *PermissionsStore {
+	return &PermissionsStore{db: db}
 }
 
 type AccessModeOptions struct {
@@ -91,7 +75,8 @@ type AccessModeOptions struct {
 	Private bool  // Whether the repository is private.
 }
 
-func (s *permsStore) AccessMode(ctx context.Context, userID, repoID int64, opts AccessModeOptions) (mode AccessMode) {
+// AccessMode returns the access mode of given user has to the repository.
+func (s *PermissionsStore) AccessMode(ctx context.Context, userID, repoID int64, opts AccessModeOptions) (mode AccessMode) {
 	if repoID <= 0 {
 		return AccessModeNone
 	}
@@ -111,9 +96,9 @@ func (s *permsStore) AccessMode(ctx context.Context, userID, repoID int64, opts
 	}
 
 	access := new(Access)
-	err := s.WithContext(ctx).Where("user_id = ? AND repo_id = ?", userID, repoID).First(access).Error
+	err := s.db.WithContext(ctx).Where("user_id = ? AND repo_id = ?", userID, repoID).First(access).Error
 	if err != nil {
-		if err != gorm.ErrRecordNotFound {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
 			log.Error("Failed to get access [user_id: %d, repo_id: %d]: %v", userID, repoID, err)
 		}
 		return mode
@@ -121,11 +106,15 @@ func (s *permsStore) AccessMode(ctx context.Context, userID, repoID int64, opts
 	return access.Mode
 }
 
-func (s *permsStore) Authorize(ctx context.Context, userID, repoID int64, desired AccessMode, opts AccessModeOptions) bool {
+// Authorize returns true if the user has as good as desired access mode to the
+// repository.
+func (s *PermissionsStore) Authorize(ctx context.Context, userID, repoID int64, desired AccessMode, opts AccessModeOptions) bool {
 	return desired <= s.AccessMode(ctx, userID, repoID, opts)
 }
 
-func (s *permsStore) SetRepoPerms(ctx context.Context, repoID int64, accessMap map[int64]AccessMode) error {
+// SetRepoPerms does a full update to which users have which level of access to
+// given repository. Keys of the "accessMap" are user IDs.
+func (s *PermissionsStore) SetRepoPerms(ctx context.Context, repoID int64, accessMap map[int64]AccessMode) error {
 	records := make([]*Access, 0, len(accessMap))
 	for userID, mode := range accessMap {
 		records = append(records, &Access{
@@ -135,7 +124,7 @@ func (s *permsStore) SetRepoPerms(ctx context.Context, repoID int64, accessMap m
 		})
 	}
 
-	return s.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
+	return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
 		err := tx.Where("repo_id = ?", repoID).Delete(new(Access)).Error
 		if err != nil {
 			return err

+ 15 - 15
internal/database/perms_test.go → internal/database/permissions_test.go

@@ -19,13 +19,13 @@ func TestPerms(t *testing.T) {
 	t.Parallel()
 
 	ctx := context.Background()
-	db := &permsStore{
-		DB: newTestDB(t, "permsStore"),
+	s := &PermissionsStore{
+		db: newTestDB(t, "PermissionsStore"),
 	}
 
 	for _, tc := range []struct {
 		name string
-		test func(t *testing.T, ctx context.Context, db *permsStore)
+		test func(t *testing.T, ctx context.Context, s *PermissionsStore)
 	}{
 		{"AccessMode", permsAccessMode},
 		{"Authorize", permsAuthorize},
@@ -33,10 +33,10 @@ func TestPerms(t *testing.T) {
 	} {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Cleanup(func() {
-				err := clearTables(t, db.DB)
+				err := clearTables(t, s.db)
 				require.NoError(t, err)
 			})
-			tc.test(t, ctx, db)
+			tc.test(t, ctx, s)
 		})
 		if t.Failed() {
 			break
@@ -44,16 +44,16 @@ func TestPerms(t *testing.T) {
 	}
 }
 
-func permsAccessMode(t *testing.T, ctx context.Context, db *permsStore) {
+func permsAccessMode(t *testing.T, ctx context.Context, s *PermissionsStore) {
 	// Set up permissions
-	err := db.SetRepoPerms(ctx, 1,
+	err := s.SetRepoPerms(ctx, 1,
 		map[int64]AccessMode{
 			2: AccessModeWrite,
 			3: AccessModeAdmin,
 		},
 	)
 	require.NoError(t, err)
-	err = db.SetRepoPerms(ctx, 2,
+	err = s.SetRepoPerms(ctx, 2,
 		map[int64]AccessMode{
 			1: AccessModeRead,
 		},
@@ -149,15 +149,15 @@ func permsAccessMode(t *testing.T, ctx context.Context, db *permsStore) {
 	}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			mode := db.AccessMode(ctx, test.userID, test.repoID, test.opts)
+			mode := s.AccessMode(ctx, test.userID, test.repoID, test.opts)
 			assert.Equal(t, test.wantAccessMode, mode)
 		})
 	}
 }
 
-func permsAuthorize(t *testing.T, ctx context.Context, db *permsStore) {
+func permsAuthorize(t *testing.T, ctx context.Context, s *PermissionsStore) {
 	// Set up permissions
-	err := db.SetRepoPerms(ctx, 1,
+	err := s.SetRepoPerms(ctx, 1,
 		map[int64]AccessMode{
 			1: AccessModeRead,
 			2: AccessModeWrite,
@@ -230,7 +230,7 @@ func permsAuthorize(t *testing.T, ctx context.Context, db *permsStore) {
 	}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			authorized := db.Authorize(ctx, test.userID, repo.ID, test.desired,
+			authorized := s.Authorize(ctx, test.userID, repo.ID, test.desired,
 				AccessModeOptions{
 					OwnerID: repo.OwnerID,
 					Private: repo.IsPrivate,
@@ -241,7 +241,7 @@ func permsAuthorize(t *testing.T, ctx context.Context, db *permsStore) {
 	}
 }
 
-func permsSetRepoPerms(t *testing.T, ctx context.Context, db *permsStore) {
+func permsSetRepoPerms(t *testing.T, ctx context.Context, s *PermissionsStore) {
 	for _, update := range []struct {
 		repoID    int64
 		accessMap map[int64]AccessMode
@@ -280,14 +280,14 @@ func permsSetRepoPerms(t *testing.T, ctx context.Context, db *permsStore) {
 			},
 		},
 	} {
-		err := db.SetRepoPerms(ctx, update.repoID, update.accessMap)
+		err := s.SetRepoPerms(ctx, update.repoID, update.accessMap)
 		if err != nil {
 			t.Fatal(err)
 		}
 	}
 
 	var accesses []*Access
-	err := db.Order("user_id, repo_id").Find(&accesses).Error
+	err := s.db.Order("user_id, repo_id").Find(&accesses).Error
 	require.NoError(t, err)
 
 	// Ignore ID fields

+ 3 - 3
internal/database/repo.go

@@ -392,7 +392,7 @@ func (repo *Repository) APIFormatLegacy(permission *api.Permission, user ...*Use
 	if repo.IsFork {
 		p := &api.Permission{Pull: true}
 		if len(user) != 0 {
-			accessMode := Perms.AccessMode(
+			accessMode := Handle.Permissions().AccessMode(
 				context.TODO(),
 				user[0].ID,
 				repo.ID,
@@ -530,7 +530,7 @@ func (repo *Repository) GetAssignees() (_ []*User, err error) {
 // GetAssigneeByID returns the user that has write access of repository by given ID.
 func (repo *Repository) GetAssigneeByID(userID int64) (*User, error) {
 	ctx := context.TODO()
-	if !Perms.Authorize(
+	if !Handle.Permissions().Authorize(
 		ctx,
 		userID,
 		repo.ID,
@@ -592,7 +592,7 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin
 }
 
 func (repo *Repository) HasAccess(userID int64) bool {
-	return Perms.Authorize(context.TODO(), userID, repo.ID, AccessModeRead,
+	return Handle.Permissions().Authorize(context.TODO(), userID, repo.ID, AccessModeRead,
 		AccessModeOptions{
 			OwnerID: repo.OwnerID,
 			Private: repo.IsPrivate,

+ 1 - 1
internal/database/repo_branch.go

@@ -176,7 +176,7 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit
 		userIDs := tool.StringsToInt64s(strings.Split(whitelistUserIDs, ","))
 		validUserIDs = make([]int64, 0, len(userIDs))
 		for _, userID := range userIDs {
-			if !Perms.Authorize(context.TODO(), userID, repo.ID, AccessModeWrite,
+			if !Handle.Permissions().Authorize(context.TODO(), userID, repo.ID, AccessModeWrite,
 				AccessModeOptions{
 					OwnerID: repo.OwnerID,
 					Private: repo.IsPrivate,

+ 7 - 7
internal/database/repos_test.go

@@ -165,10 +165,10 @@ func reposGetByCollaboratorID(t *testing.T, ctx context.Context, db *reposStore)
 	repo2, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
 	require.NoError(t, err)
 
-	permsStore := NewPermsStore(db.DB)
-	err = permsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
+	permissionsStore := newPermissionsStore(db.DB)
+	err = permissionsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
 	require.NoError(t, err)
-	err = permsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{4: AccessModeAdmin})
+	err = permissionsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{4: AccessModeAdmin})
 	require.NoError(t, err)
 
 	t.Run("user 3 is a collaborator of repo1", func(t *testing.T) {
@@ -193,12 +193,12 @@ func reposGetByCollaboratorIDWithAccessMode(t *testing.T, ctx context.Context, d
 	repo3, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo3"})
 	require.NoError(t, err)
 
-	permsStore := NewPermsStore(db.DB)
-	err = permsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
+	permissionsStore := newPermissionsStore(db.DB)
+	err = permissionsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
 	require.NoError(t, err)
-	err = permsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{3: AccessModeAdmin, 4: AccessModeWrite})
+	err = permissionsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{3: AccessModeAdmin, 4: AccessModeWrite})
 	require.NoError(t, err)
-	err = permsStore.SetRepoPerms(ctx, repo3.ID, map[int64]AccessMode{4: AccessModeWrite})
+	err = permissionsStore.SetRepoPerms(ctx, repo3.ID, map[int64]AccessMode{4: AccessModeWrite})
 	require.NoError(t, err)
 
 	got, err := db.GetByCollaboratorIDWithAccessMode(ctx, 3)

+ 1 - 1
internal/database/ssh_key.go

@@ -754,7 +754,7 @@ func DeleteDeployKey(doer *User, id int64) error {
 		if err != nil {
 			return fmt.Errorf("GetRepositoryByID: %v", err)
 		}
-		if !Perms.Authorize(context.TODO(), doer.ID, repo.ID, AccessModeAdmin,
+		if !Handle.Permissions().Authorize(context.TODO(), doer.ID, repo.ID, AccessModeAdmin,
 			AccessModeOptions{
 				OwnerID: repo.OwnerID,
 				Private: repo.IsPrivate,

+ 1 - 1
internal/route/api/v1/api.go

@@ -57,7 +57,7 @@ func repoAssignment() macaron.Handler {
 		if c.IsTokenAuth && c.User.IsAdmin {
 			c.Repo.AccessMode = database.AccessModeOwner
 		} else {
-			c.Repo.AccessMode = database.Perms.AccessMode(c.Req.Context(), c.UserID(), repo.ID,
+			c.Repo.AccessMode = database.Handle.Permissions().AccessMode(c.Req.Context(), c.UserID(), repo.ID,
 				database.AccessModeOptions{
 					OwnerID: repo.OwnerID,
 					Private: repo.IsPrivate,

+ 1 - 1
internal/route/api/v1/repo/repo.go

@@ -353,7 +353,7 @@ func ListForks(c *context.APIContext) {
 			return
 		}
 
-		accessMode := database.Perms.AccessMode(
+		accessMode := database.Handle.Permissions().AccessMode(
 			c.Req.Context(),
 			c.User.ID,
 			forks[i].ID,

+ 133 - 407
internal/route/lfs/mocks_test.go

@@ -14,413 +14,6 @@ import (
 	lfsutil "gogs.io/gogs/internal/lfsutil"
 )
 
-// MockPermsStore is a mock implementation of the PermsStore interface (from
-// the package gogs.io/gogs/internal/database) used for unit testing.
-type MockPermsStore struct {
-	// AccessModeFunc is an instance of a mock function object controlling
-	// the behavior of the method AccessMode.
-	AccessModeFunc *PermsStoreAccessModeFunc
-	// AuthorizeFunc is an instance of a mock function object controlling
-	// the behavior of the method Authorize.
-	AuthorizeFunc *PermsStoreAuthorizeFunc
-	// SetRepoPermsFunc is an instance of a mock function object controlling
-	// the behavior of the method SetRepoPerms.
-	SetRepoPermsFunc *PermsStoreSetRepoPermsFunc
-}
-
-// NewMockPermsStore creates a new mock of the PermsStore interface. All
-// methods return zero values for all results, unless overwritten.
-func NewMockPermsStore() *MockPermsStore {
-	return &MockPermsStore{
-		AccessModeFunc: &PermsStoreAccessModeFunc{
-			defaultHook: func(context.Context, int64, int64, database.AccessModeOptions) (r0 database.AccessMode) {
-				return
-			},
-		},
-		AuthorizeFunc: &PermsStoreAuthorizeFunc{
-			defaultHook: func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) (r0 bool) {
-				return
-			},
-		},
-		SetRepoPermsFunc: &PermsStoreSetRepoPermsFunc{
-			defaultHook: func(context.Context, int64, map[int64]database.AccessMode) (r0 error) {
-				return
-			},
-		},
-	}
-}
-
-// NewStrictMockPermsStore creates a new mock of the PermsStore interface.
-// All methods panic on invocation, unless overwritten.
-func NewStrictMockPermsStore() *MockPermsStore {
-	return &MockPermsStore{
-		AccessModeFunc: &PermsStoreAccessModeFunc{
-			defaultHook: func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode {
-				panic("unexpected invocation of MockPermsStore.AccessMode")
-			},
-		},
-		AuthorizeFunc: &PermsStoreAuthorizeFunc{
-			defaultHook: func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
-				panic("unexpected invocation of MockPermsStore.Authorize")
-			},
-		},
-		SetRepoPermsFunc: &PermsStoreSetRepoPermsFunc{
-			defaultHook: func(context.Context, int64, map[int64]database.AccessMode) error {
-				panic("unexpected invocation of MockPermsStore.SetRepoPerms")
-			},
-		},
-	}
-}
-
-// NewMockPermsStoreFrom creates a new mock of the MockPermsStore interface.
-// All methods delegate to the given implementation, unless overwritten.
-func NewMockPermsStoreFrom(i database.PermsStore) *MockPermsStore {
-	return &MockPermsStore{
-		AccessModeFunc: &PermsStoreAccessModeFunc{
-			defaultHook: i.AccessMode,
-		},
-		AuthorizeFunc: &PermsStoreAuthorizeFunc{
-			defaultHook: i.Authorize,
-		},
-		SetRepoPermsFunc: &PermsStoreSetRepoPermsFunc{
-			defaultHook: i.SetRepoPerms,
-		},
-	}
-}
-
-// PermsStoreAccessModeFunc describes the behavior when the AccessMode
-// method of the parent MockPermsStore instance is invoked.
-type PermsStoreAccessModeFunc struct {
-	defaultHook func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode
-	hooks       []func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode
-	history     []PermsStoreAccessModeFuncCall
-	mutex       sync.Mutex
-}
-
-// AccessMode delegates to the next hook function in the queue and stores
-// the parameter and result values of this invocation.
-func (m *MockPermsStore) AccessMode(v0 context.Context, v1 int64, v2 int64, v3 database.AccessModeOptions) database.AccessMode {
-	r0 := m.AccessModeFunc.nextHook()(v0, v1, v2, v3)
-	m.AccessModeFunc.appendCall(PermsStoreAccessModeFuncCall{v0, v1, v2, v3, r0})
-	return r0
-}
-
-// SetDefaultHook sets function that is called when the AccessMode method of
-// the parent MockPermsStore instance is invoked and the hook queue is
-// empty.
-func (f *PermsStoreAccessModeFunc) SetDefaultHook(hook func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode) {
-	f.defaultHook = hook
-}
-
-// PushHook adds a function to the end of hook queue. Each invocation of the
-// AccessMode method of the parent MockPermsStore instance invokes the hook
-// at the front of the queue and discards it. After the queue is empty, the
-// default hook function is invoked for any future action.
-func (f *PermsStoreAccessModeFunc) PushHook(hook func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode) {
-	f.mutex.Lock()
-	f.hooks = append(f.hooks, hook)
-	f.mutex.Unlock()
-}
-
-// SetDefaultReturn calls SetDefaultHook with a function that returns the
-// given values.
-func (f *PermsStoreAccessModeFunc) SetDefaultReturn(r0 database.AccessMode) {
-	f.SetDefaultHook(func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode {
-		return r0
-	})
-}
-
-// PushReturn calls PushHook with a function that returns the given values.
-func (f *PermsStoreAccessModeFunc) PushReturn(r0 database.AccessMode) {
-	f.PushHook(func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode {
-		return r0
-	})
-}
-
-func (f *PermsStoreAccessModeFunc) nextHook() func(context.Context, int64, int64, database.AccessModeOptions) database.AccessMode {
-	f.mutex.Lock()
-	defer f.mutex.Unlock()
-
-	if len(f.hooks) == 0 {
-		return f.defaultHook
-	}
-
-	hook := f.hooks[0]
-	f.hooks = f.hooks[1:]
-	return hook
-}
-
-func (f *PermsStoreAccessModeFunc) appendCall(r0 PermsStoreAccessModeFuncCall) {
-	f.mutex.Lock()
-	f.history = append(f.history, r0)
-	f.mutex.Unlock()
-}
-
-// History returns a sequence of PermsStoreAccessModeFuncCall objects
-// describing the invocations of this function.
-func (f *PermsStoreAccessModeFunc) History() []PermsStoreAccessModeFuncCall {
-	f.mutex.Lock()
-	history := make([]PermsStoreAccessModeFuncCall, len(f.history))
-	copy(history, f.history)
-	f.mutex.Unlock()
-
-	return history
-}
-
-// PermsStoreAccessModeFuncCall is an object that describes an invocation of
-// method AccessMode on an instance of MockPermsStore.
-type PermsStoreAccessModeFuncCall struct {
-	// Arg0 is the value of the 1st argument passed to this method
-	// invocation.
-	Arg0 context.Context
-	// Arg1 is the value of the 2nd argument passed to this method
-	// invocation.
-	Arg1 int64
-	// Arg2 is the value of the 3rd argument passed to this method
-	// invocation.
-	Arg2 int64
-	// Arg3 is the value of the 4th argument passed to this method
-	// invocation.
-	Arg3 database.AccessModeOptions
-	// Result0 is the value of the 1st result returned from this method
-	// invocation.
-	Result0 database.AccessMode
-}
-
-// Args returns an interface slice containing the arguments of this
-// invocation.
-func (c PermsStoreAccessModeFuncCall) Args() []interface{} {
-	return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3}
-}
-
-// Results returns an interface slice containing the results of this
-// invocation.
-func (c PermsStoreAccessModeFuncCall) Results() []interface{} {
-	return []interface{}{c.Result0}
-}
-
-// PermsStoreAuthorizeFunc describes the behavior when the Authorize method
-// of the parent MockPermsStore instance is invoked.
-type PermsStoreAuthorizeFunc struct {
-	defaultHook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool
-	hooks       []func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool
-	history     []PermsStoreAuthorizeFuncCall
-	mutex       sync.Mutex
-}
-
-// Authorize delegates to the next hook function in the queue and stores the
-// parameter and result values of this invocation.
-func (m *MockPermsStore) Authorize(v0 context.Context, v1 int64, v2 int64, v3 database.AccessMode, v4 database.AccessModeOptions) bool {
-	r0 := m.AuthorizeFunc.nextHook()(v0, v1, v2, v3, v4)
-	m.AuthorizeFunc.appendCall(PermsStoreAuthorizeFuncCall{v0, v1, v2, v3, v4, r0})
-	return r0
-}
-
-// SetDefaultHook sets function that is called when the Authorize method of
-// the parent MockPermsStore instance is invoked and the hook queue is
-// empty.
-func (f *PermsStoreAuthorizeFunc) SetDefaultHook(hook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool) {
-	f.defaultHook = hook
-}
-
-// PushHook adds a function to the end of hook queue. Each invocation of the
-// Authorize method of the parent MockPermsStore instance invokes the hook
-// at the front of the queue and discards it. After the queue is empty, the
-// default hook function is invoked for any future action.
-func (f *PermsStoreAuthorizeFunc) PushHook(hook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool) {
-	f.mutex.Lock()
-	f.hooks = append(f.hooks, hook)
-	f.mutex.Unlock()
-}
-
-// SetDefaultReturn calls SetDefaultHook with a function that returns the
-// given values.
-func (f *PermsStoreAuthorizeFunc) SetDefaultReturn(r0 bool) {
-	f.SetDefaultHook(func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
-		return r0
-	})
-}
-
-// PushReturn calls PushHook with a function that returns the given values.
-func (f *PermsStoreAuthorizeFunc) PushReturn(r0 bool) {
-	f.PushHook(func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
-		return r0
-	})
-}
-
-func (f *PermsStoreAuthorizeFunc) nextHook() func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
-	f.mutex.Lock()
-	defer f.mutex.Unlock()
-
-	if len(f.hooks) == 0 {
-		return f.defaultHook
-	}
-
-	hook := f.hooks[0]
-	f.hooks = f.hooks[1:]
-	return hook
-}
-
-func (f *PermsStoreAuthorizeFunc) appendCall(r0 PermsStoreAuthorizeFuncCall) {
-	f.mutex.Lock()
-	f.history = append(f.history, r0)
-	f.mutex.Unlock()
-}
-
-// History returns a sequence of PermsStoreAuthorizeFuncCall objects
-// describing the invocations of this function.
-func (f *PermsStoreAuthorizeFunc) History() []PermsStoreAuthorizeFuncCall {
-	f.mutex.Lock()
-	history := make([]PermsStoreAuthorizeFuncCall, len(f.history))
-	copy(history, f.history)
-	f.mutex.Unlock()
-
-	return history
-}
-
-// PermsStoreAuthorizeFuncCall is an object that describes an invocation of
-// method Authorize on an instance of MockPermsStore.
-type PermsStoreAuthorizeFuncCall struct {
-	// Arg0 is the value of the 1st argument passed to this method
-	// invocation.
-	Arg0 context.Context
-	// Arg1 is the value of the 2nd argument passed to this method
-	// invocation.
-	Arg1 int64
-	// Arg2 is the value of the 3rd argument passed to this method
-	// invocation.
-	Arg2 int64
-	// Arg3 is the value of the 4th argument passed to this method
-	// invocation.
-	Arg3 database.AccessMode
-	// Arg4 is the value of the 5th argument passed to this method
-	// invocation.
-	Arg4 database.AccessModeOptions
-	// Result0 is the value of the 1st result returned from this method
-	// invocation.
-	Result0 bool
-}
-
-// Args returns an interface slice containing the arguments of this
-// invocation.
-func (c PermsStoreAuthorizeFuncCall) Args() []interface{} {
-	return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4}
-}
-
-// Results returns an interface slice containing the results of this
-// invocation.
-func (c PermsStoreAuthorizeFuncCall) Results() []interface{} {
-	return []interface{}{c.Result0}
-}
-
-// PermsStoreSetRepoPermsFunc describes the behavior when the SetRepoPerms
-// method of the parent MockPermsStore instance is invoked.
-type PermsStoreSetRepoPermsFunc struct {
-	defaultHook func(context.Context, int64, map[int64]database.AccessMode) error
-	hooks       []func(context.Context, int64, map[int64]database.AccessMode) error
-	history     []PermsStoreSetRepoPermsFuncCall
-	mutex       sync.Mutex
-}
-
-// SetRepoPerms delegates to the next hook function in the queue and stores
-// the parameter and result values of this invocation.
-func (m *MockPermsStore) SetRepoPerms(v0 context.Context, v1 int64, v2 map[int64]database.AccessMode) error {
-	r0 := m.SetRepoPermsFunc.nextHook()(v0, v1, v2)
-	m.SetRepoPermsFunc.appendCall(PermsStoreSetRepoPermsFuncCall{v0, v1, v2, r0})
-	return r0
-}
-
-// SetDefaultHook sets function that is called when the SetRepoPerms method
-// of the parent MockPermsStore instance is invoked and the hook queue is
-// empty.
-func (f *PermsStoreSetRepoPermsFunc) SetDefaultHook(hook func(context.Context, int64, map[int64]database.AccessMode) error) {
-	f.defaultHook = hook
-}
-
-// PushHook adds a function to the end of hook queue. Each invocation of the
-// SetRepoPerms method of the parent MockPermsStore instance invokes the
-// hook at the front of the queue and discards it. After the queue is empty,
-// the default hook function is invoked for any future action.
-func (f *PermsStoreSetRepoPermsFunc) PushHook(hook func(context.Context, int64, map[int64]database.AccessMode) error) {
-	f.mutex.Lock()
-	f.hooks = append(f.hooks, hook)
-	f.mutex.Unlock()
-}
-
-// SetDefaultReturn calls SetDefaultHook with a function that returns the
-// given values.
-func (f *PermsStoreSetRepoPermsFunc) SetDefaultReturn(r0 error) {
-	f.SetDefaultHook(func(context.Context, int64, map[int64]database.AccessMode) error {
-		return r0
-	})
-}
-
-// PushReturn calls PushHook with a function that returns the given values.
-func (f *PermsStoreSetRepoPermsFunc) PushReturn(r0 error) {
-	f.PushHook(func(context.Context, int64, map[int64]database.AccessMode) error {
-		return r0
-	})
-}
-
-func (f *PermsStoreSetRepoPermsFunc) nextHook() func(context.Context, int64, map[int64]database.AccessMode) error {
-	f.mutex.Lock()
-	defer f.mutex.Unlock()
-
-	if len(f.hooks) == 0 {
-		return f.defaultHook
-	}
-
-	hook := f.hooks[0]
-	f.hooks = f.hooks[1:]
-	return hook
-}
-
-func (f *PermsStoreSetRepoPermsFunc) appendCall(r0 PermsStoreSetRepoPermsFuncCall) {
-	f.mutex.Lock()
-	f.history = append(f.history, r0)
-	f.mutex.Unlock()
-}
-
-// History returns a sequence of PermsStoreSetRepoPermsFuncCall objects
-// describing the invocations of this function.
-func (f *PermsStoreSetRepoPermsFunc) History() []PermsStoreSetRepoPermsFuncCall {
-	f.mutex.Lock()
-	history := make([]PermsStoreSetRepoPermsFuncCall, len(f.history))
-	copy(history, f.history)
-	f.mutex.Unlock()
-
-	return history
-}
-
-// PermsStoreSetRepoPermsFuncCall is an object that describes an invocation
-// of method SetRepoPerms on an instance of MockPermsStore.
-type PermsStoreSetRepoPermsFuncCall struct {
-	// Arg0 is the value of the 1st argument passed to this method
-	// invocation.
-	Arg0 context.Context
-	// Arg1 is the value of the 2nd argument passed to this method
-	// invocation.
-	Arg1 int64
-	// Arg2 is the value of the 3rd argument passed to this method
-	// invocation.
-	Arg2 map[int64]database.AccessMode
-	// Result0 is the value of the 1st result returned from this method
-	// invocation.
-	Result0 error
-}
-
-// Args returns an interface slice containing the arguments of this
-// invocation.
-func (c PermsStoreSetRepoPermsFuncCall) Args() []interface{} {
-	return []interface{}{c.Arg0, c.Arg1, c.Arg2}
-}
-
-// Results returns an interface slice containing the results of this
-// invocation.
-func (c PermsStoreSetRepoPermsFuncCall) Results() []interface{} {
-	return []interface{}{c.Result0}
-}
-
 // MockReposStore is a mock implementation of the ReposStore interface (from
 // the package gogs.io/gogs/internal/database) used for unit testing.
 type MockReposStore struct {
@@ -5634,6 +5227,10 @@ func (c UsersStoreUseCustomAvatarFuncCall) Results() []interface{} {
 // MockStore is a mock implementation of the Store interface (from the
 // package gogs.io/gogs/internal/route/lfs) used for unit testing.
 type MockStore struct {
+	// AuthorizeRepositoryAccessFunc is an instance of a mock function
+	// object controlling the behavior of the method
+	// AuthorizeRepositoryAccess.
+	AuthorizeRepositoryAccessFunc *StoreAuthorizeRepositoryAccessFunc
 	// CreateLFSObjectFunc is an instance of a mock function object
 	// controlling the behavior of the method CreateLFSObject.
 	CreateLFSObjectFunc *StoreCreateLFSObjectFunc
@@ -5655,6 +5252,11 @@ type MockStore struct {
 // return zero values for all results, unless overwritten.
 func NewMockStore() *MockStore {
 	return &MockStore{
+		AuthorizeRepositoryAccessFunc: &StoreAuthorizeRepositoryAccessFunc{
+			defaultHook: func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) (r0 bool) {
+				return
+			},
+		},
 		CreateLFSObjectFunc: &StoreCreateLFSObjectFunc{
 			defaultHook: func(context.Context, int64, lfsutil.OID, int64, lfsutil.Storage) (r0 error) {
 				return
@@ -5687,6 +5289,11 @@ func NewMockStore() *MockStore {
 // panic on invocation, unless overwritten.
 func NewStrictMockStore() *MockStore {
 	return &MockStore{
+		AuthorizeRepositoryAccessFunc: &StoreAuthorizeRepositoryAccessFunc{
+			defaultHook: func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
+				panic("unexpected invocation of MockStore.AuthorizeRepositoryAccess")
+			},
+		},
 		CreateLFSObjectFunc: &StoreCreateLFSObjectFunc{
 			defaultHook: func(context.Context, int64, lfsutil.OID, int64, lfsutil.Storage) error {
 				panic("unexpected invocation of MockStore.CreateLFSObject")
@@ -5719,6 +5326,9 @@ func NewStrictMockStore() *MockStore {
 // methods delegate to the given implementation, unless overwritten.
 func NewMockStoreFrom(i Store) *MockStore {
 	return &MockStore{
+		AuthorizeRepositoryAccessFunc: &StoreAuthorizeRepositoryAccessFunc{
+			defaultHook: i.AuthorizeRepositoryAccess,
+		},
 		CreateLFSObjectFunc: &StoreCreateLFSObjectFunc{
 			defaultHook: i.CreateLFSObject,
 		},
@@ -5737,6 +5347,122 @@ func NewMockStoreFrom(i Store) *MockStore {
 	}
 }
 
+// StoreAuthorizeRepositoryAccessFunc describes the behavior when the
+// AuthorizeRepositoryAccess method of the parent MockStore instance is
+// invoked.
+type StoreAuthorizeRepositoryAccessFunc struct {
+	defaultHook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool
+	hooks       []func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool
+	history     []StoreAuthorizeRepositoryAccessFuncCall
+	mutex       sync.Mutex
+}
+
+// AuthorizeRepositoryAccess delegates to the next hook function in the
+// queue and stores the parameter and result values of this invocation.
+func (m *MockStore) AuthorizeRepositoryAccess(v0 context.Context, v1 int64, v2 int64, v3 database.AccessMode, v4 database.AccessModeOptions) bool {
+	r0 := m.AuthorizeRepositoryAccessFunc.nextHook()(v0, v1, v2, v3, v4)
+	m.AuthorizeRepositoryAccessFunc.appendCall(StoreAuthorizeRepositoryAccessFuncCall{v0, v1, v2, v3, v4, r0})
+	return r0
+}
+
+// SetDefaultHook sets function that is called when the
+// AuthorizeRepositoryAccess method of the parent MockStore instance is
+// invoked and the hook queue is empty.
+func (f *StoreAuthorizeRepositoryAccessFunc) SetDefaultHook(hook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool) {
+	f.defaultHook = hook
+}
+
+// PushHook adds a function to the end of hook queue. Each invocation of the
+// AuthorizeRepositoryAccess method of the parent MockStore instance invokes
+// the hook at the front of the queue and discards it. After the queue is
+// empty, the default hook function is invoked for any future action.
+func (f *StoreAuthorizeRepositoryAccessFunc) PushHook(hook func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool) {
+	f.mutex.Lock()
+	f.hooks = append(f.hooks, hook)
+	f.mutex.Unlock()
+}
+
+// SetDefaultReturn calls SetDefaultHook with a function that returns the
+// given values.
+func (f *StoreAuthorizeRepositoryAccessFunc) SetDefaultReturn(r0 bool) {
+	f.SetDefaultHook(func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
+		return r0
+	})
+}
+
+// PushReturn calls PushHook with a function that returns the given values.
+func (f *StoreAuthorizeRepositoryAccessFunc) PushReturn(r0 bool) {
+	f.PushHook(func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
+		return r0
+	})
+}
+
+func (f *StoreAuthorizeRepositoryAccessFunc) nextHook() func(context.Context, int64, int64, database.AccessMode, database.AccessModeOptions) bool {
+	f.mutex.Lock()
+	defer f.mutex.Unlock()
+
+	if len(f.hooks) == 0 {
+		return f.defaultHook
+	}
+
+	hook := f.hooks[0]
+	f.hooks = f.hooks[1:]
+	return hook
+}
+
+func (f *StoreAuthorizeRepositoryAccessFunc) appendCall(r0 StoreAuthorizeRepositoryAccessFuncCall) {
+	f.mutex.Lock()
+	f.history = append(f.history, r0)
+	f.mutex.Unlock()
+}
+
+// History returns a sequence of StoreAuthorizeRepositoryAccessFuncCall
+// objects describing the invocations of this function.
+func (f *StoreAuthorizeRepositoryAccessFunc) History() []StoreAuthorizeRepositoryAccessFuncCall {
+	f.mutex.Lock()
+	history := make([]StoreAuthorizeRepositoryAccessFuncCall, len(f.history))
+	copy(history, f.history)
+	f.mutex.Unlock()
+
+	return history
+}
+
+// StoreAuthorizeRepositoryAccessFuncCall is an object that describes an
+// invocation of method AuthorizeRepositoryAccess on an instance of
+// MockStore.
+type StoreAuthorizeRepositoryAccessFuncCall struct {
+	// Arg0 is the value of the 1st argument passed to this method
+	// invocation.
+	Arg0 context.Context
+	// Arg1 is the value of the 2nd argument passed to this method
+	// invocation.
+	Arg1 int64
+	// Arg2 is the value of the 3rd argument passed to this method
+	// invocation.
+	Arg2 int64
+	// Arg3 is the value of the 4th argument passed to this method
+	// invocation.
+	Arg3 database.AccessMode
+	// Arg4 is the value of the 5th argument passed to this method
+	// invocation.
+	Arg4 database.AccessModeOptions
+	// Result0 is the value of the 1st result returned from this method
+	// invocation.
+	Result0 bool
+}
+
+// Args returns an interface slice containing the arguments of this
+// invocation.
+func (c StoreAuthorizeRepositoryAccessFuncCall) Args() []interface{} {
+	return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3, c.Arg4}
+}
+
+// Results returns an interface slice containing the results of this
+// invocation.
+func (c StoreAuthorizeRepositoryAccessFuncCall) Results() []interface{} {
+	return []interface{}{c.Result0}
+}
+
 // StoreCreateLFSObjectFunc describes the behavior when the CreateLFSObject
 // method of the parent MockStore instance is invoked.
 type StoreCreateLFSObjectFunc struct {

+ 6 - 6
internal/route/lfs/route.go

@@ -28,7 +28,7 @@ func RegisterRoutes(r *macaron.Router) {
 
 	store := NewStore()
 	r.Group("", func() {
-		r.Post("/objects/batch", authorize(database.AccessModeRead), verifyAccept, verifyContentTypeJSON, serveBatch(store))
+		r.Post("/objects/batch", authorize(store, database.AccessModeRead), verifyAccept, verifyContentTypeJSON, serveBatch(store))
 		r.Group("/objects/basic", func() {
 			basic := &basicHandler{
 				store:          store,
@@ -38,9 +38,9 @@ func RegisterRoutes(r *macaron.Router) {
 				},
 			}
 			r.Combo("/:oid", verifyOID()).
-				Get(authorize(database.AccessModeRead), basic.serveDownload).
-				Put(authorize(database.AccessModeWrite), verifyContentTypeStream, basic.serveUpload)
-			r.Post("/verify", authorize(database.AccessModeWrite), verifyAccept, verifyContentTypeJSON, basic.serveVerify)
+				Get(authorize(store, database.AccessModeRead), basic.serveDownload).
+				Put(authorize(store, database.AccessModeWrite), verifyContentTypeStream, basic.serveUpload)
+			r.Post("/verify", authorize(store, database.AccessModeWrite), verifyAccept, verifyContentTypeJSON, basic.serveVerify)
 		})
 	}, authenticate(store))
 }
@@ -104,7 +104,7 @@ func authenticate(store Store) macaron.Handler {
 }
 
 // authorize tries to authorize the user to the context repository with given access mode.
-func authorize(mode database.AccessMode) macaron.Handler {
+func authorize(store Store, mode database.AccessMode) macaron.Handler {
 	return func(c *macaron.Context, actor *database.User) {
 		username := c.Params(":username")
 		reponame := strings.TrimSuffix(c.Params(":reponame"), ".git")
@@ -131,7 +131,7 @@ func authorize(mode database.AccessMode) macaron.Handler {
 			return
 		}
 
-		if !database.Perms.Authorize(c.Req.Context(), actor.ID, repo.ID, mode,
+		if !store.AuthorizeRepositoryAccess(c.Req.Context(), actor.ID, repo.ID, mode,
 			database.AccessModeOptions{
 				OwnerID: repo.OwnerID,
 				Private: repo.IsPrivate,

+ 29 - 24
internal/route/lfs/route_test.go

@@ -187,19 +187,19 @@ func TestAuthenticate(t *testing.T) {
 	}
 }
 
-func Test_authorize(t *testing.T) {
+func TestAuthorize(t *testing.T) {
 	tests := []struct {
 		name           string
-		authroize      macaron.Handler
+		accessMode     database.AccessMode
 		mockUsersStore func() database.UsersStore
 		mockReposStore func() database.ReposStore
-		mockPermsStore func() database.PermsStore
+		mockStore      func() *MockStore
 		expStatusCode  int
 		expBody        string
 	}{
 		{
-			name:      "user does not exist",
-			authroize: authorize(database.AccessModeNone),
+			name:       "user does not exist",
+			accessMode: database.AccessModeNone,
 			mockUsersStore: func() database.UsersStore {
 				mock := NewMockUsersStore()
 				mock.GetByUsernameFunc.SetDefaultReturn(nil, database.ErrUserNotExist{})
@@ -208,8 +208,8 @@ func Test_authorize(t *testing.T) {
 			expStatusCode: http.StatusNotFound,
 		},
 		{
-			name:      "repository does not exist",
-			authroize: authorize(database.AccessModeNone),
+			name:       "repository does not exist",
+			accessMode: database.AccessModeNone,
 			mockUsersStore: func() database.UsersStore {
 				mock := NewMockUsersStore()
 				mock.GetByUsernameFunc.SetDefaultHook(func(ctx context.Context, username string) (*database.User, error) {
@@ -225,8 +225,8 @@ func Test_authorize(t *testing.T) {
 			expStatusCode: http.StatusNotFound,
 		},
 		{
-			name:      "actor is not authorized",
-			authroize: authorize(database.AccessModeWrite),
+			name:       "actor is not authorized",
+			accessMode: database.AccessModeWrite,
 			mockUsersStore: func() database.UsersStore {
 				mock := NewMockUsersStore()
 				mock.GetByUsernameFunc.SetDefaultHook(func(ctx context.Context, username string) (*database.User, error) {
@@ -241,19 +241,19 @@ func Test_authorize(t *testing.T) {
 				})
 				return mock
 			},
-			mockPermsStore: func() database.PermsStore {
-				mock := NewMockPermsStore()
-				mock.AuthorizeFunc.SetDefaultHook(func(ctx context.Context, userID int64, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool {
+			mockStore: func() *MockStore {
+				mockStore := NewMockStore()
+				mockStore.AuthorizeRepositoryAccessFunc.SetDefaultHook(func(_ context.Context, _ int64, _ int64, desired database.AccessMode, _ database.AccessModeOptions) bool {
 					return desired <= database.AccessModeRead
 				})
-				return mock
+				return mockStore
 			},
 			expStatusCode: http.StatusNotFound,
 		},
 
 		{
-			name:      "actor is authorized",
-			authroize: authorize(database.AccessModeRead),
+			name:       "actor is authorized",
+			accessMode: database.AccessModeRead,
 			mockUsersStore: func() database.UsersStore {
 				mock := NewMockUsersStore()
 				mock.GetByUsernameFunc.SetDefaultHook(func(ctx context.Context, username string) (*database.User, error) {
@@ -268,12 +268,12 @@ func Test_authorize(t *testing.T) {
 				})
 				return mock
 			},
-			mockPermsStore: func() database.PermsStore {
-				mock := NewMockPermsStore()
-				mock.AuthorizeFunc.SetDefaultHook(func(ctx context.Context, userID int64, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool {
+			mockStore: func() *MockStore {
+				mockStore := NewMockStore()
+				mockStore.AuthorizeRepositoryAccessFunc.SetDefaultHook(func(_ context.Context, _ int64, _ int64, desired database.AccessMode, _ database.AccessModeOptions) bool {
 					return desired <= database.AccessModeRead
 				})
-				return mock
+				return mockStore
 			},
 			expStatusCode: http.StatusOK,
 			expBody:       "owner.Name: owner, repo.Name: repo",
@@ -287,8 +287,9 @@ func Test_authorize(t *testing.T) {
 			if test.mockReposStore != nil {
 				database.SetMockReposStore(t, test.mockReposStore())
 			}
-			if test.mockPermsStore != nil {
-				database.SetMockPermsStore(t, test.mockPermsStore())
+			mockStore := NewMockStore()
+			if test.mockStore != nil {
+				mockStore = test.mockStore()
 			}
 
 			m := macaron.New()
@@ -296,9 +297,13 @@ func Test_authorize(t *testing.T) {
 			m.Use(func(c *macaron.Context) {
 				c.Map(&database.User{})
 			})
-			m.Get("/:username/:reponame", test.authroize, func(w http.ResponseWriter, owner *database.User, repo *database.Repository) {
-				fmt.Fprintf(w, "owner.Name: %s, repo.Name: %s", owner.Name, repo.Name)
-			})
+			m.Get(
+				"/:username/:reponame",
+				authorize(mockStore, test.accessMode),
+				func(w http.ResponseWriter, owner *database.User, repo *database.Repository) {
+					_, _ = fmt.Fprintf(w, "owner.Name: %s, repo.Name: %s", owner.Name, repo.Name)
+				},
+			)
 
 			r, err := http.NewRequest("GET", "/owner/repo", nil)
 			if err != nil {

+ 8 - 0
internal/route/lfs/store.go

@@ -26,6 +26,10 @@ type Store interface {
 	// GetLFSObjectsByOIDs returns LFS objects found within "oids". The returned
 	// list could have fewer elements if some oids were not found.
 	GetLFSObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfsutil.OID) ([]*database.LFSObject, error)
+
+	// AuthorizeRepositoryAccess returns true if the user has as good as desired
+	// access mode to the repository.
+	AuthorizeRepositoryAccess(ctx context.Context, userID, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool
 }
 
 type store struct{}
@@ -54,3 +58,7 @@ func (*store) GetLFSObjectByOID(ctx context.Context, repoID int64, oid lfsutil.O
 func (*store) GetLFSObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfsutil.OID) ([]*database.LFSObject, error) {
 	return database.Handle.LFS().GetObjectsByOIDs(ctx, repoID, oids...)
 }
+
+func (*store) AuthorizeRepositoryAccess(ctx context.Context, userID, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool {
+	return database.Handle.Permissions().Authorize(ctx, userID, repoID, desired, opts)
+}

+ 1 - 1
internal/route/repo/http.go

@@ -164,7 +164,7 @@ Please create and use personal access token on user settings page`)
 		if isPull {
 			mode = database.AccessModeRead
 		}
-		if !database.Perms.Authorize(c.Req.Context(), authUser.ID, repo.ID, mode,
+		if !database.Handle.Permissions().Authorize(c.Req.Context(), authUser.ID, repo.ID, mode,
 			database.AccessModeOptions{
 				OwnerID: repo.OwnerID,
 				Private: repo.IsPrivate,

+ 2 - 2
internal/route/repo/issue.go

@@ -596,7 +596,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 		participants = make([]*database.User, 1, 10)
 	)
 
-	// Render comments and and fetch participants.
+	// Render comments and fetch participants.
 	participants[0] = issue.Poster
 	for _, comment = range issue.Comments {
 		if comment.Type == database.COMMENT_TYPE_COMMENT {
@@ -612,7 +612,7 @@ func viewIssue(c *context.Context, isPullList bool) {
 			if repo.IsOwnedBy(comment.PosterID) ||
 				(repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(comment.PosterID)) {
 				comment.ShowTag = database.COMMENT_TAG_OWNER
-			} else if database.Perms.Authorize(
+			} else if database.Handle.Permissions().Authorize(
 				c.Req.Context(),
 				comment.PosterID,
 				repo.ID,

+ 1 - 1
internal/route/repo/pull.go

@@ -517,7 +517,7 @@ func ParseCompareInfo(c *context.Context) (*database.User, *database.Repository,
 		headGitRepo = c.Repo.GitRepo
 	}
 
-	if !database.Perms.Authorize(
+	if !database.Handle.Permissions().Authorize(
 		c.Req.Context(),
 		c.User.ID,
 		headRepo.ID,

+ 0 - 1
mockgen.yaml

@@ -39,7 +39,6 @@ mocks:
           - UsersStore
           - TwoFactorsStore
           - ReposStore
-          - PermsStore
       - path: gogs.io/gogs/internal/route/lfs
         interfaces:
           - Store