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
at master 56 lines 1.6 kB view raw
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}