forked from
willdot.net/cocoon
A fork of the Cocoon PDS but being made more distributed.
1package server
2
3import (
4 "errors"
5 "time"
6
7 "github.com/haileyok/cocoon/internal/helpers"
8 "github.com/haileyok/cocoon/oauth"
9 "github.com/haileyok/cocoon/oauth/constants"
10 "github.com/haileyok/cocoon/oauth/provider"
11 "github.com/hako/durafmt"
12 "github.com/labstack/echo/v4"
13)
14
15func (s *Server) handleAccount(e echo.Context) error {
16 ctx := e.Request().Context()
17 logger := s.logger.With("name", "handleAuth")
18
19 repo, sess, accounts, err := s.getSessionRepoAndAccountsOrErr(e)
20 if err != nil {
21 if !errors.Is(err, ErrSessionUnauthenticated) {
22 return helpers.ServerError(e, nil)
23 }
24 return e.Redirect(303, "/account/signin")
25 }
26
27 oldestPossibleSession := time.Now().Add(constants.ConfidentialClientSessionLifetime)
28
29 var tokens []provider.OauthToken
30 if err := s.db.Raw(ctx, "SELECT * FROM oauth_tokens WHERE sub = ? AND created_at < ? ORDER BY created_at ASC", nil, repo.Repo.Did, oldestPossibleSession).Scan(&tokens).Error; err != nil {
31 logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err)
32 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error")
33 sess.Save(e.Request(), e.Response())
34 return e.Render(200, "account.html", map[string]any{
35 "Repo": repo,
36 "Tokens": []map[string]string{},
37 "flashes": getFlashesFromSession(e, sess),
38 "Accounts": accounts,
39 "ActiveDid": repo.Repo.Did,
40 })
41 }
42
43 var filtered []provider.OauthToken
44 for _, t := range tokens {
45 ageRes := oauth.GetSessionAgeFromToken(t)
46 if ageRes.SessionExpired {
47 continue
48 }
49 filtered = append(filtered, t)
50 }
51
52 now := time.Now()
53
54 tokenInfo := []map[string]string{}
55 for _, t := range tokens {
56 ageRes := oauth.GetSessionAgeFromToken(t)
57 maxTime := constants.PublicClientSessionLifetime
58 if t.ClientAuth.Method != "none" {
59 maxTime = constants.ConfidentialClientSessionLifetime
60 }
61
62 var clientName string
63 metadata, err := s.oauthProvider.ClientManager.GetClient(ctx, t.ClientId)
64 if err != nil {
65 clientName = t.ClientId
66 } else {
67 clientName = metadata.Metadata.ClientName
68 }
69
70 tokenInfo = append(tokenInfo, map[string]string{
71 "ClientName": clientName,
72 "Age": durafmt.Parse(ageRes.SessionAge).LimitFirstN(2).String(),
73 "LastUpdated": durafmt.Parse(now.Sub(t.UpdatedAt)).LimitFirstN(2).String(),
74 "ExpiresIn": durafmt.Parse(now.Add(maxTime).Sub(now)).LimitFirstN(2).String(),
75 "Token": t.Token,
76 "Ip": t.Ip,
77 })
78 }
79
80 return e.Render(200, "account.html", map[string]any{
81 "Repo": repo,
82 "Tokens": tokenInfo,
83 "flashes": getFlashesFromSession(e, sess),
84 "Accounts": accounts,
85 "ActiveDid": repo.Repo.Did,
86 })
87}