nandi/gleanpublic Fork 0
c9bc9bc
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Pretty error handlingUnverified

Julien Robert committed 2026-04-23T20:58:54+02:00 Browse files
c9bc9bc parent: 3fe5441
modified internal/server/auth_handler.go +9 -9
@@ -20,7 +20,7 @@ func (s *Server) handleAuthLogin(w http.ResponseWriter, r *http.Request) {
2020 func (s *Server) handleAuthStart(w http.ResponseWriter, r *http.Request) {
2121 handle := strings.TrimPrefix(r.FormValue("handle"), "@")
2222 if handle == "" {
23- http.Error(w, "handle required", http.StatusBadRequest)
23+ s.renderError(w, r, http.StatusBadRequest, "Missing handle", "Please enter your handle.")
2424 return
2525 }
2626
@@ -30,12 +30,12 @@ func (s *Server) handleAuthStart(w http.ResponseWriter, r *http.Request) {
3030
3131 did, resolveErr := atproto.ResolveHandle(r.Context(), handle)
3232 if resolveErr != nil {
33- http.Error(w, "could not resolve handle", http.StatusInternalServerError)
33+ s.renderError(w, r, http.StatusBadGateway, "Handle not found", "Could not resolve that handle. Please check and try again.")
3434 return
3535 }
3636 user, createErr := s.dbs.Users.CreateUser(r.Context(), did)
3737 if createErr != nil {
38- http.Error(w, createErr.Error(), http.StatusInternalServerError)
38+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
3939 return
4040 }
4141 s.setUserSession(w, user)
@@ -56,21 +56,21 @@ func (s *Server) handleAuthCallback(w http.ResponseWriter, r *http.Request) {
5656
5757 handle := params.Get("handle")
5858 if handle == "" {
59- http.Error(w, "handle required", http.StatusBadRequest)
59+ s.renderError(w, r, http.StatusBadRequest, "Missing handle", "Please enter your handle.")
6060 return
6161 }
6262
6363 did, err := atproto.ResolveHandle(r.Context(), handle)
6464 if err != nil {
6565 s.logger.Error("failed to resolve handle", "error", err)
66- http.Error(w, err.Error(), http.StatusInternalServerError)
66+ s.renderError(w, r, http.StatusBadGateway, "Handle not found", "Could not resolve that handle. Please check and try again.")
6767 return
6868 }
6969
7070 user, err := s.dbs.Users.CreateUser(r.Context(), did)
7171 if err != nil {
7272 s.logger.Error("failed to create user", "error", err)
73- http.Error(w, err.Error(), http.StatusInternalServerError)
73+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
7474 return
7575 }
7676
@@ -82,7 +82,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
8282 sessData, err := s.oauth.ProcessCallback(r.Context(), r.URL.Query())
8383 if err != nil {
8484 s.logger.Error("OAuth callback failed", "error", err)
85- http.Error(w, "authentication failed: "+err.Error(), http.StatusInternalServerError)
85+ s.renderError(w, r, http.StatusInternalServerError, "Authentication failed", "Something went wrong during sign in. Please try again.")
8686 return
8787 }
8888
@@ -93,7 +93,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
9393 user, err := s.dbs.Users.CreateUser(r.Context(), did)
9494 if err != nil {
9595 s.logger.Error("failed to create user", "error", err)
96- http.Error(w, err.Error(), http.StatusInternalServerError)
96+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
9797 return
9898 }
9999
@@ -105,7 +105,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
105105 encoded, err := encodeSession(sessionData)
106106 if err != nil {
107107 s.logger.Error("failed to encode session", "error", err)
108- http.Error(w, "internal error", http.StatusInternalServerError)
108+ s.renderError(w, r, http.StatusInternalServerError, "Session error", "Could not create your session. Please try again.")
109109 return
110110 }
111111
@@ -20,7 +20,7 @@ func (s *Server) handleAuthLogin(w http.ResponseWriter, r *http.Request) {
20 func (s *Server) handleAuthStart(w http.ResponseWriter, r *http.Request) {20 func (s *Server) handleAuthStart(w http.ResponseWriter, r *http.Request) {
21 handle := strings.TrimPrefix(r.FormValue("handle"), "@")21 handle := strings.TrimPrefix(r.FormValue("handle"), "@")
22 if handle == "" {22 if handle == "" {
23- http.Error(w, "handle required", http.StatusBadRequest)23+ s.renderError(w, r, http.StatusBadRequest, "Missing handle", "Please enter your handle.")
24 return24 return
25 }25 }
26 26
@@ -30,12 +30,12 @@ func (s *Server) handleAuthStart(w http.ResponseWriter, r *http.Request) {
30 30
31 did, resolveErr := atproto.ResolveHandle(r.Context(), handle)31 did, resolveErr := atproto.ResolveHandle(r.Context(), handle)
32 if resolveErr != nil {32 if resolveErr != nil {
33- http.Error(w, "could not resolve handle", http.StatusInternalServerError)33+ s.renderError(w, r, http.StatusBadGateway, "Handle not found", "Could not resolve that handle. Please check and try again.")
34 return34 return
35 }35 }
36 user, createErr := s.dbs.Users.CreateUser(r.Context(), did)36 user, createErr := s.dbs.Users.CreateUser(r.Context(), did)
37 if createErr != nil {37 if createErr != nil {
38- http.Error(w, createErr.Error(), http.StatusInternalServerError)38+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
39 return39 return
40 }40 }
41 s.setUserSession(w, user)41 s.setUserSession(w, user)
@@ -56,21 +56,21 @@ func (s *Server) handleAuthCallback(w http.ResponseWriter, r *http.Request) {
56 56
57 handle := params.Get("handle")57 handle := params.Get("handle")
58 if handle == "" {58 if handle == "" {
59- http.Error(w, "handle required", http.StatusBadRequest)59+ s.renderError(w, r, http.StatusBadRequest, "Missing handle", "Please enter your handle.")
60 return60 return
61 }61 }
62 62
63 did, err := atproto.ResolveHandle(r.Context(), handle)63 did, err := atproto.ResolveHandle(r.Context(), handle)
64 if err != nil {64 if err != nil {
65 s.logger.Error("failed to resolve handle", "error", err)65 s.logger.Error("failed to resolve handle", "error", err)
66- http.Error(w, err.Error(), http.StatusInternalServerError)66+ s.renderError(w, r, http.StatusBadGateway, "Handle not found", "Could not resolve that handle. Please check and try again.")
67 return67 return
68 }68 }
69 69
70 user, err := s.dbs.Users.CreateUser(r.Context(), did)70 user, err := s.dbs.Users.CreateUser(r.Context(), did)
71 if err != nil {71 if err != nil {
72 s.logger.Error("failed to create user", "error", err)72 s.logger.Error("failed to create user", "error", err)
73- http.Error(w, err.Error(), http.StatusInternalServerError)73+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
74 return74 return
75 }75 }
76 76
@@ -82,7 +82,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
82 sessData, err := s.oauth.ProcessCallback(r.Context(), r.URL.Query())82 sessData, err := s.oauth.ProcessCallback(r.Context(), r.URL.Query())
83 if err != nil {83 if err != nil {
84 s.logger.Error("OAuth callback failed", "error", err)84 s.logger.Error("OAuth callback failed", "error", err)
85- http.Error(w, "authentication failed: "+err.Error(), http.StatusInternalServerError)85+ s.renderError(w, r, http.StatusInternalServerError, "Authentication failed", "Something went wrong during sign in. Please try again.")
86 return86 return
87 }87 }
88 88
@@ -93,7 +93,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
93 user, err := s.dbs.Users.CreateUser(r.Context(), did)93 user, err := s.dbs.Users.CreateUser(r.Context(), did)
94 if err != nil {94 if err != nil {
95 s.logger.Error("failed to create user", "error", err)95 s.logger.Error("failed to create user", "error", err)
96- http.Error(w, err.Error(), http.StatusInternalServerError)96+ s.renderError(w, r, http.StatusInternalServerError, "Sign in failed", "Could not create your account. Please try again.")
97 return97 return
98 }98 }
99 99
@@ -105,7 +105,7 @@ func (s *Server) handleOAuthCallback(w http.ResponseWriter, r *http.Request) {
105 encoded, err := encodeSession(sessionData)105 encoded, err := encodeSession(sessionData)
106 if err != nil {106 if err != nil {
107 s.logger.Error("failed to encode session", "error", err)107 s.logger.Error("failed to encode session", "error", err)
108- http.Error(w, "internal error", http.StatusInternalServerError)108+ s.renderError(w, r, http.StatusInternalServerError, "Session error", "Could not create your session. Please try again.")
109 return109 return
110 }110 }
111 111
modified internal/server/profile_handler.go +2 -2
@@ -20,7 +20,7 @@ func (s *Server) handleProfile(w http.ResponseWriter, r *http.Request) {
2020 resolved, err := atproto.ResolveHandle(ctx, param)
2121 if err != nil {
2222 s.logger.Warn("failed to resolve handle", "error", err, "handle", param)
23- http.Error(w, "handle not found", http.StatusNotFound)
23+ s.renderError(w, r, http.StatusNotFound, "Handle not found", "Could not find a user with that handle.")
2424 return
2525 }
2626 did = resolved
@@ -29,7 +29,7 @@ func (s *Server) handleProfile(w http.ResponseWriter, r *http.Request) {
2929 profileUser, err := s.dbs.Users.GetUser(ctx, did)
3030 if err != nil {
3131 s.logger.Warn("failed to get user", "error", err, "did", did)
32- http.Error(w, "user not found", http.StatusNotFound)
32+ s.renderError(w, r, http.StatusNotFound, "User not found", "This user doesn't exist in Glean yet.")
3333 return
3434 }
3535
@@ -20,7 +20,7 @@ func (s *Server) handleProfile(w http.ResponseWriter, r *http.Request) {
20 resolved, err := atproto.ResolveHandle(ctx, param)20 resolved, err := atproto.ResolveHandle(ctx, param)
21 if err != nil {21 if err != nil {
22 s.logger.Warn("failed to resolve handle", "error", err, "handle", param)22 s.logger.Warn("failed to resolve handle", "error", err, "handle", param)
23- http.Error(w, "handle not found", http.StatusNotFound)23+ s.renderError(w, r, http.StatusNotFound, "Handle not found", "Could not find a user with that handle.")
24 return24 return
25 }25 }
26 did = resolved26 did = resolved
@@ -29,7 +29,7 @@ func (s *Server) handleProfile(w http.ResponseWriter, r *http.Request) {
29 profileUser, err := s.dbs.Users.GetUser(ctx, did)29 profileUser, err := s.dbs.Users.GetUser(ctx, did)
30 if err != nil {30 if err != nil {
31 s.logger.Warn("failed to get user", "error", err, "did", did)31 s.logger.Warn("failed to get user", "error", err, "did", did)
32- http.Error(w, "user not found", http.StatusNotFound)32+ s.renderError(w, r, http.StatusNotFound, "User not found", "This user doesn't exist in Glean yet.")
33 return33 return
34 }34 }
35 35
modified internal/server/server.go +13 -0
@@ -512,6 +512,19 @@ func (s *Server) handleNotFound(w http.ResponseWriter, r *http.Request) {
512512 s.render(w, r, "404.html", nil)
513513 }
514514
515+func (s *Server) renderError(w http.ResponseWriter, r *http.Request, code int, title, message string) {
516+ if r.Header.Get("HX-Request") == "true" {
517+ w.WriteHeader(code)
518+ w.Write([]byte(message))
519+ return
520+ }
521+ w.WriteHeader(code)
522+ s.render(w, r, "error.html", map[string]any{
523+ "Title": title,
524+ "Message": message,
525+ })
526+}
527+
515528 func (s *Server) render(w http.ResponseWriter, r *http.Request, name string, data map[string]any) {
516529 if data == nil {
517530 data = map[string]any{}
@@ -512,6 +512,19 @@ func (s *Server) handleNotFound(w http.ResponseWriter, r *http.Request) {
512 s.render(w, r, "404.html", nil)512 s.render(w, r, "404.html", nil)
513 }513 }
514 514
515+func (s *Server) renderError(w http.ResponseWriter, r *http.Request, code int, title, message string) {
516+ if r.Header.Get("HX-Request") == "true" {
517+ w.WriteHeader(code)
518+ w.Write([]byte(message))
519+ return
520+ }
521+ w.WriteHeader(code)
522+ s.render(w, r, "error.html", map[string]any{
523+ "Title": title,
524+ "Message": message,
525+ })
526+}
527+
515 func (s *Server) render(w http.ResponseWriter, r *http.Request, name string, data map[string]any) {528 func (s *Server) render(w http.ResponseWriter, r *http.Request, name string, data map[string]any) {
516 if data == nil {529 if data == nil {
517 data = map[string]any{}530 data = map[string]any{}
added internal/tmpl/error.html +14 -0
new file mode 100644
@@ -0,0 +1,14 @@
1+{{define "error.html"}}
2+<div class="max-w-md mx-auto mt-20">
3+ <div class="bg-spot-surface rounded-xl shadow-spot-heavy p-8">
4+ <div class="flex justify-center mb-6">
5+ <span class="w-14 h-14">{{template "logo-icon"}}</span>
6+ </div>
7+ <h1 class="text-2xl font-bold text-spot-text mb-2 text-center">{{.Title}}</h1>
8+ <p class="text-spot-secondary text-sm mb-6 text-center">{{.Message}}</p>
9+ <a href="/dashboard" class="w-full flex items-center justify-center gap-2 bg-spot-green text-white rounded-pill px-4 py-3 text-sm font-bold uppercase tracking-button hover:brightness-110 transition">
10+ Back to Dashboard
11+ </a>
12+ </div>
13+</div>
14+{{end}}
new file mode 100644
@@ -0,0 +1,14 @@
1+{{define "error.html"}}
2+<div class="max-w-md mx-auto mt-20">
3+ <div class="bg-spot-surface rounded-xl shadow-spot-heavy p-8">
4+ <div class="flex justify-center mb-6">
5+ <span class="w-14 h-14">{{template "logo-icon"}}</span>
6+ </div>
7+ <h1 class="text-2xl font-bold text-spot-text mb-2 text-center">{{.Title}}</h1>
8+ <p class="text-spot-secondary text-sm mb-6 text-center">{{.Message}}</p>
9+ <a href="/dashboard" class="w-full flex items-center justify-center gap-2 bg-spot-green text-white rounded-pill px-4 py-3 text-sm font-bold uppercase tracking-button hover:brightness-110 transition">
10+ Back to Dashboard
11+ </a>
12+ </div>
13+</div>
14+{{end}}