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 repo, sess, err := s.getSessionRepoOrErr(e)
16 if err != nil {
17 return e.Redirect(303, "/account/signin")
18 }
19
20 oldestPossibleSession := time.Now().Add(constants.ConfidentialClientSessionLifetime)
21
22 var tokens []provider.OauthToken
23 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 {
24 s.logger.Error("couldnt fetch oauth sessions for account", "did", repo.Repo.Did, "error", err)
25 sess.AddFlash("Unable to fetch sessions. See server logs for more details.", "error")
26 sess.Save(e.Request(), e.Response())
27 return e.Render(200, "account.html", map[string]any{
28 "flashes": getFlashesFromSession(e, sess),
29 })
30 }
31
32 var filtered []provider.OauthToken
33 for _, t := range tokens {
34 ageRes := oauth.GetSessionAgeFromToken(t)
35 if ageRes.SessionExpired {
36 continue
37 }
38 filtered = append(filtered, t)
39 }
40
41 now := time.Now()
42
43 tokenInfo := []map[string]string{}
44 for _, t := range tokens {
45 ageRes := oauth.GetSessionAgeFromToken(t)
46 maxTime := constants.PublicClientSessionLifetime
47 if t.ClientAuth.Method != "none" {
48 maxTime = constants.ConfidentialClientSessionLifetime
49 }
50
51 var clientName string
52 metadata, err := s.oauthProvider.ClientManager.GetClient(ctx, t.ClientId)
53 if err != nil {
54 clientName = t.ClientId
55 } else {
56 clientName = metadata.Metadata.ClientName
57 }
58
59 tokenInfo = append(tokenInfo, map[string]string{
60 "ClientName": clientName,
61 "Age": durafmt.Parse(ageRes.SessionAge).LimitFirstN(2).String(),
62 "LastUpdated": durafmt.Parse(now.Sub(t.UpdatedAt)).LimitFirstN(2).String(),
63 "ExpiresIn": durafmt.Parse(now.Add(maxTime).Sub(now)).LimitFirstN(2).String(),
64 "Token": t.Token,
65 "Ip": t.Ip,
66 })
67 }
68
69 return e.Render(200, "account.html", map[string]any{
70 "Repo": repo,
71 "Tokens": tokenInfo,
72 "flashes": getFlashesFromSession(e, sess),
73 })
74}