repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
eb429da
parent
34f80a7
author
Eric Bower
date
2024-03-24 13:14:49 +0000 UTC
chore(ui): authorization checks
3 files changed,  +108, -5
M db/db.go
+1, -0
1@@ -281,6 +281,7 @@ type DB interface {
2 	RegisterUser(name, pubkey string) (*User, error)
3 	RemoveUsers(userIDs []string) error
4 	LinkUserKey(userID string, pubkey string, tx *sql.Tx) error
5+	UpdatePublicKey(pubkey, name string) (*PublicKey, error)
6 	InsertPublicKey(userID, pubkey, name string, tx *sql.Tx) (*PublicKey, error)
7 	FindPublicKeyForKey(pubkey string) (*PublicKey, error)
8 	FindKeysForUser(user *User) ([]*PublicKey, error)
M db/postgres/storage.go
+19, -1
 1@@ -442,6 +442,25 @@ func (me *PsqlDB) InsertPublicKey(userID, key, name string, tx *sql.Tx) (*db.Pub
 2 	return pk, nil
 3 }
 4 
 5+func (me *PsqlDB) UpdatePublicKey(key, name string) (*db.PublicKey, error) {
 6+	pk, err := me.FindPublicKeyForKey(key)
 7+	if err != nil {
 8+		return nil, err
 9+	}
10+
11+	query := `UPDATE public_keys SET name=$1 WHERE id=$2;`
12+	_, err = me.Db.Exec(query, name, pk.ID)
13+	if err != nil {
14+		return nil, err
15+	}
16+
17+	pk, err = me.FindPublicKeyForKey(key)
18+	if err != nil {
19+		return nil, err
20+	}
21+	return pk, nil
22+}
23+
24 func (me *PsqlDB) FindPublicKeyForKey(key string) (*db.PublicKey, error) {
25 	var keys []*db.PublicKey
26 	rs, err := me.Db.Query(sqlSelectPublicKey, key)
27@@ -1647,7 +1666,6 @@ func (me *PsqlDB) AddPicoPlusUser(username, paymentType, txId string) error {
28 			data,
29 		)
30 		if err != nil {
31-			fmt.Println(err)
32 			return err
33 		}
34 	}
M ui/api.go
+88, -4
  1@@ -186,10 +186,31 @@ func deletePubkey(httpCtx *shared.ApiConfig, ctx ssh.Context) http.HandlerFunc {
  2 		if !ensureUser(w, user) {
  3 			return
  4 		}
  5+		dbpool := shared.GetDB(r)
  6 		pubkeyID := shared.GetField(r, 0)
  7 
  8-		dbpool := shared.GetDB(r)
  9-		err := dbpool.RemoveKeys([]string{pubkeyID})
 10+		ownedKeys, err := dbpool.FindKeysForUser(user)
 11+		if err != nil {
 12+			logger.Error("could not query for pubkeys", "err", err.Error())
 13+			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
 14+			return
 15+		}
 16+
 17+		found := false
 18+		for _, key := range ownedKeys {
 19+			if key.ID == pubkeyID {
 20+				found = true
 21+				break
 22+			}
 23+		}
 24+
 25+		if !found {
 26+			logger.Error("user trying to delete key they do not own")
 27+			shared.JSONError(w, "user trying to delete key they do not own", http.StatusUnauthorized)
 28+			return
 29+		}
 30+
 31+		err = dbpool.RemoveKeys([]string{pubkeyID})
 32 		if err != nil {
 33 			logger.Error("could not remove pubkey", "err", err.Error())
 34 			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
 35@@ -199,6 +220,47 @@ func deletePubkey(httpCtx *shared.ApiConfig, ctx ssh.Context) http.HandlerFunc {
 36 	}
 37 }
 38 
 39+func patchPubkey(httpCtx *shared.ApiConfig, ctx ssh.Context) http.HandlerFunc {
 40+	logger := httpCtx.Cfg.Logger
 41+	return func(w http.ResponseWriter, r *http.Request) {
 42+		w.Header().Set("Content-Type", "application/json")
 43+		user, _ := shared.GetUserCtx(ctx)
 44+		if !ensureUser(w, user) {
 45+			return
 46+		}
 47+
 48+		dbpool := shared.GetDB(r)
 49+		var payload createPubkeyPayload
 50+		body, _ := io.ReadAll(r.Body)
 51+		_ = json.Unmarshal(body, &payload)
 52+
 53+		auth, err := dbpool.FindUserForKey("", payload.Pubkey)
 54+		if err != nil {
 55+			logger.Error("could not find user with pubkey provided", "err", err.Error())
 56+			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
 57+			return
 58+		}
 59+
 60+		if auth.ID != user.ID {
 61+			logger.Error("user trying to update pubkey they do not own")
 62+			shared.JSONError(w, "user trying to update pubkey they do not own", http.StatusUnauthorized)
 63+			return
 64+		}
 65+
 66+		pubkey, err := dbpool.UpdatePublicKey(payload.Pubkey, payload.Name)
 67+		if err != nil {
 68+			logger.Error("could not update pubkey", "err", err.Error())
 69+			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
 70+			return
 71+		}
 72+
 73+		err = json.NewEncoder(w).Encode(pubkey)
 74+		if err != nil {
 75+			logger.Error("json encode", "err", err.Error())
 76+		}
 77+	}
 78+}
 79+
 80 type tokensPayload struct {
 81 	Tokens []*db.Token `json:"tokens"`
 82 }
 83@@ -287,10 +349,31 @@ func deleteToken(httpCtx *shared.ApiConfig, ctx ssh.Context) http.HandlerFunc {
 84 		if !ensureUser(w, user) {
 85 			return
 86 		}
 87+		dbpool := shared.GetDB(r)
 88 		tokenID := shared.GetField(r, 0)
 89 
 90-		dbpool := shared.GetDB(r)
 91-		err := dbpool.RemoveToken(tokenID)
 92+		toks, err := dbpool.FindTokensForUser(user.ID)
 93+		if err != nil {
 94+			logger.Error("could not query for user tokens", "err", err.Error())
 95+			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
 96+			return
 97+		}
 98+
 99+		found := false
100+		for _, tok := range toks {
101+			if tok.ID == tokenID {
102+				found = true
103+				break
104+			}
105+		}
106+
107+		if !found {
108+			logger.Error("user trying to delete token they do not own")
109+			shared.JSONError(w, "user trying to delete token they do not own", http.StatusUnauthorized)
110+			return
111+		}
112+
113+		err = dbpool.RemoveToken(tokenID)
114 		if err != nil {
115 			logger.Error("could not remove token", "err", err.Error())
116 			shared.JSONError(w, err.Error(), http.StatusUnprocessableEntity)
117@@ -436,6 +519,7 @@ func CreateRoutes(apiConfig *shared.ApiConfig, ctx ssh.Context) []shared.Route {
118 		shared.NewCorsRoute("GET", "/api/pubkeys", getPublicKeys(apiConfig, ctx)),
119 		shared.NewCorsRoute("POST", "/api/pubkeys", createPubkey(apiConfig, ctx)),
120 		shared.NewCorsRoute("DELETE", "/api/pubkeys/(.+)", deletePubkey(apiConfig, ctx)),
121+		shared.NewCorsRoute("PATCH", "/api/pubkeys", patchPubkey(apiConfig, ctx)),
122 		shared.NewCorsRoute("GET", "/api/tokens", getTokens(apiConfig, ctx)),
123 		shared.NewCorsRoute("POST", "/api/tokens", createToken(apiConfig, ctx)),
124 		shared.NewCorsRoute("DELETE", "/api/tokens/(.+)", deleteToken(apiConfig, ctx)),