1package web
2
3import (
4 "errors"
5 "net/http"
6
7 "tug/internal/transport/web/text"
8)
9
10type adminPendingData struct {
11 Viewer Ident
12 ID string
13 Username Ident
14 Expires Ident
15 Spent bool
16 Message text.Key
17}
18
19func (a *admin) pendingAccount(w http.ResponseWriter, r *http.Request) (Principal, string, AdminPendingAccount, bool) {
20 p, ok := a.kit.principal(w, r)
21 if !ok {
22 return Principal{}, "", AdminPendingAccount{}, false
23 }
24 id, ok := a.id(w, r)
25 if !ok {
26 return Principal{}, "", AdminPendingAccount{}, false
27 }
28 acct, err := a.b.PendingAccount(r.Context(), id)
29 if err != nil {
30 a.failed(w, r, "pending account", err)
31 return Principal{}, "", AdminPendingAccount{}, false
32 }
33 return p, id, acct, true
34}
35
36func (a *admin) pendingPage(w http.ResponseWriter, r *http.Request, p Principal, id string, acct AdminPendingAccount, message text.Key) {
37 if acct.Spent && message == "" {
38 message = text.AdminProblemConfirmSpent
39 }
40 a.render(w, r, http.StatusOK, "admin-user-confirm", adminPendingData{Viewer: p.Username, ID: id, Username: Ident(acct.Username), Expires: Ident(stamp(acct.ExpiresAt)), Spent: acct.Spent, Message: message})
41}
42
43func (a *admin) confirmShow(w http.ResponseWriter, r *http.Request) {
44 if p, id, acct, ok := a.pendingAccount(w, r); ok {
45 a.pendingPage(w, r, p, id, acct, "")
46 }
47}
48
49func (a *admin) confirmRun(w http.ResponseWriter, r *http.Request) {
50 p, id, acct, ok := a.pendingAccount(w, r)
51 if !ok {
52 return
53 }
54 err := a.b.ConfirmAccount(r.Context(), p.UserID, id, r.PostFormValue("code"))
55 switch {
56 case errors.Is(err, ErrAdminConfirmCode):
57 fresh, err := a.b.PendingAccount(r.Context(), id)
58 if err != nil {
59 a.failed(w, r, "pending account", err)
60 return
61 }
62 if fresh.Spent {
63 a.pendingPage(w, r, p, id, fresh, text.AdminProblemConfirmSpent)
64 return
65 }
66 a.pendingPage(w, r, p, id, fresh, text.AdminProblemConfirmCode)
67 case errors.Is(err, ErrAdminConfirmSpent):
68 acct.Spent = true
69 a.pendingPage(w, r, p, id, acct, text.AdminProblemConfirmSpent)
70 case err != nil:
71 a.failed(w, r, "confirm account", err)
72 default:
73 a.done(w, r, text.FlashAdminUserConfirmed, Ident(acct.Username), "/users/"+id)
74 }
75}