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