- commit
- 8c838e2
- parent
- 5403c06
- author
- Eric Bower
- date
- 2025-07-13 09:20:13 -0400 EDT
feat(pgs): self hosted init cmd
5 files changed,
+70,
-15
+31,
-0
1@@ -1,11 +1,15 @@
2 package main
3
4 import (
5+ "os"
6+ "strings"
7+
8 "github.com/picosh/pico/pkg/apps/pgs"
9 pgsdb "github.com/picosh/pico/pkg/apps/pgs/db"
10 "github.com/picosh/pico/pkg/shared"
11 "github.com/picosh/pico/pkg/shared/storage"
12 "github.com/picosh/utils"
13+ "golang.org/x/crypto/ssh"
14 )
15
16 func main() {
17@@ -27,6 +31,33 @@ func main() {
18 cfg := pgs.NewPgsConfig(logger, dbpool, st, pubsub)
19 killCh := make(chan error)
20
21+ // first time user experience flow
22+ args := os.Args
23+ if len(args) > 0 {
24+ if args[1] == "init" {
25+ if len(args) < 4 {
26+ panic("must provide username and pubkey")
27+ }
28+
29+ userName := args[2]
30+ pubkeyRaw := strings.Join(args[3:], " ")
31+ key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubkeyRaw))
32+ if err != nil {
33+ logger.Error("parse pubkey", "err", err)
34+ return
35+ }
36+ pubkey := utils.KeyForKeyText(key)
37+ logger.Info("init cli", "userName", userName, "pubkey", pubkey)
38+
39+ err = dbpool.RegisterAdmin(userName, pubkey)
40+ if err != nil {
41+ panic(err)
42+ }
43+ logger.Info("Admin user created. You can now start using pgs!")
44+ return
45+ }
46+ }
47+
48 go pgs.StartApiServer(cfg)
49 pgs.StartSshServer(cfg, killCh)
50 }
+11,
-15
1@@ -67,29 +67,25 @@ func Middleware(handler *UploadAssetHandler) pssh.SSHServerMiddleware {
2 height = pty.Window.Height
3 }
4
5- user, err := getUser(sesh, dbpool)
6- if err != nil {
7- sendutils.ErrorHandler(sesh, err)
8- return err
9- }
10-
11- // renderer := bm.MakeRenderer(sesh)
12- // renderer.SetColorProfile(termenv.TrueColor)
13- // styles := common.DefaultStyles(renderer)
14-
15 opts := Cmd{
16 Session: sesh,
17- User: user,
18 Store: store,
19 Log: log,
20 Dbpool: dbpool,
21 Write: false,
22- // Styles: styles,
23- Width: width,
24- Height: height,
25- Cfg: handler.Cfg,
26+ Width: width,
27+ Height: height,
28+ Cfg: handler.Cfg,
29 }
30
31+ user, err := getUser(sesh, dbpool)
32+ if err != nil {
33+ sendutils.ErrorHandler(sesh, err)
34+ return err
35+ }
36+
37+ opts.User = user
38+
39 if len(args) == 0 {
40 opts.help()
41 return nil
+2,
-0
1@@ -22,5 +22,7 @@ type PgsDB interface {
2 FindProjectsByPrefix(userID, name string) ([]*db.Project, error)
3 FindProjects(by string) ([]*db.Project, error)
4
5+ RegisterAdmin(username string, pubkey string) error
6+
7 Close() error
8 }
+4,
-0
1@@ -187,3 +187,7 @@ func (me *MemoryDB) FindProjects(userID string) ([]*db.Project, error) {
2 func (me *MemoryDB) UpdateProjectAcl(userID, name string, acl db.ProjectAcl) error {
3 return errNotImpl
4 }
5+
6+func (me *MemoryDB) RegisterAdmin(username, pubkey string) error {
7+ return errNotImpl
8+}
+22,
-0
1@@ -240,3 +240,25 @@ func (me *PgsPsqlDB) UpdateProjectAcl(userID, name string, acl db.ProjectAcl) er
2 )
3 return err
4 }
5+
6+func (me *PgsPsqlDB) RegisterAdmin(username, pubkey string) error {
7+ var userID string
8+ row := me.Db.QueryRow("INSERT INTO app_users (name) VALUES ($1) RETURNING id", username)
9+ err := row.Scan(&userID)
10+ if err != nil {
11+ return err
12+ }
13+
14+ _, err = me.Db.Exec("INSERT INTO public_keys (user_id, name, public_key) VALUES ($1, 'main', $2)", userID, pubkey)
15+ if err != nil {
16+ return err
17+ }
18+
19+ _, err = me.Db.Exec("INSERT INTO feature_flags (user_id, name, expires_at) VALUES (1, 'plus', '2100-01-01')", userID)
20+ if err != nil {
21+ return err
22+ }
23+
24+ _, err = me.Db.Exec("INSERT INTO feature_flags (user_id, name, expires_at) VALUES (1, 'admin', '2100-01-01')", userID)
25+ return err
26+}