diff --git a/internal/auth/service.go b/internal/auth/service.go index 8c7b8b9..00b3ef0 100644 --- a/internal/auth/service.go +++ b/internal/auth/service.go @@ -42,3 +42,12 @@ func (s *Service) Authenticate(ctx context.Context, email UserEmail, password st return account, nil } + +// LookupByEmail fetches a user by canonical email. +func (s *Service) LookupByEmail(ctx context.Context, email UserEmail) (*User, error) { + if email.IsZero() { + return nil, ErrInvalidInput + } + + return s.store.FindByEmail(ctx, email) +} diff --git a/internal/server/handler_dashboard.go b/internal/server/handler_dashboard.go index 02ee0bc..50190b5 100644 --- a/internal/server/handler_dashboard.go +++ b/internal/server/handler_dashboard.go @@ -1,6 +1,14 @@ package server -import "net/http" +import ( + "log" + "net/http" + "time" + + "github.com/rjnemo/auth/internal/auth" +) + +const dashboardTimeDisplayLayout = "02 Jan 2006 15:04 MST" func (s *Server) dashboardHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { @@ -12,6 +20,23 @@ func (s *Server) dashboardHandler() http.HandlerFunc { return } - s.render(w, "in.html", PageData{Email: state.Email, CSRFToken: state.CSRFToken}) + email, err := auth.NewUserEmail(state.Email) + if err != nil { + log.Printf("dashboard: invalid session email: %v", err) + http.Error(w, "session invalid", http.StatusUnauthorized) + return + } + + account, err := s.authService.LookupByEmail(r.Context(), email) + if err != nil { + log.Printf("dashboard: lookup failed: %v", err) + http.Error(w, "unable to load account", http.StatusInternalServerError) + return + } + + createdAtISO := account.CreatedAt.Format(time.RFC3339) + createdAtDisplay := account.CreatedAt.Format(dashboardTimeDisplayLayout) + + s.render(w, "in.html", newDashboardData(state.Email, state.CSRFToken, createdAtDisplay, createdAtISO)) } } diff --git a/internal/server/session.go b/internal/server/session.go index 76f30d3..a2e8796 100644 --- a/internal/server/session.go +++ b/internal/server/session.go @@ -3,14 +3,13 @@ package server import ( "crypto/rand" "encoding/base64" - "errors" + "fmt" "net/http" "time" ) const ( sessionCookieName = "auth_session" - csrfSessionKey = "csrf_token" sessionLifetime = 12 * time.Hour sessionSecretMinLength = 32 csrfTokenByteLength int = 32 @@ -24,7 +23,7 @@ type SessionStore struct { // NewSessionStore creates a cookie-backed session store. func NewSessionStore(secret []byte) (*SessionStore, error) { if len(secret) < sessionSecretMinLength { - return nil, errors.New("session secret must be at least 32 bytes") + return nil, fmt.Errorf("session secret must be at least %d bytes", sessionSecretMinLength) } // copy secret to avoid external mutation buf := make([]byte, len(secret)) diff --git a/internal/server/views.go b/internal/server/views.go index 072fa26..84b0c85 100644 --- a/internal/server/views.go +++ b/internal/server/views.go @@ -2,9 +2,11 @@ package server // PageData contains fields shared by the templates for now. type PageData struct { - Email string - Error string - CSRFToken string + Email string + Error string + CSRFToken string + CreatedAt string + CreatedAtISO string } func newIndexData(email, errMsg, token string) PageData { @@ -14,3 +16,7 @@ func newIndexData(email, errMsg, token string) PageData { func newUnauthorizedData(errMsg, token string) PageData { return PageData{Error: errMsg, CSRFToken: token} } + +func newDashboardData(email, token, createdAt, createdAtISO string) PageData { + return PageData{Email: email, CSRFToken: token, CreatedAt: createdAt, CreatedAtISO: createdAtISO} +} diff --git a/web/templates/in.html b/web/templates/in.html index 3fce694..9285aef 100644 --- a/web/templates/in.html +++ b/web/templates/in.html @@ -12,12 +12,24 @@

Welcome

-

You are signed in as {{.Email}}.

-

This placeholder dashboard will evolve as we flesh out the auth flow.

-
- - -
+
+

You are signed in as {{.Email}}.

+ {{if .CreatedAt}} +

+ Member since + . +

+ {{end}} +

+ This placeholder dashboard will evolve as we flesh out the auth flow. +

+ +
diff --git a/web/templates/index.html b/web/templates/index.html index 3456526..ff8dab2 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -15,7 +15,12 @@

Authenticate with the demo credentials below to view the dashboard.

Demo account
-

Email: user@example.com
Password: password123

+

+ Email: user@example.com
+ Password: + + password123 +

{{if .Error}}
diff --git a/web/templates/unauthorized.html b/web/templates/unauthorized.html index 702da32..d8d7787 100644 --- a/web/templates/unauthorized.html +++ b/web/templates/unauthorized.html @@ -12,7 +12,10 @@

Unauthorized

-

{{if .Error}}{{.Error}}{{else}}You do not have permission to view that page.{{end}}

+

+ {{if .Error}}{{.Error}}{{else}}You do not have permission to view that + page.{{end}} +

Back to safety