collab.go

  1package database
  2
  3import (
  4	"context"
  5	"strings"
  6
  7	"github.com/charmbracelet/soft-serve/pkg/access"
  8	"github.com/charmbracelet/soft-serve/pkg/db"
  9	"github.com/charmbracelet/soft-serve/pkg/db/models"
 10	"github.com/charmbracelet/soft-serve/pkg/store"
 11	"github.com/charmbracelet/soft-serve/pkg/utils"
 12)
 13
 14type collabStore struct{}
 15
 16var _ store.CollaboratorStore = (*collabStore)(nil)
 17
 18// AddCollabByUsernameAndRepo implements store.CollaboratorStore.
 19func (*collabStore) AddCollabByUsernameAndRepo(ctx context.Context, tx db.Handler, username string, repo string, level access.AccessLevel) error {
 20	username = strings.ToLower(username)
 21	if err := utils.ValidateUsername(username); err != nil {
 22		return err //nolint:wrapcheck
 23	}
 24
 25	repo = utils.SanitizeRepo(repo)
 26
 27	query := tx.Rebind(`INSERT INTO collabs (access_level, user_id, repo_id, updated_at)
 28			VALUES (
 29				?,
 30				(
 31					SELECT id FROM users WHERE username = ?
 32				),
 33				(
 34					SELECT id FROM repos WHERE name = ?
 35				),
 36				CURRENT_TIMESTAMP
 37			);`)
 38	_, err := tx.ExecContext(ctx, query, level, username, repo)
 39	return err //nolint:wrapcheck
 40}
 41
 42// GetCollabByUsernameAndRepo implements store.CollaboratorStore.
 43func (*collabStore) GetCollabByUsernameAndRepo(ctx context.Context, tx db.Handler, username string, repo string) (models.Collab, error) {
 44	var m models.Collab
 45
 46	username = strings.ToLower(username)
 47	if err := utils.ValidateUsername(username); err != nil {
 48		return models.Collab{}, err //nolint:wrapcheck
 49	}
 50
 51	repo = utils.SanitizeRepo(repo)
 52
 53	err := tx.GetContext(ctx, &m, tx.Rebind(`
 54		SELECT
 55			collabs.*
 56		FROM
 57			collabs
 58		INNER JOIN users ON users.id = collabs.user_id
 59		INNER JOIN repos ON repos.id = collabs.repo_id
 60		WHERE
 61			users.username = ? AND repos.name = ?
 62	`), username, repo)
 63
 64	return m, err //nolint:wrapcheck
 65}
 66
 67// ListCollabsByRepo implements store.CollaboratorStore.
 68func (*collabStore) ListCollabsByRepo(ctx context.Context, tx db.Handler, repo string) ([]models.Collab, error) {
 69	var m []models.Collab
 70
 71	repo = utils.SanitizeRepo(repo)
 72	query := tx.Rebind(`
 73		SELECT
 74			collabs.*
 75		FROM
 76			collabs
 77		INNER JOIN repos ON repos.id = collabs.repo_id
 78		WHERE
 79			repos.name = ?
 80	`)
 81
 82	err := tx.SelectContext(ctx, &m, query, repo)
 83	return m, err //nolint:wrapcheck
 84}
 85
 86// ListCollabsByRepoAsUsers implements store.CollaboratorStore.
 87func (*collabStore) ListCollabsByRepoAsUsers(ctx context.Context, tx db.Handler, repo string) ([]models.User, error) {
 88	var m []models.User
 89
 90	repo = utils.SanitizeRepo(repo)
 91	query := tx.Rebind(`
 92		SELECT
 93			users.*
 94		FROM
 95			users
 96		INNER JOIN collabs ON collabs.user_id = users.id
 97		INNER JOIN repos ON repos.id = collabs.repo_id
 98		WHERE
 99			repos.name = ?
100	`)
101
102	err := tx.SelectContext(ctx, &m, query, repo)
103	return m, err //nolint:wrapcheck
104}
105
106// RemoveCollabByUsernameAndRepo implements store.CollaboratorStore.
107func (*collabStore) RemoveCollabByUsernameAndRepo(ctx context.Context, tx db.Handler, username string, repo string) error {
108	username = strings.ToLower(username)
109	if err := utils.ValidateUsername(username); err != nil {
110		return err //nolint:wrapcheck
111	}
112
113	repo = utils.SanitizeRepo(repo)
114	query := tx.Rebind(`
115		DELETE FROM
116			collabs
117		WHERE
118			user_id = (
119				SELECT id FROM users WHERE username = ?
120			) AND repo_id = (
121				SELECT id FROM repos WHERE name = ?
122			)
123	`)
124	_, err := tx.ExecContext(ctx, query, username, repo)
125	return err //nolint:wrapcheck
126}