Discover books, shows, and movies at your level. Track your progress by filling your Shelf with what you find, and share with other language learners. *No dusting required.
shlf.space
1package server
2
3import (
4 "fmt"
5 "log/slog"
6 "net/http"
7 "strings"
8
9 "shlf.space/internal/server/htmx"
10 "shlf.space/internal/views/login"
11)
12
13func (s *Server) Login(w http.ResponseWriter, r *http.Request) {
14 switch r.Method {
15 case http.MethodGet:
16 returnURL := r.URL.Query().Get("return_url")
17 errorCode := r.URL.Query().Get("error")
18 login.LoginPage(login.LoginPageParams{
19 ReturnUrl: returnURL,
20 ErrorCode: errorCode,
21 }).Render(r.Context(), w)
22 case http.MethodPost:
23 handle := r.FormValue("handle")
24 returnURL := r.FormValue("return_url")
25
26 // When users copy their handle from bsky.app, it tends to have these
27 // characters around it:
28 //
29 // @nelind.dk:
30 // \u202a ensures that the handle is always rendered left to right and
31 // \u202c reverts that so the rest of the page renders however it should
32 handle = strings.TrimPrefix(handle, "\u202a")
33 handle = strings.TrimSuffix(handle, "\u202c")
34
35 // `@` is harmless
36 handle = strings.TrimPrefix(handle, "@")
37
38 // Basic handle validation
39 if !strings.Contains(handle, ".") {
40 htmx.HxNotice(w, "login-msg", fmt.Sprintf("'%s' is an invalid handle. Did you mean %s.bsky.social?", handle, handle))
41 return
42 }
43
44 if err := s.oauth.SetAuthReturn(w, r, returnURL); err != nil {
45 slog.Error("failed to set auth return", "err", err)
46 }
47
48 redirectURL, err := s.oauth.ClientApp.StartAuthFlow(r.Context(), handle)
49 if err != nil {
50 htmx.HxNotice(w, "login-msg", fmt.Sprintf("Failed to start auth flow: %v", err))
51 return
52 }
53
54 htmx.HxRedirect(w, http.StatusOK, redirectURL)
55 }
56}