Goit

Simple and lightweight Git web server
git clone http://git.omkov.net/Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2024-06-16 10:57:19
Commit2954edd7dff67c4d435e513612e741d9483bba35
Parent774bd71421447e58d001ecef4ae975cab4719949

Add visibility filter to repository index

Diffstat

M .vscode/launch.json | 2 +-
M src/goit/db.go | 135 +++++++++++++++++++++++++++++++------------------------------------------------
M src/goit/goit.go | 2 +-
M src/goit/index.go | 12 ++++++++++--
M src/util/util.go | 9 +++++++++

5 files changed, 74 insertions, 86 deletions

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 17d6e25..ecbe435 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,7 +6,7 @@
 			"type": "go",
 			"request": "launch",
 			"program": "${workspaceFolder}/src/main.go",
-			"cwd": "${workspaceFolder}/bin",
+			"cwd": "${workspaceFolder}",
 			"mode": "debug",
 			"args": ["--debug"],
 			"postDebugTask": "clean",
diff --git a/src/goit/db.go b/src/goit/db.go
index 672a9c2..734f8c2 100644
--- a/src/goit/db.go
+++ b/src/goit/db.go
@@ -8,46 +8,24 @@ import (
 	"github.com/Jamozed/Goit/src/util"
 )
 
-/*
-	Version 1 Table Schemas
-
-	CREATE TABLE IF NOT EXISTS users (
-		id INTEGER PRIMARY KEY AUTOINCREMENT,
-		name TEXT UNIQUE NOT NULL,
-		name_full TEXT NOT NULL,
-		pass BLOB NOT NULL,
-		pass_algo TEXT NOT NULL,
-		salt BLOB NOT NULL,
-		is_admin BOOLEAN NOT NULL
-	)
-
-	CREATE TABLE IF NOT EXISTS repos (
-		id INTEGER PRIMARY KEY AUTOINCREMENT,
-		owner_id INTEGER NOT NULL,
-		name TEXT UNIQUE NOT NULL,
-		name_lower TEXT UNIQUE NOT NULL,
-		description TEXT NOT NULL,
-		upstream TEXT NOT NULL,
-		is_private BOOLEAN NOT NULL,
-		is_mirror BOOLEAN NOT NULL
-	)
-*/
-
-func dbUpdate(db *sql.DB) error {
-	latestVersion := 3
+func updateDatabase(db *sql.DB) error {
+	const LATEST_VERSION = 3
 
 	var version int
 	if err := db.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
 		return err
 	}
 
-	if version > latestVersion {
-		return fmt.Errorf("database version is newer than supported (%d > %d)", version, latestVersion)
+	if version > LATEST_VERSION {
+		return fmt.Errorf("database version is newer than supported (%d > %d)", version, LATEST_VERSION)
 	}
 
-	if version == 0 {
-		/* Database is empty or new, initialise the newest version */
-		log.Println("Initialising database at version", latestVersion)
+	logMigration := true
+
+	if version <= 0 {
+		/* Database is empty or new, initialise from scratch */
+		log.Println("Initialising database at version", LATEST_VERSION)
+		logMigration = false
 
 		if _, err := db.Exec(
 			`CREATE TABLE IF NOT EXISTS users (
@@ -70,83 +48,76 @@ func dbUpdate(db *sql.DB) error {
 				name TEXT UNIQUE NOT NULL,
 				name_lower TEXT UNIQUE NOT NULL,
 				description TEXT NOT NULL,
-				default_branch TEXT NOT NULL,
 				upstream TEXT NOT NULL,
-				visibility INTEGER NOT NULL,
+				is_private BOOLEAN NOT NULL,
 				is_mirror BOOLEAN NOT NULL
 			)`,
 		); err != nil {
 			return err
 		}
 
-		if _, err := db.Exec(fmt.Sprint("PRAGMA user_version = ", latestVersion)); err != nil {
-			return err
-		}
+		version = 1
 	}
-
-	for {
-		switch version {
-		case 1: /* 1 -> 2 */
+	if version <= 1 {
+		if logMigration {
 			log.Println("Migrating database from version 1 to 2")
+		}
 
-			if _, err := db.Exec(
-				"ALTER TABLE repos ADD COLUMN default_branch TEXT NOT NULL DEFAULT 'master'",
-			); err != nil {
-				return err
-			}
-
-			version = 2
+		if _, err := db.Exec(
+			"ALTER TABLE repos ADD COLUMN default_branch TEXT NOT NULL DEFAULT 'master'",
+		); err != nil {
+			return err
+		}
 
-		case 2: /* 2 -> 3 */
+		version = 2
+	}
+	if version <= 2 {
+		if logMigration {
 			log.Println("Migrating database from version 2 to 3")
+		}
 
-			if _, err := db.Exec(
-				"ALTER TABLE repos ADD COLUMN visibility INTEGER NOT NULL DEFAULT 0",
-			); err != nil {
-				return err
-			}
-
-			/* Set values for each repo according to is_private */
-			var visibilities = map[int64]Visibility{}
+		if _, err := db.Exec(
+			"ALTER TABLE repos ADD COLUMN visibility INTEGER NOT NULL DEFAULT 0",
+		); err != nil {
+			return err
+		}
 
-			if rows, err := db.Query("SELECT id, is_private FROM repos"); err != nil {
-				return err
-			} else {
-				for rows.Next() {
-					var id int64
-					var isPrivate bool
+		/* Set values for each repo according to is_private */
+		var visibilities = map[int64]Visibility{}
 
-					if err := rows.Scan(&id, &isPrivate); err != nil {
-						return err
-					}
+		if rows, err := db.Query("SELECT id, is_private FROM repos"); err != nil {
+			return err
+		} else {
+			for rows.Next() {
+				var id int64
+				var isPrivate bool
 
-					visibilities[id] = util.If(isPrivate, Private, Public)
+				if err := rows.Scan(&id, &isPrivate); err != nil {
+					return err
 				}
 
-				rows.Close()
+				visibilities[id] = util.If(isPrivate, Private, Public)
 			}
 
-			for id, visibility := range visibilities {
-				if _, err := db.Exec(
-					"UPDATE repos SET visibility = ? WHERE id = ?", visibility, id,
-				); err != nil {
-					return err
-				}
-			}
+			rows.Close()
+		}
 
-			/* Remove is_private column */
-			if _, err := db.Exec("ALTER TABLE repos DROP COLUMN is_private"); err != nil {
+		for id, visibility := range visibilities {
+			if _, err := db.Exec(
+				"UPDATE repos SET visibility = ? WHERE id = ?", visibility, id,
+			); err != nil {
 				return err
 			}
+		}
 
-			version = 3
-
-		default: /* No required migrations */
-			goto done
+		/* Remove is_private column */
+		if _, err := db.Exec("ALTER TABLE repos DROP COLUMN is_private"); err != nil {
+			return err
 		}
+
+		version = 3
 	}
 
-done:
 	if _, err := db.Exec(fmt.Sprint("PRAGMA user_version = ", version)); err != nil {
 		return err
 	}
diff --git a/src/goit/goit.go b/src/goit/goit.go
index 6011243..121ba4f 100644
--- a/src/goit/goit.go
+++ b/src/goit/goit.go
@@ -70,7 +70,7 @@ func Goit() error {
 	}
 
 	/* Update the database if necessary */
-	if err := dbUpdate(db); err != nil {
+	if err := updateDatabase(db); err != nil {
 		return fmt.Errorf("[database] %w", err)
 	}
 
diff --git a/src/goit/index.go b/src/goit/index.go
index e127415..597f6d0 100644
--- a/src/goit/index.go
+++ b/src/goit/index.go
@@ -7,10 +7,12 @@ import (
 	"errors"
 	"log"
 	"net/http"
+	"slices"
 	"sort"
 	"strings"
 	"time"
 
+	"github.com/Jamozed/Goit/src/util"
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 )
@@ -23,7 +25,8 @@ func HandleIndex(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	userQuery := r.FormValue("u")
+	userQuery := util.FormValues(r, "u")
+	visibilityQuery := util.FormValues(r, "v")
 
 	type row struct{ Name, Description, Owner, Visibility, LastCommit string }
 	data := struct {
@@ -64,7 +67,12 @@ func HandleIndex(w http.ResponseWriter, r *http.Request) {
 		}
 
 		/* Only display repositories matching user query if present */
-		if userQuery != "" && owner.Name != userQuery {
+		if len(userQuery) > 0 && !slices.Contains(userQuery, owner.Name) {
+			continue
+		}
+
+		/* Only display repositories matching a visibility query if present */
+		if len(visibilityQuery) > 0 && !slices.Contains(visibilityQuery, repo.Visibility.String()) {
 			continue
 		}
 
diff --git a/src/util/util.go b/src/util/util.go
index 4447a8d..105357e 100644
--- a/src/util/util.go
+++ b/src/util/util.go
@@ -46,6 +46,15 @@ func Cookie(r *http.Request, name string) *http.Cookie {
 	return nil
 }
 
+/* Return a slice of form values with the specified key. */
+func FormValues(r *http.Request, key string) []string {
+	if r.Form == nil {
+		r.ParseMultipartForm(32 << 20 /* 32 MB */)
+	}
+
+	return r.Form[key]
+}
+
 func ModeString(mode uint32) string {
 	s := If((mode&0o40000) != 0, "d", "-")
 	s += If((mode&0o400) != 0, "r", "-")