fix(backend): propagate errors

Ayman Bagabas created

Change summary

server/backend/repo.go          | 12 +++++-----
server/backend/sqlite/sqlite.go | 38 +++++++++++++++++-----------------
server/backend/sqlite/user.go   |  3 +
server/cmd/cmd.go               |  6 ++--
server/cmd/description.go       |  6 ++++
server/cmd/hidden.go            |  6 ++++
server/cmd/private.go           |  6 ++++
server/cmd/project_name.go      |  6 ++++
8 files changed, 50 insertions(+), 33 deletions(-)

Detailed changes

server/backend/repo.go 🔗

@@ -34,28 +34,28 @@ type RepositoryStore interface {
 // RepositoryMetadata is an interface for managing repository metadata.
 type RepositoryMetadata interface {
 	// ProjectName returns the repository's project name.
-	ProjectName(repo string) string
+	ProjectName(repo string) (string, error)
 	// SetProjectName sets the repository's project name.
 	SetProjectName(repo, name string) error
 	// Description returns the repository's description.
-	Description(repo string) string
+	Description(repo string) (string, error)
 	// SetDescription sets the repository's description.
 	SetDescription(repo, desc string) error
 	// IsPrivate returns whether the repository is private.
-	IsPrivate(repo string) bool
+	IsPrivate(repo string) (bool, error)
 	// SetPrivate sets whether the repository is private.
 	SetPrivate(repo string, private bool) error
 	// IsMirror returns whether the repository is a mirror.
-	IsMirror(repo string) bool
+	IsMirror(repo string) (bool, error)
 	// IsHidden returns whether the repository is hidden.
-	IsHidden(repo string) bool
+	IsHidden(repo string) (bool, error)
 	// SetHidden sets whether the repository is hidden.
 	SetHidden(repo string, hidden bool) error
 }
 
 // RepositoryAccess is an interface for managing repository access.
 type RepositoryAccess interface {
-	IsCollaborator(repo string, username string) bool
+	IsCollaborator(repo string, username string) (bool, error)
 	// AddCollaborator adds the authorized key as a collaborator on the repository.
 	AddCollaborator(repo string, username string) error
 	// RemoveCollaborator removes the authorized key as a collaborator on the repository.

server/backend/sqlite/sqlite.go 🔗

@@ -134,7 +134,7 @@ func (d *SqliteBackend) CreateRepository(name string, opts backend.RepositoryOpt
 
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		_, err := tx.Exec(`INSERT INTO repo (name, project_name, description, private, mirror, hidden, updated_at)
-			VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP);`,
+			VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP);`,
 			name, opts.ProjectName, opts.Description, opts.Private, opts.Mirror, opts.Hidden)
 		return err
 	}); err != nil {
@@ -282,61 +282,61 @@ func (d *SqliteBackend) Repository(repo string) (backend.Repository, error) {
 // Description returns the description of a repository.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) Description(repo string) string {
+func (d *SqliteBackend) Description(repo string) (string, error) {
 	repo = utils.SanitizeRepo(repo)
 	var desc string
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		return tx.Get(&desc, "SELECT description FROM repo WHERE name = ?", repo)
 	}); err != nil {
-		return ""
+		return "", wrapDbErr(err)
 	}
 
-	return desc
+	return desc, nil
 }
 
 // IsMirror returns true if the repository is a mirror.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) IsMirror(repo string) bool {
+func (d *SqliteBackend) IsMirror(repo string) (bool, error) {
 	repo = utils.SanitizeRepo(repo)
 	var mirror bool
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		return tx.Get(&mirror, "SELECT mirror FROM repo WHERE name = ?", repo)
 	}); err != nil {
-		return false
+		return false, wrapDbErr(err)
 	}
 
-	return mirror
+	return mirror, nil
 }
 
 // IsPrivate returns true if the repository is private.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) IsPrivate(repo string) bool {
+func (d *SqliteBackend) IsPrivate(repo string) (bool, error) {
 	repo = utils.SanitizeRepo(repo)
 	var private bool
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		return tx.Get(&private, "SELECT private FROM repo WHERE name = ?", repo)
 	}); err != nil {
-		return false
+		return false, wrapDbErr(err)
 	}
 
-	return private
+	return private, nil
 }
 
 // IsHidden returns true if the repository is hidden.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) IsHidden(repo string) bool {
+func (d *SqliteBackend) IsHidden(repo string) (bool, error) {
 	repo = utils.SanitizeRepo(repo)
 	var hidden bool
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		return tx.Get(&hidden, "SELECT hidden FROM repo WHERE name = ?", repo)
 	}); err != nil {
-		return false
+		return false, wrapDbErr(err)
 	}
 
-	return hidden
+	return hidden, nil
 }
 
 // SetHidden sets the hidden flag of a repository.
@@ -353,16 +353,16 @@ func (d *SqliteBackend) SetHidden(repo string, hidden bool) error {
 // ProjectName returns the project name of a repository.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) ProjectName(repo string) string {
+func (d *SqliteBackend) ProjectName(repo string) (string, error) {
 	repo = utils.SanitizeRepo(repo)
 	var name string
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
 		return tx.Get(&name, "SELECT project_name FROM repo WHERE name = ?", repo)
 	}); err != nil {
-		return ""
+		return "", wrapDbErr(err)
 	}
 
-	return name
+	return name, nil
 }
 
 // SetDescription sets the description of a repository.
@@ -440,7 +440,7 @@ func (d *SqliteBackend) Collaborators(repo string) ([]string, error) {
 // IsCollaborator returns true if the user is a collaborator of the repository.
 //
 // It implements backend.Backend.
-func (d *SqliteBackend) IsCollaborator(repo string, username string) bool {
+func (d *SqliteBackend) IsCollaborator(repo string, username string) (bool, error) {
 	repo = utils.SanitizeRepo(repo)
 	var count int
 	if err := wrapTx(d.db, context.Background(), func(tx *sqlx.Tx) error {
@@ -449,10 +449,10 @@ func (d *SqliteBackend) IsCollaborator(repo string, username string) bool {
 			INNER JOIN repo ON repo.id = collab.repo_id
 			WHERE repo.name = ? AND user.username = ?`, repo, username)
 	}); err != nil {
-		return false
+		return false, wrapDbErr(err)
 	}
 
