repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
03dd883
parent
7f9ad09
author
Eric Bower
date
2024-06-25 10:16:38 -0400 EDT
feat: acl
3 files changed,  +42, -3
M db.go
M pr.go
M ssh.go
M db.go
+10, -0
 1@@ -17,6 +17,15 @@ type User struct {
 2 	UpdatedAt time.Time `db:"updated_at"`
 3 }
 4 
 5+type Acl struct {
 6+	ID         int64     `db:"id"`
 7+	UserID     int64     `db:"user_id"`
 8+	Pubkey     string    `db:"pubkey"`
 9+	IpAddress  string    `db:"ip_address"`
10+	Permission string    `db:"permission"`
11+	CreatedAt  time.Time `db:"created_at"`
12+}
13+
14 // PatchRequest is a database model for patches submitted to a Repo.
15 type PatchRequest struct {
16 	ID        int64     `db:"id"`
17@@ -77,6 +86,7 @@ CREATE TABLE IF NOT EXISTS app_users (
18 CREATE TABLE IF NOT EXISTS acl (
19   id INTEGER PRIMARY KEY AUTOINCREMENT,
20   user_id INTEGER,
21+  pubkey string,
22   ip_address string,
23   permission string,
24   created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
M pr.go
+15, -0
 1@@ -28,6 +28,7 @@ type GitPatchRequest interface {
 2 	GetUserByID(userID int64) (*User, error)
 3 	GetUserByPubkey(pubkey string) (*User, error)
 4 	UpsertUser(pubkey, name string) (*User, error)
 5+	IsBanned(pubkey, ipAddress string) error
 6 	GetRepos() ([]*Repo, error)
 7 	GetReposWithLatestPr() ([]RepoWithLatestPr, error)
 8 	GetRepoByID(repoID string) (*Repo, error)
 9@@ -54,6 +55,20 @@ type PrCmd struct {
10 var _ GitPatchRequest = PrCmd{}
11 var _ GitPatchRequest = (*PrCmd)(nil)
12 
13+func (pr PrCmd) IsBanned(pubkey, ipAddress string) error {
14+	acl := []*Acl{}
15+	err := pr.Backend.DB.Select(
16+		&acl,
17+		"SELECT * FROM acl WHERE permission='banned' AND (pubkey=? OR ip_address=?)",
18+		pubkey,
19+		ipAddress,
20+	)
21+	if len(acl) > 0 {
22+		return fmt.Errorf("user has been banned")
23+	}
24+	return err
25+}
26+
27 func (pr PrCmd) GetUsers() ([]*User, error) {
28 	users := []*User{}
29 	err := pr.Backend.DB.Select(&users, "SELECT * FROM app_users")
M ssh.go
+17, -3
 1@@ -14,8 +14,22 @@ import (
 2 	"github.com/charmbracelet/wish"
 3 )
 4 
 5-func authHandler(ctx ssh.Context, key ssh.PublicKey) bool {
 6-	return true
 7+func authHandler(pr *PrCmd) func(ctx ssh.Context, key ssh.PublicKey) bool {
 8+	return func(ctx ssh.Context, key ssh.PublicKey) bool {
 9+		pubkey := pr.Backend.Pubkey(key)
10+		userName := ctx.User()
11+		err := pr.IsBanned(pubkey, userName)
12+		if err != nil {
13+			pr.Backend.Logger.Info(
14+				"user denied access",
15+				"err", err,
16+				"username", userName,
17+				"pubkey", pubkey,
18+			)
19+			return false
20+		}
21+		return true
22+	}
23 }
24 
25 func GitSshServer(cfg *GitCfg) {
26@@ -53,7 +67,7 @@ func GitSshServer(cfg *GitCfg) {
27 		wish.WithHostKeyPath(
28 			filepath.Join(cfg.DataPath, "term_info_ed25519"),
29 		),
30-		wish.WithPublicKeyAuth(authHandler),
31+		wish.WithPublicKeyAuth(authHandler(prCmd)),
32 		wish.WithMiddleware(
33 			GitPatchRequestMiddleware(be, prCmd),
34 		),