- commit
- 74f0af0
- parent
- 6cec7bd
- author
- Eric Bower
- date
- 2024-03-13 03:29:02 +0000 UTC
feat(pgs): impersonate any user
1 files changed,
+23,
-2
+23,
-2
1@@ -3,6 +3,7 @@ package pgs
2 import (
3 "encoding/json"
4 "net/http"
5+ "strings"
6
7 "github.com/charmbracelet/ssh"
8 "github.com/picosh/pico/db"
9@@ -16,13 +17,23 @@ func allowPerm(proj *db.Project) bool {
10
11 type CtxHttpBridge = func(ssh.Context) http.Handler
12
13+func getInfoFromUser(user string) (string, string) {
14+ if strings.Contains(user, "__") {
15+ results := strings.SplitN(user, "__", 1)
16+ return results[0], results[1]
17+ }
18+
19+ return "", user
20+}
21+
22 func createHttpHandler(httpCtx *shared.HttpCtx) CtxHttpBridge {
23 return func(ctx ssh.Context) http.Handler {
24- subdomain := ctx.User()
25 dbh := httpCtx.Dbpool
26 logger := httpCtx.Cfg.Logger
27+ asUser, subdomain := getInfoFromUser(ctx.User())
28 log := logger.With(
29 "subdomain", subdomain,
30+ "impersonating", asUser,
31 )
32
33 pubkey, err := shared.GetPublicKeyCtx(ctx)
34@@ -62,11 +73,21 @@ func createHttpHandler(httpCtx *shared.HttpCtx) CtxHttpBridge {
35
36 requester, _ := dbh.FindUserForKey("", pubkeyStr)
37 if requester != nil {
38- log = logger.With(
39+ log = log.With(
40 "requester", requester.Name,
41 )
42 }
43
44+ // impersonation logic
45+ if asUser != "" {
46+ isAdmin := dbh.HasFeatureForUser(requester.ID, "admin")
47+ if !isAdmin {
48+ log.Error("impersonation attempt failed")
49+ return http.HandlerFunc(shared.UnauthorizedHandler)
50+ }
51+ requester, _ = dbh.FindUserForName(asUser)
52+ }
53+
54 if !HasProjectAccess(project, owner, requester, pubkey) {
55 log.Error("no access")
56 return http.HandlerFunc(shared.UnauthorizedHandler)