-	return count > 0
+	return count > 0, nil
 }
 
 // RemoveCollaborator removes a collaborator from a repository.

server/backend/sqlite/user.go 🔗

@@ -82,7 +82,8 @@ func (d *SqliteBackend) AccessLevel(repo string, username string) backend.Access
 	r, _ := d.Repository(repo)
 	if r != nil {
 		// If the user is a collaborator, they have read/write access.
-		if d.IsCollaborator(repo, username) {
+		isCollab, _ := d.IsCollaborator(repo, username)
+		if isCollab {
 			if anon > backend.ReadWriteAccess {
 				return anon
 			}

server/cmd/cmd.go 🔗

@@ -108,9 +108,9 @@ func checkIfAdmin(cmd *cobra.Command, _ []string) error {
 		}
 	}
 
-	user, err := cfg.Backend.UserByPublicKey(s.PublicKey())
-	if err != nil {
-		return err
+	user, _ := cfg.Backend.UserByPublicKey(s.PublicKey())
+	if user == nil {
+		return ErrUnauthorized
 	}
 
 	if !user.IsAdmin() {

server/cmd/description.go 🔗

@@ -21,7 +21,11 @@ func descriptionCommand() *cobra.Command {
 					return err
 				}
 
-				desc := cfg.Backend.Description(rn)
+				desc, err := cfg.Backend.Description(rn)
+				if err != nil {
+					return err
+				}
+
 				cmd.Println(desc)
 			default:
 				if err := checkIfCollab(cmd, args); err != nil {

server/cmd/hidden.go 🔗

@@ -16,7 +16,11 @@ func hiddenCommand() *cobra.Command {
 					return err
 				}
 
-				hidden := cfg.Backend.IsHidden(repo)
+				hidden, err := cfg.Backend.IsHidden(repo)
+				if err != nil {
+					return err
+				}
+
 				cmd.Println(hidden)
 			case 2:
 				if err := checkIfCollab(cmd, args); err != nil {

server/cmd/private.go 🔗

@@ -22,7 +22,11 @@ func privateCommand() *cobra.Command {
 					return err
 				}
 
-				isPrivate := cfg.Backend.IsPrivate(rn)
+				isPrivate, err := cfg.Backend.IsPrivate(rn)
+				if err != nil {
+					return err
+				}
+
 				cmd.Println(isPrivate)
 			case 2:
 				isPrivate, err := strconv.ParseBool(args[1])

server/cmd/project_name.go 🔗

@@ -21,7 +21,11 @@ func projectName() *cobra.Command {
 					return err
 				}
 
-				pn := cfg.Backend.ProjectName(rn)
+				pn, err := cfg.Backend.ProjectName(rn)
+				if err != nil {
+					return err
+				}
+
 				cmd.Println(pn)
 			default:
 				if err := checkIfCollab(cmd, args); err != nil {