feat(db): add IsRepoPublicKeyCollab to get whether key is a repo collab

Ayman Bagabas created

Change summary

server/db/db.go            |  1 +
server/db/fakedb/db.go     |  5 +++++
server/db/sqlite/sql.go    | 17 +++++++++--------
server/db/sqlite/sqlite.go | 18 ++++++++++++++++++
4 files changed, 33 insertions(+), 8 deletions(-)

Detailed changes

server/db/db.go 🔗

@@ -47,6 +47,7 @@ type CollabStore interface {
 	DeleteRepoCollab(int, int) error
 	ListRepoCollabs(string) ([]*types.User, error)
 	ListRepoPublicKeys(string) ([]*types.PublicKey, error)
+	IsRepoPublicKeyCollab(string, string) (bool, error)
 }
 
 // Store is a database.

server/db/fakedb/db.go 🔗

@@ -165,6 +165,11 @@ func (*FakeDB) ListRepoPublicKeys(string) ([]*types.PublicKey, error) {
 	return nil, nil
 }
 
+// IsRepoPublicKeyCollab implements db.Store.
+func (*FakeDB) IsRepoPublicKeyCollab(string, string) (bool, error) {
+	return false, nil
+}
+
 // Close implements db.Store.
 func (*FakeDB) Close() error {
 	return nil

server/db/sqlite/sql.go 🔗

@@ -81,12 +81,13 @@ var (
 	sqlUpdateRepoPrivateByName     = `UPDATE repo SET private = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?;`
 
 	// Collab.
-	sqlInsertCollab               = `INSERT INTO collab (user_id, repo_id, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP);`
-	sqlInsertCollabByName         = `INSERT INTO collab (user_id, repo_id, updated_at) VALUES (?, (SELECT id FROM repo WHERE name = ?), CURRENT_TIMESTAMP);`
-	sqlDeleteCollab               = `DELETE FROM collab WHERE user_id = ? AND repo_id = ?;`
-	sqlDeleteCollabByName         = `DELETE FROM collab WHERE user_id = ? AND repo_id = (SELECT id FROM repo WHERE name = ?);`
-	sqlSelectRepoCollabs          = `SELECT user.id, user.name, user.login, user.email, user.admin, user.created_at, user.updated_at FROM user INNER JOIN collab ON user.id = collab.user_id WHERE collab.repo_id = ?;`
-	sqlSelectRepoCollabsByName    = `SELECT user.id, user.name, user.login, user.email, user.admin, user.created_at, user.updated_at FROM user INNER JOIN collab ON user.id = collab.user_id WHERE collab.repo_id = (SELECT id FROM repo WHERE name = ?);`
-	sqlSelectRepoPublicKeys       = `SELECT public_key.id, public_key.user_id, public_key.public_key, public_key.created_at, public_key.updated_at FROM public_key INNER JOIN collab ON public_key.user_id = collab.user_id WHERE collab.repo_id = ?;`
-	sqlSelectRepoPublicKeysByName = `SELECT public_key.id, public_key.user_id, public_key.public_key, public_key.created_at, public_key.updated_at FROM public_key INNER JOIN collab ON public_key.user_id = collab.user_id WHERE collab.repo_id = (SELECT id FROM repo WHERE name = ?);`
+	sqlInsertCollab                    = `INSERT INTO collab (user_id, repo_id, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP);`
+	sqlInsertCollabByName              = `INSERT INTO collab (user_id, repo_id, updated_at) VALUES (?, (SELECT id FROM repo WHERE name = ?), CURRENT_TIMESTAMP);`
+	sqlDeleteCollab                    = `DELETE FROM collab WHERE user_id = ? AND repo_id = ?;`
+	sqlDeleteCollabByName              = `DELETE FROM collab WHERE user_id = ? AND repo_id = (SELECT id FROM repo WHERE name = ?);`
+	sqlSelectRepoCollabs               = `SELECT user.id, user.name, user.login, user.email, user.admin, user.created_at, user.updated_at FROM user INNER JOIN collab ON user.id = collab.user_id WHERE collab.repo_id = ?;`
+	sqlSelectRepoCollabsByName         = `SELECT user.id, user.name, user.login, user.email, user.admin, user.created_at, user.updated_at FROM user INNER JOIN collab ON user.id = collab.user_id WHERE collab.repo_id = (SELECT id FROM repo WHERE name = ?);`
+	sqlSelectRepoPublicKeys            = `SELECT public_key.id, public_key.user_id, public_key.public_key, public_key.created_at, public_key.updated_at FROM public_key INNER JOIN collab ON public_key.user_id = collab.user_id WHERE collab.repo_id = ?;`
+	sqlSelectRepoPublicKeysByName      = `SELECT public_key.id, public_key.user_id, public_key.public_key, public_key.created_at, public_key.updated_at FROM public_key INNER JOIN collab ON public_key.user_id = collab.user_id WHERE collab.repo_id = (SELECT id FROM repo WHERE name = ?);`
+	sqlSelectRepoPublicKeyCollabByName = `SELECT COUNT(*) FROM public_key INNER JOIN collab ON public_key.user_id = collab.user_id WHERE collab.repo_id = (SELECT id FROM repo WHERE name = ?) AND public_key.public_key = ?;`
 )

server/db/sqlite/sqlite.go 🔗

@@ -404,6 +404,24 @@ func (d *Sqlite) ListRepoPublicKeys(repo string) ([]*types.PublicKey, error) {
 	return keys, nil
 }
 
+// IsRepoPublicKeyCollab returns true if the public key is a collaborator for the repository.
+func (d *Sqlite) IsRepoPublicKeyCollab(repo string, key string) (bool, error) {
+	var count int
+	if err := d.wrapTransaction(func(tx *sql.Tx) error {
+		rows := tx.QueryRow(sqlSelectRepoPublicKeyCollabByName, repo, key)
+		if err := rows.Scan(&count); err != nil {
+			return err
+		}
+		if err := rows.Err(); err != nil {
+			return err
+		}
+		return nil
+	}); err != nil {
+		return false, err
+	}
+	return count > 0, nil
+}
+
 // WrapTransaction runs the given function within a transaction.
 func (d *Sqlite) wrapTransaction(f func(tx *sql.Tx) error) error {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)