💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Gemigit › files › 7f4d7fd8357339502b8b4cae08… captured on 2023-04-19 at 23:34:04. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 package gmi
1
2 import (
3 "gemigit/auth"
4 "gemigit/config"
5 "gemigit/db"
6
7 "github.com/pitr/gig"
8 "github.com/pquerna/otp/totp"
9
10 "log"
11 "bytes"
12 "image/png"
13 )
14
15 var keys = make(map[string]string)
16
17 func CreateTOTP(c gig.Context) error {
18
19 user, exist := db.GetUser(c.CertHash())
20 if !exist {
21 return c.NoContent(gig.StatusBadRequest, "Invalid username")
22 }
23
24 key, err := totp.Generate(totp.GenerateOpts{
25 Issuer: config.Cfg.Title,
26 AccountName: user.Name,
27 })
28
29 if err != nil {
30 log.Println(err)
31 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
32 }
33
34 var buf bytes.Buffer
35 img, err_ := key.Image(200, 200)
36 if err_ != nil {
37 log.Println(err)
38 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
39 }
40 png.Encode(&buf, img)
41
42 keys[c.CertHash()] = key.Secret()
43
44 return c.Blob("image/png", buf.Bytes())
45 }
46
47 func ConfirmTOTP(c gig.Context) error {
48
49 user, exist := db.GetUser(c.CertHash())
50 if !exist {
51 return c.NoContent(gig.StatusBadRequest, "Invalid username")
52 }
53
54 query, err := c.QueryString()
55 if err != nil {
56 log.Println(err)
57 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
58 }
59 if query == "" {
60 return c.NoContent(gig.StatusInput, "Code")
61 }
62
63 key, exist := keys[c.CertHash()]
64
65 valid := false
66 if exist {
67 valid = totp.Validate(query, key)
68 }
69 if !valid {
70 return c.NoContent(gig.StatusBadRequest, "Invalid code")
71 }
72
73 err = user.SetUserSecret(key)
74 if err != nil {
75 log.Println(err)
76 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
77 }
78
79 return c.NoContent(gig.StatusRedirectTemporary, "/account")
80 }
81
82 func LoginOTP(c gig.Context) error {
83
84 query, err := c.QueryString()
85 if err != nil {
86 log.Println(err)
87 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
88 }
89 if query == "" {
90 return c.NoContent(gig.StatusInput, "Code")
91 }
92
93 err = auth.LoginOTP(c.CertHash(), query)
94 if err != nil && err.Error() == "wrong code" {
95 return c.NoContent(gig.StatusInput, "Code")
96 }
97 if err != nil {
98 return c.NoContent(gig.StatusBadRequest, err.Error())
99 }
100 return c.NoContent(gig.StatusRedirectTemporary, "/account")
101 }
102
103 func RemoveTOTP(c gig.Context) error {
104
105 user, exist := db.GetUser(c.CertHash())
106 if !exist {
107 return c.NoContent(gig.StatusBadRequest, "Invalid username")
108 }
109
110 query, err := c.QueryString()
111 if err != nil {
112 log.Println(err)
113 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
114 }
115 if query == "" {
116 return c.NoContent(gig.StatusInput, "Code")
117 }
118
119 valid := totp.Validate(query, user.Secret)
120 if !valid {
121 return c.NoContent(gig.StatusInput, "Code")
122 }
123
124 err = user.SetUserSecret("")
125 if err != nil {
126 log.Println(err)
127 return c.NoContent(gig.StatusBadRequest, "Unexpected error")
128 }
129
130 return c.NoContent(gig.StatusRedirectTemporary, "/account/otp")
131 }
132
133 func ShowOTP(c gig.Context) error {
134 user, exist := db.GetUser(c.CertHash())
135 if !exist {
136 return c.NoContent(gig.StatusBadRequest, "Invalid username")
137 }
138 data := struct {
139 Secret bool
140 }{
141 Secret: user.Secret != "",
142 }
143 return execT(c, "otp.gmi", data)
144 }
145