forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
this repo has no description
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package auth
2
3import (
4 "context"
5 "fmt"
6 "net/http"
7 "time"
8
9 comatproto "github.com/bluesky-social/indigo/api/atproto"
10 "github.com/bluesky-social/indigo/atproto/identity"
11 "github.com/bluesky-social/indigo/xrpc"
12 "github.com/gorilla/sessions"
13 "tangled.sh/tangled.sh/core/appview"
14)
15
16type Auth struct {
17 Store *sessions.CookieStore
18}
19
20type AtSessionCreate struct {
21 comatproto.ServerCreateSession_Output
22 PDSEndpoint string
23}
24
25type AtSessionRefresh struct {
26 comatproto.ServerRefreshSession_Output
27 PDSEndpoint string
28}
29
30func Make(secret string) (*Auth, error) {
31 store := sessions.NewCookieStore([]byte(secret))
32 return &Auth{store}, nil
33}
34
35func (a *Auth) CreateInitialSession(ctx context.Context, resolved *identity.Identity, appPassword string) (*comatproto.ServerCreateSession_Output, error) {
36
37 pdsUrl := resolved.PDSEndpoint()
38 client := xrpc.Client{
39 Host: pdsUrl,
40 }
41
42 atSession, err := comatproto.ServerCreateSession(ctx, &client, &comatproto.ServerCreateSession_Input{
43 Identifier: resolved.DID.String(),
44 Password: appPassword,
45 })
46 if err != nil {
47 return nil, fmt.Errorf("invalid app password")
48 }
49
50 return atSession, nil
51}
52
53// Sessionish is an interface that provides access to the common fields of both types.
54type Sessionish interface {
55 GetAccessJwt() string
56 GetActive() *bool
57 GetDid() string
58 GetDidDoc() *interface{}
59 GetHandle() string
60 GetRefreshJwt() string
61 GetStatus() *string
62}
63
64// Create a wrapper type for ServerRefreshSession_Output
65type RefreshSessionWrapper struct {
66 *comatproto.ServerRefreshSession_Output
67}
68
69func (s *RefreshSessionWrapper) GetAccessJwt() string {
70 return s.AccessJwt
71}
72
73func (s *RefreshSessionWrapper) GetActive() *bool {
74 return s.Active
75}
76
77func (s *RefreshSessionWrapper) GetDid() string {
78 return s.Did
79}
80
81func (s *RefreshSessionWrapper) GetDidDoc() *interface{} {
82 return s.DidDoc
83}
84
85func (s *RefreshSessionWrapper) GetHandle() string {
86 return s.Handle
87}
88
89func (s *RefreshSessionWrapper) GetRefreshJwt() string {
90 return s.RefreshJwt
91}
92
93func (s *RefreshSessionWrapper) GetStatus() *string {
94 return s.Status
95}
96
97// Create a wrapper type for ServerRefreshSession_Output
98type CreateSessionWrapper struct {
99 *comatproto.ServerCreateSession_Output
100}
101
102func (s *CreateSessionWrapper) GetAccessJwt() string {
103 return s.AccessJwt
104}
105
106func (s *CreateSessionWrapper) GetActive() *bool {
107 return s.Active
108}
109
110func (s *CreateSessionWrapper) GetDid() string {
111 return s.Did
112}
113
114func (s *CreateSessionWrapper) GetDidDoc() *interface{} {
115 return s.DidDoc
116}
117
118func (s *CreateSessionWrapper) GetHandle() string {
119 return s.Handle
120}
121
122func (s *CreateSessionWrapper) GetRefreshJwt() string {
123 return s.RefreshJwt
124}
125
126func (s *CreateSessionWrapper) GetStatus() *string {
127 return s.Status
128}
129
130func (a *Auth) ClearSession(r *http.Request, w http.ResponseWriter) error {
131 clientSession, err := a.Store.Get(r, appview.SessionName)
132 if err != nil {
133 return fmt.Errorf("invalid session", err)
134 }
135 if clientSession.IsNew {
136 return fmt.Errorf("invalid session")
137 }
138 clientSession.Options.MaxAge = -1
139 return clientSession.Save(r, w)
140}
141
142func (a *Auth) StoreSession(r *http.Request, w http.ResponseWriter, atSessionish Sessionish, pdsEndpoint string) error {
143 clientSession, _ := a.Store.Get(r, appview.SessionName)
144 clientSession.Values[appview.SessionHandle] = atSessionish.GetHandle()
145 clientSession.Values[appview.SessionDid] = atSessionish.GetDid()
146 clientSession.Values[appview.SessionPds] = pdsEndpoint
147 clientSession.Values[appview.SessionAccessJwt] = atSessionish.GetAccessJwt()
148 clientSession.Values[appview.SessionRefreshJwt] = atSessionish.GetRefreshJwt()
149 clientSession.Values[appview.SessionExpiry] = time.Now().Add(time.Minute * 15).Format(time.RFC3339)
150 clientSession.Values[appview.SessionAuthenticated] = true
151 return clientSession.Save(r, w)
152}
153
154func (a *Auth) AuthorizedClient(r *http.Request) (*xrpc.Client, error) {
155 clientSession, err := a.Store.Get(r, "appview-session")
156 if err != nil || clientSession.IsNew {
157 return nil, err
158 }
159
160 did := clientSession.Values["did"].(string)
161 pdsUrl := clientSession.Values["pds"].(string)
162 accessJwt := clientSession.Values["accessJwt"].(string)
163 refreshJwt := clientSession.Values["refreshJwt"].(string)
164
165 client := &xrpc.Client{
166 Host: pdsUrl,
167 Auth: &xrpc.AuthInfo{
168 AccessJwt: accessJwt,
169 RefreshJwt: refreshJwt,
170 Did: did,
171 },
172 }
173
174 return client, nil
175}
176
177func (a *Auth) GetSession(r *http.Request) (*sessions.Session, error) {
178 return a.Store.Get(r, appview.SessionName)
179}
180
181func (a *Auth) GetDid(r *http.Request) string {
182 clientSession, err := a.Store.Get(r, appview.SessionName)
183 if err != nil || clientSession.IsNew {
184 return ""
185 }
186
187 return clientSession.Values[appview.SessionDid].(string)
188}
189
190func (a *Auth) GetHandle(r *http.Request) string {
191 clientSession, err := a.Store.Get(r, appview.SessionName)
192 if err != nil || clientSession.IsNew {
193 return ""
194 }
195
196 return clientSession.Values[appview.SessionHandle].(string)
197}
198
199type User struct {
200 Handle string
201 Did string
202 Pds string
203}
204
205func (a *Auth) GetUser(r *http.Request) *User {
206 clientSession, err := a.Store.Get(r, appview.SessionName)
207
208 if err != nil || clientSession.IsNew {
209 return nil
210 }
211
212 return &User{
213 Handle: clientSession.Values[appview.SessionHandle].(string),
214 Did: clientSession.Values[appview.SessionDid].(string),
215 Pds: clientSession.Values[appview.SessionPds].(string),
216 }
217}