- 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)
+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 }
+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)),