gitforgefs/platforms/gitlab/user.go

124 lines
3.0 KiB
Go
Raw Normal View History

2020-12-30 00:49:11 +00:00
package gitlab
import (
"fmt"
2020-12-31 20:00:10 +00:00
"sync"
2020-12-30 00:49:11 +00:00
"github.com/badjware/gitlabfs/fstree"
2020-12-30 00:49:11 +00:00
"github.com/xanzy/go-gitlab"
)
type User struct {
ID int
Name string
mux sync.Mutex
// hold user content
2024-06-07 02:01:22 +00:00
childProjects map[string]fstree.RepositorySource
2020-12-30 00:49:11 +00:00
}
func (u *User) GetGroupID() uint64 {
return uint64(u.ID)
2020-12-30 00:49:11 +00:00
}
func (u *User) InvalidateContentCache() {
2020-12-31 20:00:10 +00:00
u.mux.Lock()
defer u.mux.Unlock()
2024-06-07 02:01:22 +00:00
// clear child repositories from cache
u.childProjects = nil
2020-12-31 20:00:10 +00:00
}
func (c *gitlabClient) fetchUser(uid int) (*User, error) {
// start by searching the cache
// TODO: cache invalidation?
c.userCacheMux.RLock()
user, found := c.userCache[uid]
c.userCacheMux.RUnlock()
if found {
// if found in cache, return the cached reference
c.logger.Debug("User cache hit", "uid", uid)
return user, nil
} else {
c.logger.Debug("User cache miss", "uid", uid)
}
// If not found in cache, fetch group infos from API
2020-12-30 00:49:11 +00:00
gitlabUser, _, err := c.client.Users.GetUser(uid)
if err != nil {
return nil, fmt.Errorf("failed to fetch user with id %v: %v", uid, err)
}
newUser := User{
ID: gitlabUser.ID,
Name: gitlabUser.Username,
2024-06-07 02:01:22 +00:00
childProjects: nil,
}
// save in cache
2024-07-19 04:12:39 +00:00
c.userCacheMux.Lock()
c.userCache[uid] = &newUser
c.userCacheMux.Unlock()
return &newUser, nil
2020-12-30 00:49:11 +00:00
}
func (c *gitlabClient) fetchCurrentUser() (*User, error) {
if c.currentUserCache == nil {
gitlabUser, _, err := c.client.Users.CurrentUser()
if err != nil {
return nil, fmt.Errorf("failed to fetch current user: %v", err)
}
newUser := User{
ID: gitlabUser.ID,
Name: gitlabUser.Username,
2024-06-07 02:01:22 +00:00
childProjects: nil,
}
c.currentUserCache = &newUser
2020-12-30 00:49:11 +00:00
}
return c.currentUserCache, nil
2020-12-30 00:49:11 +00:00
}
func (c *gitlabClient) fetchUserContent(user *User) (map[string]fstree.GroupSource, map[string]fstree.RepositorySource, error) {
// Only a single routine can fetch the user content at the time.
// We lock for the whole duration of the function to avoid fetching the same data from the API
// multiple times if concurrent calls where to occur.
2020-12-31 20:00:10 +00:00
user.mux.Lock()
defer user.mux.Unlock()
// Get cached data if available
// TODO: cache cache invalidation?
2024-06-07 02:01:22 +00:00
if user.childProjects == nil {
childProjects := make(map[string]fstree.RepositorySource)
// Fetch the user repositories
listProjectOpt := &gitlab.ListProjectsOptions{
ListOptions: gitlab.ListOptions{
Page: 1,
PerPage: 100,
}}
for {
gitlabProjects, response, err := c.client.Projects.ListUserProjects(user.ID, listProjectOpt)
if err != nil {
return nil, nil, fmt.Errorf("failed to fetch projects in gitlab: %v", err)
}
for _, gitlabProject := range gitlabProjects {
project := c.newProjectFromGitlabProject(gitlabProject)
if project != nil {
childProjects[project.Path] = project
}
}
if response.CurrentPage >= response.TotalPages {
break
}
// Get the next page
listProjectOpt.Page = response.NextPage
2020-12-30 00:49:11 +00:00
}
2024-06-07 02:01:22 +00:00
user.childProjects = childProjects
}
2024-06-07 02:01:22 +00:00
return make(map[string]fstree.GroupSource), user.childProjects, nil
2020-12-30 00:49:11 +00:00
}