From 502a4d15dfb5a3d2bfd029ec68678b2cd30df7b0 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Fri, 6 Mar 2026 22:03:24 +0000 Subject: [PATCH] Add organization to all authorized endpoints We use it in filtering quite a bit. --- api/api.go | 16 ++++++++-------- api/handler.go | 9 ++------- auth/auth.go | 10 ++++++++-- sync/handler.go | 26 +++----------------------- sync/signin.go | 2 +- sync/tile.go | 3 +-- 6 files changed, 23 insertions(+), 43 deletions(-) diff --git a/api/api.go b/api/api.go index 5a25aff2..e1591c79 100644 --- a/api/api.go +++ b/api/api.go @@ -24,7 +24,7 @@ import ( "github.com/rs/zerolog/log" ) -func apiAudioPost(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiAudioPost(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { id := chi.URLParam(r, "uuid") noteUUID, err := uuid.Parse(id) if err != nil { @@ -61,7 +61,7 @@ func apiAudioPost(w http.ResponseWriter, r *http.Request, u *models.User) { w.WriteHeader(http.StatusAccepted) } -func apiAudioContentPost(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiAudioContentPost(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { u_str := chi.URLParam(r, "uuid") audioUUID, err := uuid.Parse(u_str) if err != nil { @@ -78,7 +78,7 @@ func apiAudioContentPost(w http.ResponseWriter, r *http.Request, u *models.User) w.WriteHeader(http.StatusOK) } -func handleClientIos(w http.ResponseWriter, r *http.Request, u *models.User) { +func handleClientIos(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { var sinceStr string err := r.ParseForm() if err != nil { @@ -121,7 +121,7 @@ func handleClientIos(w http.ResponseWriter, r *http.Request, u *models.User) { } } -func apiImagePost(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiImagePost(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { id := chi.URLParam(r, "uuid") noteUUID, err := uuid.Parse(id) if err != nil { @@ -156,7 +156,7 @@ func apiImagePost(w http.ResponseWriter, r *http.Request, u *models.User) { w.WriteHeader(http.StatusAccepted) } -func apiImageContentPost(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiImageContentPost(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { u_str := chi.URLParam(r, "uuid") imageUUID, err := uuid.Parse(u_str) if err != nil { @@ -173,7 +173,7 @@ func apiImageContentPost(w http.ResponseWriter, r *http.Request, u *models.User) fmt.Fprintf(w, "PNG uploaded successfully") } -func apiMosquitoSource(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiMosquitoSource(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { bounds, err := parseBounds(r) if err != nil { render.Render(w, r, errRender(err)) @@ -198,7 +198,7 @@ func apiMosquitoSource(w http.ResponseWriter, r *http.Request, u *models.User) { } } -func apiTrapData(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiTrapData(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { bounds, err := parseBounds(r) if err != nil { render.Render(w, r, errRender(err)) @@ -223,7 +223,7 @@ func apiTrapData(w http.ResponseWriter, r *http.Request, u *models.User) { } } -func apiServiceRequest(w http.ResponseWriter, r *http.Request, u *models.User) { +func apiServiceRequest(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { bounds, err := parseBounds(r) if err != nil { render.Render(w, r, errRender(err)) diff --git a/api/handler.go b/api/handler.go index de42c558..d3e933e5 100644 --- a/api/handler.go +++ b/api/handler.go @@ -37,7 +37,7 @@ type ErrorAPI struct { } func authenticatedHandlerJSON[T any](f handlerFunctionGet[T]) http.Handler { - return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { ctx := r.Context() org, err := u.Organization().One(ctx, db.PGInstance.BobDB) if err != nil { @@ -82,7 +82,7 @@ func authenticatedHandlerJSON[T any](f handlerFunctionGet[T]) http.Handler { type handlerFunctionPost[ReqType any, ResponseType any] func(context.Context, *http.Request, *models.Organization, *models.User, ReqType) (ResponseType, *nhttp.ErrorWithStatus) func authenticatedHandlerJSONPost[ReqType any, ResponseType any](f handlerFunctionPost[ReqType, ResponseType]) http.Handler { - return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { w.Header().Set("Content-Type", "application/json") var req ReqType body, err := io.ReadAll(r.Body) @@ -96,11 +96,6 @@ func authenticatedHandlerJSONPost[ReqType any, ResponseType any](f handlerFuncti return } ctx := r.Context() - org, err := u.Organization().One(ctx, db.PGInstance.BobDB) - if err != nil { - respondError(w, http.StatusInternalServerError, "Failed to get org: %w", err) - return - } response, e := f(ctx, r, org, u, req) if e != nil { http.Error(w, e.Error(), e.Status) diff --git a/auth/auth.go b/auth/auth.go index dc3487dd..6e76a044 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -36,7 +36,7 @@ type InvalidUsername struct{} func (e InvalidUsername) Error() string { return "That username doesn't exist" } -type AuthenticatedHandler func(http.ResponseWriter, *http.Request, *models.User) +type AuthenticatedHandler func(http.ResponseWriter, *http.Request, *models.Organization, *models.User) type EnsureAuth struct { handler AuthenticatedHandler } @@ -82,6 +82,7 @@ func (ea *EnsureAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) { accept := r.Header.Values("Accept") offers := []string{"application/json", "text/html"} + ctx := r.Context() content_type := NegotiateContent(accept, offers) user, err := GetAuthenticatedUser(r) if err != nil || user == nil { @@ -108,8 +109,13 @@ func (ea *EnsureAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write(msg) return } + org, err := user.Organization().One(ctx, db.PGInstance.BobDB) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } - ea.handler(w, r, user) + ea.handler(w, r, org, user) } func SigninUser(r *http.Request, username string, password string) (*models.User, error) { user, err := validateUser(r.Context(), username, password) diff --git a/sync/handler.go b/sync/handler.go index 95d47c71..962bb8fd 100644 --- a/sync/handler.go +++ b/sync/handler.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/Gleipnir-Technology/nidus-sync/auth" - "github.com/Gleipnir-Technology/nidus-sync/db" "github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" @@ -28,22 +27,13 @@ type contentAuthenticated[T any] struct { // w http.ResponseWriter, r *http.Request, u *models.User) { func authenticatedHandler[T any](f handlerFunctionGet[T]) http.Handler { - return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { ctx := r.Context() userContent, err := auth.ContentForUser(ctx, u) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - org, err := u.Organization().One(ctx, db.PGInstance.BobDB) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if org == nil { - http.Error(w, "nil org", http.StatusInternalServerError) - return - } resp, e := f(ctx, r, org, u) //log.Info().Str("template", template).Err(e).Msg("handler done") if e != nil { @@ -64,7 +54,7 @@ func authenticatedHandler[T any](f handlerFunctionGet[T]) http.Handler { type handlerFunctionPost[T any] func(context.Context, *http.Request, *models.Organization, *models.User, T) (string, *nhttp.ErrorWithStatus) func authenticatedHandlerPost[T any](f handlerFunctionPost[T]) http.Handler { - return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { err := r.ParseForm() if err != nil { respondError(w, "Failed to parse form", err, http.StatusBadRequest) @@ -79,11 +69,6 @@ func authenticatedHandlerPost[T any](f handlerFunctionPost[T]) http.Handler { return } ctx := r.Context() - org, err := u.Organization().One(ctx, db.PGInstance.BobDB) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } path, e := f(ctx, r, org, u, content) if e != nil { http.Error(w, e.Error(), e.Status) @@ -93,7 +78,7 @@ func authenticatedHandlerPost[T any](f handlerFunctionPost[T]) http.Handler { }) } func authenticatedHandlerPostMultipart[T any](f handlerFunctionPost[T]) http.Handler { - return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { err := r.ParseMultipartForm(32 << 10) // 32 MB buffer if err != nil { respondError(w, "Failed to parse form", err, http.StatusBadRequest) @@ -108,11 +93,6 @@ func authenticatedHandlerPostMultipart[T any](f handlerFunctionPost[T]) http.Han return } ctx := r.Context() - org, err := u.Organization().One(ctx, db.PGInstance.BobDB) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } path, e := f(ctx, r, org, u, content) if e != nil { http.Error(w, e.Error(), e.Status) diff --git a/sync/signin.go b/sync/signin.go index cdb6c4aa..6cdf4219 100644 --- a/sync/signin.go +++ b/sync/signin.go @@ -24,7 +24,7 @@ func getSignin(w http.ResponseWriter, r *http.Request) { signin(w, errorCode, next) } -func getSignout(w http.ResponseWriter, r *http.Request, user *models.User) { +func getSignout(w http.ResponseWriter, r *http.Request, org *models.Organization, user *models.User) { auth.SignoutUser(r, user) http.Redirect(w, r, "/signin", http.StatusFound) } diff --git a/sync/tile.go b/sync/tile.go index c23374af..fbe50472 100644 --- a/sync/tile.go +++ b/sync/tile.go @@ -11,7 +11,7 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/platform/imagetile" ) -func getTileGPS(w http.ResponseWriter, r *http.Request, u *models.User) { +func getTileGPS(w http.ResponseWriter, r *http.Request, org *models.Organization, u *models.User) { ctx := r.Context() if err := r.ParseForm(); err != nil { respondError(w, "Could not parse form", err, http.StatusBadRequest) @@ -40,7 +40,6 @@ func getTileGPS(w http.ResponseWriter, r *http.Request, u *models.User) { respondError(w, "couldn't parse lng", err, http.StatusBadRequest) return } - org := u.R.Organization img, err := imagetile.ImageAtPoint(ctx, org, uint(level), lat, lng) if err != nil { respondError(w, "image at point", err, http.StatusInternalServerError)