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.ValidateHandle(username); err != nil {
22 return err
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 handle_id = (
32 SELECT id FROM handles WHERE handle = ?
33 )
34 ),
35 (
36 SELECT id FROM repos WHERE name = ?
37 ),
38 CURRENT_TIMESTAMP
39 );`)
40 _, err := tx.ExecContext(ctx, query, level, username, repo)
41 return err
42}
43
44// GetCollabByUsernameAndRepo implements store.CollaboratorStore.
45func (*collabStore) GetCollabByUsernameAndRepo(ctx context.Context, tx db.Handler, username string, repo string) (models.Collab, error) {
46 var m models.Collab
47
48 username = strings.ToLower(username)
49 if err := utils.ValidateHandle(username); err != nil {
50 return models.Collab{}, err
51 }
52
53 repo = utils.SanitizeRepo(repo)
54
55 err := tx.GetContext(ctx, &m, tx.Rebind(`
56 SELECT
57 collabs.*
58 FROM
59 collabs
60 INNER JOIN users ON users.id = collabs.user_id
61 INNER JOIN handles ON handles.id = users.handle_id
62 INNER JOIN repos ON repos.id = collabs.repo_id
63 WHERE
64 handles.handle = ? AND repos.name = ?
65 `), username, repo)
66
67 return m, err
68}
69
70// ListCollabsByRepo implements store.CollaboratorStore.
71func (*collabStore) ListCollabsByRepo(ctx context.Context, tx db.Handler, repo string) ([]models.Collab, error) {
72 var m []models.Collab
73
74 repo = utils.SanitizeRepo(repo)
75 query := tx.Rebind(`
76 SELECT
77 collabs.*
78 FROM
79 collabs
80 INNER JOIN repos ON repos.id = collabs.repo_id
81 WHERE
82 repos.name = ?
83 `)
84
85 err := tx.SelectContext(ctx, &m, query, repo)
86 return m, err
87}
88
89// ListCollabsByRepoAsUsers implements store.CollaboratorStore.
90func (*collabStore) ListCollabsByRepoAsUsers(ctx context.Context, tx db.Handler, repo string) ([]models.User, error) {
91 var m []models.User
92
93 repo = utils.SanitizeRepo(repo)
94 query := tx.Rebind(`
95 SELECT
96 users.*
97 FROM
98 users
99 INNER JOIN collabs ON collabs.user_id = users.id
100 INNER JOIN repos ON repos.id = collabs.repo_id
101 WHERE
102 repos.name = ?
103 `)
104
105 err := tx.SelectContext(ctx, &m, query, repo)
106 return m, err
107}
108
109// RemoveCollabByUsernameAndRepo implements store.CollaboratorStore.
110func (*collabStore) RemoveCollabByUsernameAndRepo(ctx context.Context, tx db.Handler, username string, repo string) error {
111 username = strings.ToLower(username)
112 if err := utils.ValidateHandle(username); err != nil {
113 return err
114 }
115
116 repo = utils.SanitizeRepo(repo)
117 query := tx.Rebind(`
118 DELETE FROM
119 collabs
120 WHERE
121 user_id = (
122 SELECT id FROM users WHERE handle_id = (
123 SELECT id FROM handles WHERE handle = ?
124 )
125 ) AND repo_id = (
126 SELECT id FROM repos WHERE name = ?
127 )
128 `)
129 _, err := tx.ExecContext(ctx, query, username, repo)
130 return err
131}