forked from wrenn/wrenn
v0.2.0 (#50)
Co-authored-by: Tasnim Kabir Sadik <tksadik@omukk.dev> Reviewed-on: wrenn/wrenn#50
This commit is contained in:
66
internal/api/handlers_sessions.go
Normal file
66
internal/api/handlers_sessions.go
Normal file
@ -0,0 +1,66 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"git.omukk.dev/wrenn/wrenn/pkg/auth"
|
||||
"git.omukk.dev/wrenn/wrenn/pkg/auth/session"
|
||||
)
|
||||
|
||||
type sessionsHandler struct {
|
||||
sessions *session.Service
|
||||
}
|
||||
|
||||
func newSessionsHandler(svc *session.Service) *sessionsHandler {
|
||||
return &sessionsHandler{sessions: svc}
|
||||
}
|
||||
|
||||
// List handles GET /v1/me/sessions — returns all active sessions for the
|
||||
// current user, flagging the caller's own session as current.
|
||||
func (h *sessionsHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
ac := auth.MustFromContext(r.Context())
|
||||
rows, err := h.sessions.ListForUser(r.Context(), ac.UserID)
|
||||
if err != nil {
|
||||
slog.Error("list sessions: db error", "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "db_error", "failed to list sessions")
|
||||
return
|
||||
}
|
||||
out := make([]sessionRow, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
out = append(out, sessionRow{
|
||||
ID: row.ID,
|
||||
UserAgent: row.UserAgent,
|
||||
IPAddress: row.IpAddress,
|
||||
CreatedAt: row.CreatedAt.Time.UTC().Format(time.RFC3339),
|
||||
LastSeenAt: row.LastSeenAt.Time.UTC().Format(time.RFC3339),
|
||||
ExpiresAt: row.ExpiresAt.Time.UTC().Format(time.RFC3339),
|
||||
Current: row.ID == ac.SessionID,
|
||||
})
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"sessions": out})
|
||||
}
|
||||
|
||||
// Delete handles DELETE /v1/me/sessions/{id} — revokes a single session
|
||||
// belonging to the current user. If the caller revokes their own session,
|
||||
// their cookies are cleared on the response.
|
||||
func (h *sessionsHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
ac := auth.MustFromContext(r.Context())
|
||||
sid := chi.URLParam(r, "id")
|
||||
if sid == "" {
|
||||
writeError(w, http.StatusBadRequest, "invalid_request", "missing session id")
|
||||
return
|
||||
}
|
||||
if err := h.sessions.DeleteForUser(r.Context(), sid, ac.UserID); err != nil {
|
||||
slog.Error("delete session: db error", "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "db_error", "failed to delete session")
|
||||
return
|
||||
}
|
||||
if sid == ac.SessionID {
|
||||
clearSessionCookies(w, isSecure(r))
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
Reference in New Issue
Block a user