this repo has no description
1package state 2 3import ( 4 "log" 5 "net/http" 6 "strings" 7 "time" 8 9 comatproto "github.com/bluesky-social/indigo/api/atproto" 10 "github.com/bluesky-social/indigo/xrpc" 11 "github.com/go-chi/chi/v5" 12 "github.com/sotangled/tangled/appview" 13 "github.com/sotangled/tangled/appview/auth" 14) 15 16type Middleware func(http.Handler) http.Handler 17 18func AuthMiddleware(s *State) Middleware { 19 return func(next http.Handler) http.Handler { 20 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 session, _ := s.auth.Store.Get(r, appview.SessionName) 22 authorized, ok := session.Values[appview.SessionAuthenticated].(bool) 23 if !ok || !authorized { 24 log.Printf("not logged in, redirecting") 25 http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) 26 return 27 } 28 29 // refresh if nearing expiry 30 // TODO: dedup with /login 31 expiryStr := session.Values[appview.SessionExpiry].(string) 32 expiry, err := time.Parse(time.RFC3339, expiryStr) 33 if err != nil { 34 log.Println("invalid expiry time", err) 35 return 36 } 37 pdsUrl := session.Values[appview.SessionPds].(string) 38 did := session.Values[appview.SessionDid].(string) 39 refreshJwt := session.Values[appview.SessionRefreshJwt].(string) 40 41 if time.Now().After(expiry) { 42 log.Println("token expired, refreshing ...") 43 44 client := xrpc.Client{ 45 Host: pdsUrl, 46 Auth: &xrpc.AuthInfo{ 47 Did: did, 48 AccessJwt: refreshJwt, 49 RefreshJwt: refreshJwt, 50 }, 51 } 52 atSession, err := comatproto.ServerRefreshSession(r.Context(), &client) 53 if err != nil { 54 log.Println(err) 55 return 56 } 57 58 sessionish := auth.RefreshSessionWrapper{atSession} 59 60 err = s.auth.StoreSession(r, w, &sessionish, pdsUrl) 61 if err != nil { 62 log.Printf("failed to store session for did: %s\n: %s", atSession.Did, err) 63 return 64 } 65 66 log.Println("successfully refreshed token") 67 } 68 69 next.ServeHTTP(w, r) 70 }) 71 } 72} 73 74func RoleMiddleware(s *State, group string) Middleware { 75 return func(next http.Handler) http.Handler { 76 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 77 // requires auth also 78 actor := s.auth.GetUser(r) 79 if actor == nil { 80 // we need a logged in user 81 log.Printf("not logged in, redirecting") 82 http.Error(w, "Forbiden", http.StatusUnauthorized) 83 return 84 } 85 domain := chi.URLParam(r, "domain") 86 if domain == "" { 87 http.Error(w, "malformed url", http.StatusBadRequest) 88 return 89 } 90 91 ok, err := s.enforcer.E.HasGroupingPolicy(actor.Did, group, domain) 92 if err != nil || !ok { 93 // we need a logged in user 94 log.Printf("%s does not have perms of a %s in domain %s", actor.Did, group, domain) 95 http.Error(w, "Forbiden", http.StatusUnauthorized) 96 return 97 } 98 99 next.ServeHTTP(w, r) 100 }) 101 } 102} 103 104func StripLeadingAt(next http.Handler) http.Handler { 105 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 106 path := req.URL.Path 107 if strings.HasPrefix(path, "/@") { 108 req.URL.Path = "/" + strings.TrimPrefix(path, "/@") 109 } 110 next.ServeHTTP(w, req) 111 }) 112}