aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/db/actions_test.go4
-rw-r--r--internal/db/db.go2
-rw-r--r--internal/db/perms.go6
-rw-r--r--internal/db/repos.go63
-rw-r--r--internal/db/repos_test.go62
-rw-r--r--internal/db/user.go39
-rw-r--r--internal/route/api/v1/repo/repo.go24
-rw-r--r--internal/route/lfs/mocks_test.go261
-rw-r--r--internal/route/user/home.go4
9 files changed, 410 insertions, 55 deletions
diff --git a/internal/db/actions_test.go b/internal/db/actions_test.go
index aa6bbf4e..15e11e9f 100644
--- a/internal/db/actions_test.go
+++ b/internal/db/actions_test.go
@@ -720,6 +720,10 @@ func actionsNewRepo(t *testing.T, db *actions) {
func actionsPushTag(t *testing.T, db *actions) {
ctx := context.Background()
+ // NOTE: We set a noop mock here to avoid data race with other tests that writes
+ // to the mock server because this function holds a lock.
+ conf.SetMockServer(t, conf.ServerOpts{})
+
alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := NewReposStore(db.DB).Create(ctx,
diff --git a/internal/db/db.go b/internal/db/db.go
index 7b063dec..2e883fc0 100644
--- a/internal/db/db.go
+++ b/internal/db/db.go
@@ -127,7 +127,7 @@ func Init(w logger.Writer) (*gorm.DB, error) {
LFS = &lfs{DB: db}
Orgs = NewOrgsStore(db)
OrgUsers = NewOrgUsersStore(db)
- Perms = &perms{DB: db}
+ Perms = NewPermsStore(db)
Repos = NewReposStore(db)
TwoFactors = &twoFactors{DB: db}
Users = NewUsersStore(db)
diff --git a/internal/db/perms.go b/internal/db/perms.go
index a72a013a..b0a1a85a 100644
--- a/internal/db/perms.go
+++ b/internal/db/perms.go
@@ -82,6 +82,12 @@ type perms struct {
*gorm.DB
}
+// NewPermsStore returns a persistent interface for permissions with given
+// database connection.
+func NewPermsStore(db *gorm.DB) PermsStore {
+ return &perms{DB: db}
+}
+
type AccessModeOptions struct {
OwnerID int64 // The ID of the repository owner.
Private bool // Whether the repository is private.
diff --git a/internal/db/repos.go b/internal/db/repos.go
index 7ca78ad8..10f292b9 100644
--- a/internal/db/repos.go
+++ b/internal/db/repos.go
@@ -26,6 +26,16 @@ type ReposStore interface {
// ErrRepoAlreadyExist when a repository with same name already exists for the
// owner.
Create(ctx context.Context, ownerID int64, opts CreateRepoOptions) (*Repository, error)
+ // GetByCollaboratorID returns a list of repositories that the given
+ // collaborator has access to. Results are limited to the given limit and sorted
+ // by the given order (e.g. "updated_unix DESC"). Repositories that are owned
+ // directly by the given collaborator are not included.
+ GetByCollaboratorID(ctx context.Context, collaboratorID int64, limit int, orderBy string) ([]*Repository, error)
+ // GetByCollaboratorIDWithAccessMode returns a list of repositories and
+ // corresponding access mode that the given collaborator has access to.
+ // Repositories that are owned directly by the given collaborator are not
+ // included.
+ GetByCollaboratorIDWithAccessMode(ctx context.Context, collaboratorID int64) (map[*Repository]AccessMode, error)
// GetByName returns the repository with given owner and name. It returns
// ErrRepoNotExist when not found.
GetByName(ctx context.Context, ownerID int64, name string) (*Repository, error)
@@ -170,6 +180,59 @@ func (db *repos) Create(ctx context.Context, ownerID int64, opts CreateRepoOptio
return repo, db.WithContext(ctx).Create(repo).Error
}
+func (db *repos) GetByCollaboratorID(ctx context.Context, collaboratorID int64, limit int, orderBy string) ([]*Repository, error) {
+ /*
+ Equivalent SQL for PostgreSQL:
+
+ SELECT * FROM repository
+ JOIN access ON access.repo_id = repository.id AND access.user_id = @collaboratorID
+ WHERE access.mode >= @accessModeRead
+ ORDER BY @orderBy
+ LIMIT @limit
+ */
+ var repos []*Repository
+ return repos, db.WithContext(ctx).
+ Joins("JOIN access ON access.repo_id = repository.id AND access.user_id = ?", collaboratorID).
+ Where("access.mode >= ?", AccessModeRead).
+ Order(orderBy).
+ Limit(limit).
+ Find(&repos).
+ Error
+}
+
+func (db *repos) GetByCollaboratorIDWithAccessMode(ctx context.Context, collaboratorID int64) (map[*Repository]AccessMode, error) {
+ /*
+ Equivalent SQL for PostgreSQL:
+
+ SELECT
+ repository.*,
+ access.mode
+ FROM repository
+ JOIN access ON access.repo_id = repository.id AND access.user_id = @collaboratorID
+ WHERE access.mode >= @accessModeRead
+ */
+ var reposWithAccessMode []*struct {
+ *Repository
+ Mode AccessMode
+ }
+ err := db.WithContext(ctx).
+ Select("repository.*", "access.mode").
+ Table("repository").
+ Joins("JOIN access ON access.repo_id = repository.id AND access.user_id = ?", collaboratorID).
+ Where("access.mode >= ?", AccessModeRead).
+ Find(&reposWithAccessMode).
+ Error
+ if err != nil {
+ return nil, err
+ }
+
+ repos := make(map[*Repository]AccessMode, len(reposWithAccessMode))
+ for _, repoWithAccessMode := range reposWithAccessMode {
+ repos[repoWithAccessMode.Repository] = repoWithAccessMode.Mode
+ }
+ return repos, nil
+}
+
var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
type ErrRepoNotExist struct {
diff --git a/internal/db/repos_test.go b/internal/db/repos_test.go
index 3c01105d..09289729 100644
--- a/internal/db/repos_test.go
+++ b/internal/db/repos_test.go
@@ -85,7 +85,7 @@ func TestRepos(t *testing.T) {
}
t.Parallel()
- tables := []any{new(Repository)}
+ tables := []any{new(Repository), new(Access)}
db := &repos{
DB: dbtest.NewDB(t, "repos", tables...),
}
@@ -95,6 +95,8 @@ func TestRepos(t *testing.T) {
test func(t *testing.T, db *repos)
}{
{"Create", reposCreate},
+ {"GetByCollaboratorID", reposGetByCollaboratorID},
+ {"GetByCollaboratorIDWithAccessMode", reposGetByCollaboratorIDWithAccessMode},
{"GetByName", reposGetByName},
{"Touch", reposTouch},
} {
@@ -154,6 +156,64 @@ func reposCreate(t *testing.T, db *repos) {
assert.Equal(t, db.NowFunc().Format(time.RFC3339), repo.Created.UTC().Format(time.RFC3339))
}
+func reposGetByCollaboratorID(t *testing.T, db *repos) {
+ ctx := context.Background()
+
+ repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
+ require.NoError(t, err)
+ 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})
+ require.NoError(t, err)
+ err = permsStore.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) {
+ got, err := db.GetByCollaboratorID(ctx, 3, 10, "")
+ require.NoError(t, err)
+ require.Len(t, got, 1)
+ assert.Equal(t, repo1.ID, got[0].ID)
+ })
+
+ t.Run("do not return directly owned repository", func(t *testing.T) {
+ got, err := db.GetByCollaboratorID(ctx, 1, 10, "")
+ require.NoError(t, err)
+ require.Len(t, got, 0)
+ })
+}
+
+func reposGetByCollaboratorIDWithAccessMode(t *testing.T, db *repos) {
+ ctx := context.Background()
+
+ repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
+ require.NoError(t, err)
+ repo2, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
+ require.NoError(t, err)
+ 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})
+ require.NoError(t, err)
+ err = permsStore.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})
+ require.NoError(t, err)
+
+ got, err := db.GetByCollaboratorIDWithAccessMode(ctx, 3)
+ require.NoError(t, err)
+ require.Len(t, got, 2)
+
+ accessModes := make(map[int64]AccessMode)
+ for repo, mode := range got {
+ accessModes[repo.ID] = mode
+ }
+ assert.Equal(t, AccessModeRead, accessModes[repo1.ID])
+ assert.Equal(t, AccessModeAdmin, accessModes[repo2.ID])
+}
+
func reposGetByName(t *testing.T, db *repos) {
ctx := context.Background()
diff --git a/internal/db/user.go b/internal/db/user.go
index 5be64668..9cbc2fa3 100644
--- a/internal/db/user.go
+++ b/internal/db/user.go
@@ -10,7 +10,6 @@ import (
"os"
"time"
- log "unknwon.dev/clog/v2"
"xorm.io/xorm"
"gogs.io/gogs/internal/repoutil"
@@ -196,41 +195,3 @@ func DeleteInactivateUsers() (err error) {
_, err = x.Where("is_activated = ?", false).Delete(new(EmailAddress))
return err
}
-
-// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
-func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
- accesses := make([]*Access, 0, 10)
- if err := x.Find(&accesses, &Access{UserID: u.ID}); err != nil {
- return nil, err
- }
-
- repos := make(map[*Repository]AccessMode, len(accesses))
- for _, access := range accesses {
- repo, err := GetRepositoryByID(access.RepoID)
- if err != nil {
- if IsErrRepoNotExist(err) {
- log.Error("Failed to get repository by ID: %v", err)
- continue
- }
- return nil, err
- }
- if repo.OwnerID == u.ID {
- continue
- }
- repos[repo] = access.Mode
- }
- return repos, nil
-}
-
-// GetAccessibleRepositories finds repositories which the user has access but does not own.
-// If limit is smaller than 1 means returns all found results.
-func (user *User) GetAccessibleRepositories(limit int) (repos []*Repository, _ error) {
- sess := x.Where("owner_id !=? ", user.ID).Desc("updated_unix")
- if limit > 0 {
- sess.Limit(limit)
- repos = make([]*Repository, 0, limit)
- } else {
- repos = make([]*Repository, 0, 10)
- }
- return repos, sess.Join("INNER", "access", "access.user_id = ? AND access.repo_id = repository.id", user.ID).Find(&repos)
-}
diff --git a/internal/route/api/v1/repo/repo.go b/internal/route/api/v1/repo/repo.go
index 089269ac..a4cc36b3 100644
--- a/internal/route/api/v1/repo/repo.go
+++ b/internal/route/api/v1/repo/repo.go
@@ -116,26 +116,26 @@ func listUserRepositories(c *context.APIContext, username string) {
return
}
- accessibleRepos, err := user.GetRepositoryAccesses()
+ accessibleRepos, err := db.Repos.GetByCollaboratorIDWithAccessMode(c.Req.Context(), user.ID)
if err != nil {
- c.Error(err, "get repositories accesses")
+ c.Error(err, "get repositories accesses by collaborator")
return
}
numOwnRepos := len(ownRepos)
- repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
- for i := range ownRepos {
- repos[i] = ownRepos[i].APIFormatLegacy(&api.Permission{Admin: true, Push: true, Pull: true})
+ repos := make([]*api.Repository, 0, numOwnRepos+len(accessibleRepos))
+ for _, r := range ownRepos {
+ repos = append(repos, r.APIFormatLegacy(&api.Permission{Admin: true, Push: true, Pull: true}))
}
- i := numOwnRepos
for repo, access := range accessibleRepos {
- repos[i] = repo.APIFormatLegacy(&api.Permission{
- Admin: access >= db.AccessModeAdmin,
- Push: access >= db.AccessModeWrite,
- Pull: true,
- })
- i++
+ repos = append(repos,
+ repo.APIFormatLegacy(&api.Permission{
+ Admin: access >= db.AccessModeAdmin,
+ Push: access >= db.AccessModeWrite,
+ Pull: true,
+ }),
+ )
}
c.JSONSuccess(&repos)
diff --git a/internal/route/lfs/mocks_test.go b/internal/route/lfs/mocks_test.go
index 9a51b395..089004fc 100644
--- a/internal/route/lfs/mocks_test.go
+++ b/internal/route/lfs/mocks_test.go
@@ -1495,6 +1495,13 @@ type MockReposStore struct {
// CreateFunc is an instance of a mock function object controlling the
// behavior of the method Create.
CreateFunc *ReposStoreCreateFunc
+ // GetByCollaboratorIDFunc is an instance of a mock function object
+ // controlling the behavior of the method GetByCollaboratorID.
+ GetByCollaboratorIDFunc *ReposStoreGetByCollaboratorIDFunc
+ // GetByCollaboratorIDWithAccessModeFunc is an instance of a mock
+ // function object controlling the behavior of the method
+ // GetByCollaboratorIDWithAccessMode.
+ GetByCollaboratorIDWithAccessModeFunc *ReposStoreGetByCollaboratorIDWithAccessModeFunc
// GetByNameFunc is an instance of a mock function object controlling
// the behavior of the method GetByName.
GetByNameFunc *ReposStoreGetByNameFunc
@@ -1512,6 +1519,16 @@ func NewMockReposStore() *MockReposStore {
return
},
},
+ GetByCollaboratorIDFunc: &ReposStoreGetByCollaboratorIDFunc{
+ defaultHook: func(context.Context, int64, int, string) (r0 []*db.Repository, r1 error) {
+ return
+ },
+ },
+ GetByCollaboratorIDWithAccessModeFunc: &ReposStoreGetByCollaboratorIDWithAccessModeFunc{
+ defaultHook: func(context.Context, int64) (r0 map[*db.Repository]db.AccessMode, r1 error) {
+ return
+ },
+ },
GetByNameFunc: &ReposStoreGetByNameFunc{
defaultHook: func(context.Context, int64, string) (r0 *db.Repository, r1 error) {
return
@@ -1534,6 +1551,16 @@ func NewStrictMockReposStore() *MockReposStore {
panic("unexpected invocation of MockReposStore.Create")
},
},
+ GetByCollaboratorIDFunc: &ReposStoreGetByCollaboratorIDFunc{
+ defaultHook: func(context.Context, int64, int, string) ([]*db.Repository, error) {
+ panic("unexpected invocation of MockReposStore.GetByCollaboratorID")
+ },
+ },
+ GetByCollaboratorIDWithAccessModeFunc: &ReposStoreGetByCollaboratorIDWithAccessModeFunc{
+ defaultHook: func(context.Context, int64) (map[*db.Repository]db.AccessMode, error) {
+ panic("unexpected invocation of MockReposStore.GetByCollaboratorIDWithAccessMode")
+ },
+ },
GetByNameFunc: &ReposStoreGetByNameFunc{
defaultHook: func(context.Context, int64, string) (*db.Repository, error) {
panic("unexpected invocation of MockReposStore.GetByName")
@@ -1554,6 +1581,12 @@ func NewMockReposStoreFrom(i db.ReposStore) *MockReposStore {
CreateFunc: &ReposStoreCreateFunc{
defaultHook: i.Create,
},
+ GetByCollaboratorIDFunc: &ReposStoreGetByCollaboratorIDFunc{
+ defaultHook: i.GetByCollaboratorID,
+ },
+ GetByCollaboratorIDWithAccessModeFunc: &ReposStoreGetByCollaboratorIDWithAccessModeFunc{
+ defaultHook: i.GetByCollaboratorIDWithAccessMode,
+ },
GetByNameFunc: &ReposStoreGetByNameFunc{
defaultHook: i.GetByName,
},
@@ -1673,6 +1706,234 @@ func (c ReposStoreCreateFuncCall) Results() []interface{} {
return []interface{}{c.Result0, c.Result1}
}
+// ReposStoreGetByCollaboratorIDFunc describes the behavior when the
+// GetByCollaboratorID method of the parent MockReposStore instance is
+// invoked.
+type ReposStoreGetByCollaboratorIDFunc struct {
+ defaultHook func(context.Context, int64, int, string) ([]*db.Repository, error)
+ hooks []func(context.Context, int64, int, string) ([]*db.Repository, error)
+ history []ReposStoreGetByCollaboratorIDFuncCall
+ mutex sync.Mutex
+}
+
+// GetByCollaboratorID delegates to the next hook function in the queue and
+// stores the parameter and result values of this invocation.
+func (m *MockReposStore) GetByCollaboratorID(v0 context.Context, v1 int64, v2 int, v3 string) ([]*db.Repository, error) {
+ r0, r1 := m.GetByCollaboratorIDFunc.nextHook()(v0, v1, v2, v3)
+ m.GetByCollaboratorIDFunc.appendCall(ReposStoreGetByCollaboratorIDFuncCall{v0, v1, v2, v3, r0, r1})
+ return r0, r1
+}
+
+// SetDefaultHook sets function that is called when the GetByCollaboratorID
+// method of the parent MockReposStore instance is invoked and the hook
+// queue is empty.
+func (f *ReposStoreGetByCollaboratorIDFunc) SetDefaultHook(hook func(context.Context, int64, int, string) ([]*db.Repository, error)) {
+ f.defaultHook = hook
+}
+
+// PushHook adds a function to the end of hook queue. Each invocation of the
+// GetByCollaboratorID method of the parent MockReposStore 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 *ReposStoreGetByCollaboratorIDFunc) PushHook(hook func(context.Context, int64, int, string) ([]*db.Repository, 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 *ReposStoreGetByCollaboratorIDFunc) SetDefaultReturn(r0 []*db.Repository, r1 error) {
+ f.SetDefaultHook(func(context.Context, int64, int, string) ([]*db.Repository, error) {
+ return r0, r1
+ })
+}
+
+// PushReturn calls PushHook with a function that returns the given values.
+func (f *ReposStoreGetByCollaboratorIDFunc) PushReturn(r0 []*db.Repository, r1 error) {
+ f.PushHook(func(context.Context, int64, int, string) ([]*db.Repository, error) {
+ return r0, r1
+ })
+}
+
+func (f *ReposStoreGetByCollaboratorIDFunc) nextHook() func(context.Context, int64, int, string) ([]*db.Repository, 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 *ReposStoreGetByCollaboratorIDFunc) appendCall(r0 ReposStoreGetByCollaboratorIDFuncCall) {
+ f.mutex.Lock()
+ f.history = append(f.history, r0)
+ f.mutex.Unlock()
+}
+
+// History returns a sequence of ReposStoreGetByCollaboratorIDFuncCall
+// objects describing the invocations of this function.
+func (f *ReposStoreGetByCollaboratorIDFunc) History() []ReposStoreGetByCollaboratorIDFuncCall {
+ f.mutex.Lock()
+ history := make([]ReposStoreGetByCollaboratorIDFuncCall, len(f.history))
+ copy(history, f.history)
+ f.mutex.Unlock()
+
+ return history
+}
+
+// ReposStoreGetByCollaboratorIDFuncCall is an object that describes an
+// invocation of method GetByCollaboratorID on an instance of
+// MockReposStore.
+type ReposStoreGetByCollaboratorIDFuncCall 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 int
+ // Arg3 is the value of the 4th argument passed to this method
+ // invocation.
+ Arg3 string
+ // Result0 is the value of the 1st result returned from this method
+ // invocation.
+ Result0 []*db.Repository
+ // Result1 is the value of the 2nd result returned from this method
+ // invocation.
+ Result1 error
+}
+
+// Args returns an interface slice containing the arguments of this
+// invocation.
+func (c ReposStoreGetByCollaboratorIDFuncCall) 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 ReposStoreGetByCollaboratorIDFuncCall) Results() []interface{} {
+ return []interface{}{c.Result0, c.Result1}
+}
+
+// ReposStoreGetByCollaboratorIDWithAccessModeFunc describes the behavior
+// when the GetByCollaboratorIDWithAccessMode method of the parent
+// MockReposStore instance is invoked.
+type ReposStoreGetByCollaboratorIDWithAccessModeFunc struct {
+ defaultHook func(context.Context, int64) (map[*db.Repository]db.AccessMode, error)
+ hooks []func(context.Context, int64) (map[*db.Repository]db.AccessMode, error)
+ history []ReposStoreGetByCollaboratorIDWithAccessModeFuncCall
+ mutex sync.Mutex
+}
+
+// GetByCollaboratorIDWithAccessMode delegates to the next hook function in
+// the queue and stores the parameter and result values of this invocation.
+func (m *MockReposStore) GetByCollaboratorIDWithAccessMode(v0 context.Context, v1 int64) (map[*db.Repository]db.AccessMode, error) {
+ r0, r1 := m.GetByCollaboratorIDWithAccessModeFunc.nextHook()(v0, v1)
+ m.GetByCollaboratorIDWithAccessModeFunc.appendCall(ReposStoreGetByCollaboratorIDWithAccessModeFuncCall{v0, v1, r0, r1})
+ return r0, r1
+}
+
+// SetDefaultHook sets function that is called when the
+// GetByCollaboratorIDWithAccessMode method of the parent MockReposStore
+// instance is invoked and the hook queue is empty.
+func (f *ReposStoreGetByCollaboratorIDWithAccessModeFunc) SetDefaultHook(hook func(context.Context, int64) (map[*db.Repository]db.AccessMode, error)) {
+ f.defaultHook = hook
+}
+
+// PushHook adds a function to the end of hook queue. Each invocation of the
+// GetByCollaboratorIDWithAccessMode method of the parent MockReposStore
+// 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 *ReposStoreGetByCollaboratorIDWithAccessModeFunc) PushHook(hook func(context.Context, int64) (map[*db.Repository]db.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 *ReposStoreGetByCollaboratorIDWithAccessModeFunc) SetDefaultReturn(r0 map[*db.Repository]db.AccessMode, r1 error) {
+ f.SetDefaultHook(func(context.Context, int64) (map[*db.Repository]db.AccessMode, error) {
+ return r0, r1
+ })
+}
+
+// PushReturn calls PushHook with a function that returns the given values.
+func (f *ReposStoreGetByCollaboratorIDWithAccessModeFunc) PushReturn(r0 map[*db.Repository]db.AccessMode, r1 error) {
+ f.PushHook(func(context.Context, int64) (map[*db.Repository]db.AccessMode, error) {
+ return r0, r1
+ })
+}
+
+func (f *ReposStoreGetByCollaboratorIDWithAccessModeFunc) nextHook() func(context.Context, int64) (map[*db.Repository]db.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 *ReposStoreGetByCollaboratorIDWithAccessModeFunc) appendCall(r0 ReposStoreGetByCollaboratorIDWithAccessModeFuncCall) {
+ f.mutex.Lock()
+ f.history = append(f.history, r0)
+ f.mutex.Unlock()
+}
+
+// History returns a sequence of
+// ReposStoreGetByCollaboratorIDWithAccessModeFuncCall objects describing
+// the invocations of this function.
+func (f *ReposStoreGetByCollaboratorIDWithAccessModeFunc) History() []ReposStoreGetByCollaboratorIDWithAccessModeFuncCall {
+ f.mutex.Lock()
+ history := make([]ReposStoreGetByCollaboratorIDWithAccessModeFuncCall, len(f.history))
+ copy(history, f.history)
+ f.mutex.Unlock()
+
+ return history
+}
+
+// ReposStoreGetByCollaboratorIDWithAccessModeFuncCall is an object that
+// describes an invocation of method GetByCollaboratorIDWithAccessMode on an
+// instance of MockReposStore.
+type ReposStoreGetByCollaboratorIDWithAccessModeFuncCall 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
+ // Result0 is the value of the 1st result returned from this method
+ // invocation.
+ Result0 map[*db.Repository]db.AccessMode
+ // Result1 is the value of the 2nd result returned from this method
+ // invocation.
+ Result1 error
+}
+
+// Args returns an interface slice containing the arguments of this
+// invocation.
+func (c ReposStoreGetByCollaboratorIDWithAccessModeFuncCall) Args() []interface{} {
+ return []interface{}{c.Arg0, c.Arg1}
+}
+
+// Results returns an interface slice containing the results of this
+// invocation.
+func (c ReposStoreGetByCollaboratorIDWithAccessModeFuncCall) Results() []interface{} {
+ return []interface{}{c.Result0, c.Result1}
+}
+
// ReposStoreGetByNameFunc describes the behavior when the GetByName method
// of the parent MockReposStore instance is invoked.
type ReposStoreGetByNameFunc struct {
diff --git a/internal/route/user/home.go b/internal/route/user/home.go
index f9f1b7b1..4521f511 100644
--- a/internal/route/user/home.go
+++ b/internal/route/user/home.go
@@ -125,9 +125,9 @@ func Dashboard(c *context.Context) {
// Only user can have collaborative repositories.
if !ctxUser.IsOrganization() {
- collaborateRepos, err := c.User.GetAccessibleRepositories(conf.UI.User.RepoPagingNum)
+ collaborateRepos, err := db.Repos.GetByCollaboratorID(c.Req.Context(), c.User.ID, conf.UI.User.RepoPagingNum, "updated_unix DESC")
if err != nil {
- c.Error(err, "get accessible repositories")
+ c.Error(err, "get accessible repositories by collaborator")
return
} else if err = db.RepositoryList(collaborateRepos).LoadAttributes(); err != nil {
c.Error(err, "load attributes")