Goit

Simple and lightweight Git web server
git clone https://git.omkov.net/Goit
git clone [email protected]:Goit
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2025-01-04 22:53:33
Commita0fd9fb9f71026e34ecf9afc3c48236d13a8a370
Parenta12579f06473bd31846118c3ac7fa9807452ec7f

Backup user default visibility and keys

Diffstat

M src/goit/db.go | 2 ++
M src/goit/goit.go | 35 +++++++++++++++++++++++++++--------
M src/goit/user.go | 39 ++++++++++++++++++++++-----------------
M src/main.go | 2 +-
M src/util/log.go | 4 ++--

5 files changed, 54 insertions, 28 deletions

diff --git a/src/goit/db.go b/src/goit/db.go
index f3a0516..ec0f040 100644
--- a/src/goit/db.go
+++ b/src/goit/db.go
@@ -37,6 +37,8 @@ keys:
 	type INTEGER NOT NULL
 	description TEXT NOT NULL
 	key BLOB NOT NULL
+
+NOTE: Remember to update LATEST_VERSION and the backup function when changing the schema.
 */
 
 const LATEST_VERSION = 4
diff --git a/src/goit/goit.go b/src/goit/goit.go
index 9144153..29c478d 100644
--- a/src/goit/goit.go
+++ b/src/goit/goit.go
@@ -160,6 +160,7 @@ func Backup() error {
 	data := struct {
 		Users []User `json:"users"`
 		Repos []Repo `json:"repos"`
+		Keys  []Key  `json:"keys"`
 	}{}
 
 	bdir := filepath.Join(Conf.DataPath, "backup")
@@ -178,8 +179,8 @@ func Backup() error {
 	}
 	defer tx.Rollback()
 
-	/* Dump users */
-	rows, err := tx.Query("SELECT id, name, name_full, pass, pass_algo, salt, is_admin FROM users")
+	/* Dump users. */
+	rows, err := tx.Query("SELECT id, name, name_full, pass, pass_algo, salt, is_admin, default_visibility FROM users")
 	if err != nil {
 		return err
 	}
@@ -187,14 +188,16 @@ func Backup() error {
 
 	for rows.Next() {
 		u := User{}
-		if err := rows.Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin); err != nil {
+		if err := rows.Scan(
+			&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin, &u.DefaultVisibility,
+		); err != nil {
 			return err
 		}
 
 		data.Users = append(data.Users, u)
 	}
 
-	/* Dump repositories */
+	/* Dump repositories. */
 	rows, err = tx.Query(
 		"SELECT id, owner_id, name, description, default_branch, upstream, visibility, is_mirror FROM repos",
 	)
@@ -214,7 +217,23 @@ func Backup() error {
 		data.Repos = append(data.Repos, r)
 	}
 
-	/* Open an output ZIP file */
+	/* Dump keys. */
+	rows, err = tx.Query("SELECT id, owner_id, type, description, key FROM keys")
+	if err != nil {
+		return err
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		k := Key{}
+		if err := rows.Scan(&k.ID, &k.OwnerID, &k.Type, &k.Description, &k.Key); err != nil {
+			return err
+		}
+
+		data.Keys = append(data.Keys, k)
+	}
+
+	/* Open an output ZIP file. */
 	ts := "goit_" + time.Now().UTC().Format("20060102T150405Z")
 
 	log.Println("Backing up to", filepath.Join(bdir, ts+".zip"))
@@ -227,7 +246,7 @@ func Backup() error {
 	zw := zip.NewWriter(zf)
 	defer zw.Close()
 
-	/* Copy repositories to ZIP */
+	/* Copy repositories to ZIP. */
 	tempdir, err := os.MkdirTemp(os.TempDir(), "goit-")
 	if err != nil {
 		return err
@@ -259,7 +278,7 @@ func Backup() error {
 			return fmt.Errorf("%s %w", cd, err)
 		}
 
-		/* Walk duplicated repository and add it to the ZIP */
+		/* Walk duplicated repository and add it to the ZIP. */
 		if err = filepath.WalkDir(cd, func(path string, d fs.DirEntry, err error) error {
 			if err != nil {
 				return err
@@ -308,7 +327,7 @@ func Backup() error {
 		log.Println("Backed up", r.Name, "in", time.Since(t0))
 	}
 
-	/* Write database as JSON to ZIP */
+	/* Write database as JSON to ZIP. */
 	if b, err := json.MarshalIndent(data, "", "\t"); err != nil {
 		return err
 	} else if w, err := zw.Create(filepath.Join(ts, "goit.json")); err != nil {
diff --git a/src/goit/user.go b/src/goit/user.go
index 6930580..79d49d1 100644
--- a/src/goit/user.go
+++ b/src/goit/user.go
@@ -12,13 +12,14 @@ import (
 )
 
 type User struct {
-	Id       int64  `json:"id"`
-	Name     string `json:"name"`
-	FullName string `json:"name_full"`
-	Pass     []byte `json:"pass"`
-	PassAlgo string `json:"pass_algo"`
-	Salt     []byte `json:"salt"`
-	IsAdmin  bool   `json:"is_admin"`
+	Id                int64      `json:"id"`
+	Name              string     `json:"name"`
+	FullName          string     `json:"name_full"`
+	Pass              []byte     `json:"pass"`
+	PassAlgo          string     `json:"pass_algo"`
+	Salt              []byte     `json:"salt"`
+	IsAdmin           bool       `json:"is_admin"`
+	DefaultVisibility Visibility `json:"default_visibility"`
 }
 
 func HandleUserLogout(w http.ResponseWriter, r *http.Request) {
@@ -31,7 +32,7 @@ func HandleUserLogout(w http.ResponseWriter, r *http.Request) {
 func GetUsers() ([]User, error) {
 	users := []User{}
 
-	rows, err := db.Query("SELECT id, name, name_full, pass, pass_algo, salt, is_admin FROM users")
+	rows, err := db.Query("SELECT id, name, name_full, pass, pass_algo, salt, is_admin, default_visibility FROM users")
 	if err != nil {
 		return nil, err
 	}
@@ -40,7 +41,9 @@ func GetUsers() ([]User, error) {
 
 	for rows.Next() {
 		u := User{}
-		if err := rows.Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin); err != nil {
+		if err := rows.Scan(
+			&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin, &u.DefaultVisibility,
+		); err != nil {
 			return nil, err
 		}
 
@@ -58,8 +61,8 @@ func GetUser(id int64) (*User, error) {
 	u := User{}
 
 	if err := db.QueryRow(
-		"SELECT id, name, name_full, pass, pass_algo, salt, is_admin FROM users WHERE id = ?", id,
-	).Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin); err != nil {
+		"SELECT id, name, name_full, pass, pass_algo, salt, is_admin, default_visibility FROM users WHERE id = ?", id,
+	).Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin, &u.DefaultVisibility); err != nil {
 		if !errors.Is(err, sql.ErrNoRows) {
 			return nil, fmt.Errorf("[SELECT:user] %w", err)
 		} else {
@@ -74,8 +77,9 @@ func GetUserByName(name string) (*User, error) {
 	u := &User{}
 
 	err := db.QueryRow(
-		"SELECT id, name, name_full, pass, pass_algo, salt, is_admin FROM users WHERE name = ?", strings.ToLower(name),
-	).Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin)
+		"SELECT id, name, name_full, pass, pass_algo, salt, is_admin, default_visibility FROM users WHERE name = ?",
+		strings.ToLower(name),
+	).Scan(&u.Id, &u.Name, &u.FullName, &u.Pass, &u.PassAlgo, &u.Salt, &u.IsAdmin, &u.DefaultVisibility)
 	if errors.Is(err, sql.ErrNoRows) {
 		return nil, nil
 	} else if err != nil {
@@ -99,8 +103,9 @@ func UserExists(name string) (bool, error) {
 
 func CreateUser(user User) error {
 	if _, err := db.Exec(
-		"INSERT INTO users (name, name_full, pass, pass_algo, salt, is_admin) VALUES (?, ?, ?, ?, ?, ?)",
-		user.Name, user.FullName, user.Pass, user.PassAlgo, user.Salt, user.IsAdmin,
+		`INSERT INTO users (name, name_full, pass, pass_algo, salt, is_admin, default_visibility)
+			VALUES (?, ?, ?, ?, ?, ?, ?)`,
+		user.Name, user.FullName, user.Pass, user.PassAlgo, user.Salt, user.IsAdmin, user.DefaultVisibility,
 	); err != nil {
 		return err
 	}
@@ -110,8 +115,8 @@ func CreateUser(user User) error {
 
 func UpdateUser(uid int64, user User) error {
 	if _, err := db.Exec(
-		"UPDATE users SET name = ?, name_full = ?, is_admin = ? WHERE id = ?",
-		user.Name, user.FullName, user.IsAdmin, uid,
+		"UPDATE users SET name = ?, name_full = ?, is_admin = ?, default_visibility = ? WHERE id = ?",
+		user.Name, user.FullName, user.IsAdmin, user.DefaultVisibility, uid,
 	); err != nil {
 		return err
 	}
diff --git a/src/main.go b/src/main.go
index e47d18d..468c8f4 100644
--- a/src/main.go
+++ b/src/main.go
@@ -35,7 +35,7 @@ func main() {
 
 	if backup {
 		if err := goit.Backup(); err != nil {
-			log.Fatalln(err.Error())
+			util.PrintFuncError(err)
 		}
 
 		os.Exit(0)
diff --git a/src/util/log.go b/src/util/log.go
index fa149fe..047f40f 100644
--- a/src/util/log.go
+++ b/src/util/log.go
@@ -11,14 +11,14 @@ import (
 var Debug = false
 
 func PrintFuncError(err error) {
-	pc, _, _, ok := runtime.Caller(1)
+	pc, _, ln, ok := runtime.Caller(1)
 	if !ok {
 		log.Println(err)
 		return
 	}
 
 	fn := runtime.FuncForPC(pc)
-	log.Printf("[%s] %s\n", fn.Name(), err.Error())
+	log.Printf("[%s:%d] %s\n", fn.Name(), ln, err.Error())
 }
 
 func Debugln(v ...any) {