A vibe coded tangled fork which supports pijul.
at 18cb4a37ddc239a63f0bdbb2ca0ad26dc7a5c6c4 154 lines 3.4 kB view raw
1package oauth 2 3import ( 4 "encoding/json" 5 "errors" 6 "net/http" 7 "time" 8) 9 10const MaxAccounts = 20 11 12var ErrMaxAccountsReached = errors.New("maximum number of linked accounts reached") 13 14type AccountInfo struct { 15 Did string `json:"did"` 16 SessionId string `json:"session_id"` 17 AddedAt int64 `json:"added_at"` 18} 19 20type AccountRegistry struct { 21 Accounts []AccountInfo `json:"accounts"` 22} 23 24type MultiAccountUser struct { 25 Did string 26 Accounts []AccountInfo 27} 28 29func (o *OAuth) GetAccounts(r *http.Request) *AccountRegistry { 30 session, err := o.SessStore.Get(r, AccountsName) 31 if err != nil || session.IsNew { 32 return &AccountRegistry{Accounts: []AccountInfo{}} 33 } 34 35 data, ok := session.Values["accounts"].(string) 36 if !ok { 37 return &AccountRegistry{Accounts: []AccountInfo{}} 38 } 39 40 var registry AccountRegistry 41 if err := json.Unmarshal([]byte(data), &registry); err != nil { 42 return &AccountRegistry{Accounts: []AccountInfo{}} 43 } 44 45 return &registry 46} 47 48func (o *OAuth) saveAccounts(w http.ResponseWriter, r *http.Request, registry *AccountRegistry) error { 49 session, err := o.SessStore.Get(r, AccountsName) 50 if err != nil { 51 return err 52 } 53 54 data, err := json.Marshal(registry) 55 if err != nil { 56 return err 57 } 58 59 session.Values["accounts"] = string(data) 60 session.Options.MaxAge = 60 * 60 * 24 * 365 61 session.Options.HttpOnly = true 62 session.Options.Secure = !o.Config.Core.Dev 63 session.Options.SameSite = http.SameSiteLaxMode 64 65 return session.Save(r, w) 66} 67 68func (r *AccountRegistry) AddAccount(did, handle, sessionId string) error { 69 for i, acc := range r.Accounts { 70 if acc.Did == did { 71 r.Accounts[i].SessionId = sessionId 72 return nil 73 } 74 } 75 76 if len(r.Accounts) >= MaxAccounts { 77 return ErrMaxAccountsReached 78 } 79 80 r.Accounts = append(r.Accounts, AccountInfo{ 81 Did: did, 82 SessionId: sessionId, 83 AddedAt: time.Now().Unix(), 84 }) 85 return nil 86} 87 88func (r *AccountRegistry) RemoveAccount(did string) { 89 filtered := make([]AccountInfo, 0, len(r.Accounts)) 90 for _, acc := range r.Accounts { 91 if acc.Did != did { 92 filtered = append(filtered, acc) 93 } 94 } 95 r.Accounts = filtered 96} 97 98func (r *AccountRegistry) FindAccount(did string) *AccountInfo { 99 for i := range r.Accounts { 100 if r.Accounts[i].Did == did { 101 return &r.Accounts[i] 102 } 103 } 104 return nil 105} 106 107func (o *OAuth) GetMultiAccountUser(r *http.Request) *MultiAccountUser { 108 sess, err := o.ResumeSession(r) 109 if err != nil { 110 return nil 111 } 112 113 registry := o.GetAccounts(r) 114 return &MultiAccountUser{ 115 Did: sess.Data.AccountDID.String(), 116 Accounts: registry.Accounts, 117 } 118} 119 120func (o *OAuth) SetAuthReturn(w http.ResponseWriter, r *http.Request, returnURL string) error { 121 session, err := o.SessStore.Get(r, AuthReturnName) 122 if err != nil { 123 return err 124 } 125 126 session.Values[AuthReturnURL] = returnURL 127 session.Options.MaxAge = 60 * 30 128 session.Options.HttpOnly = true 129 session.Options.Secure = !o.Config.Core.Dev 130 session.Options.SameSite = http.SameSiteLaxMode 131 132 return session.Save(r, w) 133} 134 135func (o *OAuth) GetAuthReturn(r *http.Request) string { 136 session, err := o.SessStore.Get(r, AuthReturnName) 137 if err != nil || session.IsNew { 138 return "" 139 } 140 141 returnURL, _ := session.Values[AuthReturnURL].(string) 142 143 return returnURL 144} 145 146func (o *OAuth) ClearAuthReturn(w http.ResponseWriter, r *http.Request) error { 147 session, err := o.SessStore.Get(r, AuthReturnName) 148 if err != nil { 149 return err 150 } 151 152 session.Options.MaxAge = -1 153 return session.Save(r, w) 154}