1package state
2
3import (
4 "context"
5 "fmt"
6 "log"
7 "net/http"
8 "time"
9
10 "github.com/gorilla/sessions"
11 "github.com/sotangled/tangled/appview"
12 "github.com/sotangled/tangled/appview/auth"
13)
14
15func (s *State) StartTokenRefresher(
16 ctx context.Context,
17 refreshInterval time.Duration,
18 r *http.Request,
19 w http.ResponseWriter,
20 atSessionish auth.Sessionish,
21 pdsEndpoint string,
22) {
23 go func() {
24 ticker := time.NewTicker(refreshInterval)
25 defer ticker.Stop()
26
27 for {
28 select {
29 case <-ticker.C:
30 err := s.auth.RefreshSession(ctx, r, w, atSessionish, pdsEndpoint)
31 if err != nil {
32 log.Printf("token refresh failed: %v", err)
33 } else {
34 log.Println("token refreshed successfully")
35 }
36 case <-ctx.Done():
37 log.Println("stopping token refresher")
38 return
39 }
40 }
41 }()
42}
43
44// RestoreSessionIfNeeded checks if a session exists in the request and starts a
45// token refresher if it doesn't have one running already.
46func (s *State) RestoreSessionIfNeeded(r *http.Request, w http.ResponseWriter) error {
47 var session *sessions.Session
48 var err error
49 session, err = s.auth.GetSession(r)
50 if err != nil {
51 fmt.Errorf("error getting session: %w", err)
52 }
53
54 did, ok := session.Values[appview.SessionDid].(string)
55 if !ok {
56 return fmt.Errorf("session did not contain a did")
57 }
58 sessionish := auth.ClientSessionish{Session: *session}
59 pdsEndpoint := session.Values[appview.SessionPds].(string)
60
61 // If no refresher is running for this session, start one
62 if _, exists := s.sessionCancelFuncs[did]; !exists {
63 sessionCtx, cancel := context.WithCancel(context.Background())
64 s.sessionCancelFuncs[did] = cancel
65
66 s.StartTokenRefresher(sessionCtx, auth.ExpiryDuration, r, w, &sessionish, pdsEndpoint)
67
68 log.Printf("restored session refresher for %s", did)
69 }
70
71 return nil
72}