feat(backend): create default admin user with initial admin keys

Ayman Bagabas created

Change summary

server/backend/sqlite/db.go | 42 +++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)

Detailed changes

server/backend/sqlite/db.go 🔗

@@ -44,6 +44,48 @@ func (d *SqliteBackend) init() error {
 			return err
 		}
 
+		var init bool
+		if err := tx.Get(&init, "SELECT value FROM settings WHERE key = 'init'"); err != nil && !errors.Is(err, sql.ErrNoRows) {
+			return err
+		}
+
+		// Create default user.
+		if !init {
+			r, err := tx.Exec("INSERT OR IGNORE INTO user (username, admin, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP);", "admin", true)
+			if err != nil {
+				return err
+			}
+			userID, err := r.LastInsertId()
+			if err != nil {
+				return err
+			}
+
+			// Add initial keys
+			for _, k := range d.cfg.InitialAdminKeys {
+				pk, _, err := backend.ParseAuthorizedKey(k)
+				if err != nil {
+					logger.Error("error parsing initial admin key, skipping", "key", k, "err", err)
+					continue
+				}
+
+				stmt, err := tx.Prepare(`INSERT INTO public_key (user_id, public_key, updated_at)
+					VALUES (?, ?, CURRENT_TIMESTAMP);`)
+				if err != nil {
+					return err
+				}
+
+				defer stmt.Close() // nolint: errcheck
+				if _, err := stmt.Exec(userID, backend.MarshalAuthorizedKey(pk)); err != nil {
+					return err
+				}
+			}
+		}
+
+		// set init flag
+		if _, err := tx.Exec("INSERT OR IGNORE INTO settings (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)", "init", true); err != nil {
+			return err
+		}
+
 		return nil
 	})
 }