diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2026-09-24 17:09:25 -0700 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2026-09-24 17:09:42 -0700 |
| commit | b8f2d13664698d999a4154f43e869402cc5cec49 (patch) | |
| tree | 6ffec6b2d7db3f4701371f3475852185f2d232ff | |
| parent | Add a way to log out (diff) | |
| download | roseh.moe-b8f2d13664698d999a4154f43e869402cc5cec49.tar.zst | |
Add an easier way to log in
| -rw-r--r-- | roseh.moe.go | 59 | ||||
| -rw-r--r-- | templates/otp.html.template | 6 |
2 files changed, 65 insertions, 0 deletions
diff --git a/roseh.moe.go b/roseh.moe.go index 53deb02..e8f2d41 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -829,6 +829,63 @@ func logout(w http.ResponseWriter, r *http.Request) { } var ( + //go:embed templates/otp.html.template + otpString string + otpTemplate = template.Must(outlinedTemplate(otpString)) + + otpMu sync.Mutex + currentOTP string +) + +type otpTemplateArgs struct { + URL string + QR string +} + +func otp(w http.ResponseWriter, r *http.Request) { + buf := make([]byte, 20) + rand.Read(buf) + newOTP := new(strings.Builder) + for i := range 10 { + if i > 0 { + newOTP.WriteString("-") + } + newOTP.WriteString(wordlist.Words[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff]) + } + otpMu.Lock() + currentOTP = newOTP.String() + otpMu.Unlock() + downloadURL := selfURL.String() + "/otp/" + newOTP.String() + if err := otpTemplate.Execute(w, otpTemplateArgs{ + URL: downloadURL, + QR: "/qr.png?" + url.Values{"t": []string{downloadURL}, "s": []string{base64.RawURLEncoding.EncodeToString(mac([]byte(downloadURL), "qr"))}}.Encode(), + }); err != nil { + log.Printf("Warning: otp: %s", err) + } +} + +func otpCode(w http.ResponseWriter, r *http.Request) { + code := r.PathValue("code") + if code == "" { + notFound(w, r) + return + } + matched := false + otpMu.Lock() + if code == currentOTP { + currentOTP = "" + matched = true + } + otpMu.Unlock() + if !matched { + notFound(w, r) + return + } + attachCookie(w) + io.WriteString(w, "logged in\n") +} + +var ( //go:embed templates/note.html.template notepadString string notepadTemplate = template.Must(outlinedTemplate(notepadString)) @@ -1140,6 +1197,8 @@ func main() { mux.HandleFunc("GET /wormhole/{hole}", wormholeDownload) mux.HandleFunc("GET /login", serveLogin) mux.HandleFunc("POST /login", login) + mux.Handle("GET /otp", &authHandler{h: http.HandlerFunc(otp)}) + mux.HandleFunc("GET /otp/{code}", otpCode) mux.Handle("GET /logout", &authHandler{h: http.HandlerFunc(logout), noRedirect: true}) mux.Handle("GET /notepad", &authHandler{h: http.HandlerFunc(notepad)}) mux.Handle("POST /notepad", &authHandler{h: http.HandlerFunc(autosave), noRedirect: true}) diff --git a/templates/otp.html.template b/templates/otp.html.template new file mode 100644 index 0000000..3b765f7 --- /dev/null +++ b/templates/otp.html.template @@ -0,0 +1,6 @@ +<title>OTP</title> + +<div style="display:flex;flex-direction:column;align-items:center;font-size:50px"> + <p><a href="{{.URL}}">{{.URL}}</a></p> + <img src="{{.QR}}" alt="QR code for {{.URL}}" width="500px"> +</div> |
