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