1package backend
 2
 3import (
 4	"context"
 5	"strings"
 6
 7	"github.com/charmbracelet/soft-serve/server/access"
 8	"github.com/charmbracelet/soft-serve/server/db"
 9	"github.com/charmbracelet/soft-serve/server/db/models"
10	"github.com/charmbracelet/soft-serve/server/utils"
11)
12
13// AddCollaborator adds a collaborator to a repository.
14//
15// It implements backend.Backend.
16func (d *Backend) AddCollaborator(ctx context.Context, repo string, username string, level access.AccessLevel) error {
17	username = strings.ToLower(username)
18	if err := utils.ValidateUsername(username); err != nil {
19		return err
20	}
21
22	repo = utils.SanitizeRepo(repo)
23	return db.WrapError(
24		d.db.TransactionContext(ctx, func(tx *db.Tx) error {
25			return d.store.AddCollabByUsernameAndRepo(ctx, tx, username, repo, level)
26		}),
27	)
28}
29
30// Collaborators returns a list of collaborators for a repository.
31//
32// It implements backend.Backend.
33func (d *Backend) Collaborators(ctx context.Context, repo string) ([]string, error) {
34	repo = utils.SanitizeRepo(repo)
35	var users []models.User
36	if err := d.db.TransactionContext(ctx, func(tx *db.Tx) error {
37		var err error
38		users, err = d.store.ListCollabsByRepoAsUsers(ctx, tx, repo)
39		return err
40	}); err != nil {
41		return nil, db.WrapError(err)
42	}
43
44	var usernames []string
45	for _, u := range users {
46		usernames = append(usernames, u.Username)
47	}
48
49	return usernames, nil
50}
51
52// IsCollaborator returns the access level and true if the user is a collaborator of the repository.
53//
54// It implements backend.Backend.
55func (d *Backend) IsCollaborator(ctx context.Context, repo string, username string) (access.AccessLevel, bool, error) {
56	if username == "" {
57		return -1, false, nil
58	}
59
60	repo = utils.SanitizeRepo(repo)
61	var m models.Collab
62	if err := d.db.TransactionContext(ctx, func(tx *db.Tx) error {
63		var err error
64		m, err = d.store.GetCollabByUsernameAndRepo(ctx, tx, username, repo)
65		return err
66	}); err != nil {
67		return -1, false, db.WrapError(err)
68	}
69
70	return m.AccessLevel, m.ID > 0, nil
71}
72
73// RemoveCollaborator removes a collaborator from a repository.
74//
75// It implements backend.Backend.
76func (d *Backend) RemoveCollaborator(ctx context.Context, repo string, username string) error {
77	repo = utils.SanitizeRepo(repo)
78	return db.WrapError(
79		d.db.TransactionContext(ctx, func(tx *db.Tx) error {
80			return d.store.RemoveCollabByUsernameAndRepo(ctx, tx, username, repo)
81		}),
82	)
83}