1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package sshserver
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/bluesky-social/indigo/atproto/syntax"
"github.com/johnandersen777/socialweb-computer-kcp/internal/atproto/pdsclient"
"github.com/johnandersen777/socialweb-computer-kcp/internal/atprotorepo/remote"
"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/lease"
"github.com/johnandersen777/socialweb-computer-kcp/internal/ssh/ownersession"
)
func (s *Service) openOwner(did string, session ownersession.Session) (ownersession.Repo, error) {
owner, err := syntax.ParseDID(did)
if err != nil {
return nil, fmt.Errorf("sshserver: the owner DID: %w", err)
}
client := s.httpClient(requestTimeout)
tokens := &ownerTokens{did: owner, session: session, client: client}
tokens.access = lease.New(tokens.login)
pds, err := pdsclient.NewRemote(pdsclient.RemoteConfig{
BaseURL: session.Service,
DID: owner,
HTTPClient: client,
Tokens: tokens,
Timeout: requestTimeout,
})
if err != nil {
return nil, fmt.Errorf("sshserver: the owner PDS %s: %w", session.Service, err)
}
return remote.Wrap(pds, owner), nil
}
type ownerTokens struct {
did syntax.DID
session ownersession.Session
client *http.Client
access *lease.Source[string]
}
func (t *ownerTokens) AccessToken(ctx context.Context) (string, error) {
return t.access.Get(ctx)
}
func (t *ownerTokens) RefreshAccessToken(ctx context.Context) (string, error) {
t.access.Invalidate()
return t.access.Get(ctx)
}
func (t *ownerTokens) login(ctx context.Context) (string, time.Time, error) {
pds, err := pdsclient.NewRemote(pdsclient.RemoteConfig{
BaseURL: t.session.Service,
DID: t.did,
HTTPClient: t.client,
Timeout: requestTimeout,
})
if err != nil {
return "", time.Time{}, fmt.Errorf("sshserver: the owner PDS %s: %w", t.session.Service, err)
}
session, err := pds.CreateSession(ctx, t.session.Identifier, t.session.Password)
if err != nil {
return "", time.Time{}, fmt.Errorf("sshserver: the owner session of %s: %w", t.did, err)
}
expires, ok := pdsclient.TokenExpiry(session.AccessJWT)
if !ok {
return session.AccessJWT, time.Now(), nil
}
return session.AccessJWT, expires.Add(-pdsclient.TokenExpirySkew), nil
}
func ownerSessionPDS(sessions map[string]ownersession.Session) map[string]string {
if len(sessions) == 0 {
return nil
}
out := make(map[string]string, len(sessions))
for did, session := range sessions {
out[did] = strings.TrimRight(strings.TrimSpace(session.Service), "/")
}
return out
}