Add avatar resource

This commit is contained in:
Eli Ribble 2026-04-01 21:23:28 +00:00
parent 0a7a2512d4
commit a89a4fbec5
No known key found for this signature in database
10 changed files with 129 additions and 62 deletions

View file

@ -1,26 +1 @@
package api
import (
"context"
"fmt"
"net/http"
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/platform/file"
)
func avatarPost(ctx context.Context, r *http.Request, u platform.User, uploads []file.Upload) (string, *nhttp.ErrorWithStatus) {
if len(uploads) == 0 {
return "", nhttp.NewErrorStatus(http.StatusBadRequest, "No upload found")
}
if len(uploads) != 1 {
return "", nhttp.NewErrorStatus(http.StatusBadRequest, "You must only submit one file at a time")
}
upload := uploads[0]
err := platform.AvatarCreate(r.Context(), u, upload)
if err != nil {
return "", nhttp.NewErrorStatus(http.StatusBadRequest, "Create avatar: %w", err)
}
return fmt.Sprintf("/avatar/%s", upload.UUID.String()), nil
}

View file

@ -73,7 +73,7 @@ func apiGetDistrictLogo(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Logo not found", http.StatusNotFound)
return
}
file.ImageFileContentWriteLogo(w, org.LogoUUID.MustGet())
file.ImageFileToWriter(file.CollectionLogo, org.LogoUUID.MustGet(), w)
return
default:
http.Error(w, "Too many organizations, this is a programmer error", http.StatusInternalServerError)

View file

@ -13,12 +13,34 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/platform/file"
"github.com/Gleipnir-Technology/nidus-sync/resource"
"github.com/google/uuid"
"github.com/gorilla/schema"
"github.com/rs/zerolog/log"
)
var decoder = schema.NewDecoder()
type handlerFunctionGetImage func(context.Context, *http.Request, platform.User) (file.Collection, uuid.UUID, *nhttp.ErrorWithStatus)
func authenticatedHandlerGetImage(f handlerFunctionGetImage) http.Handler {
return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u platform.User) {
ctx := r.Context()
collection, uid, e := f(ctx, r, u)
if e != nil {
log.Warn().Int("status", e.Status).Err(e).Str("user message", e.Message).Msg("Responding with an error from api")
body, err := json.Marshal(ErrorAPI{Message: e.Error()})
if err != nil {
log.Error().Err(err).Msg("failed to marshal error")
http.Error(w, "{\"message\": \"boom. I can't even tell you what went wrong\"}", http.StatusInternalServerError)
return
}
http.Error(w, string(body), e.Status)
return
}
file.ImageFileToWriter(collection, uid, w)
})
}
type handlerFunctionGet[T any] func(context.Context, *http.Request, platform.User, resource.QueryParams) (*T, *nhttp.ErrorWithStatus)
type wrappedHandler func(http.ResponseWriter, *http.Request)
type contentAuthenticated[T any] struct {

View file

@ -62,7 +62,7 @@ func apiImageContentGet(w http.ResponseWriter, r *http.Request, u platform.User)
log.Error().Err(err).Msg("Failed to parse image UUID")
http.Error(w, "Failed to parse image UUID", http.StatusBadRequest)
}
file.PublicImageFileToResponse(w, imageUUID)
file.ImageFileToWriter(file.CollectionPublicImage, imageUUID, w)
w.WriteHeader(http.StatusOK)
}
func apiImageContentPost(w http.ResponseWriter, r *http.Request, u platform.User) {
@ -73,7 +73,7 @@ func apiImageContentPost(w http.ResponseWriter, r *http.Request, u platform.User
log.Error().Err(err).Msg("Failed to parse image UUID")
http.Error(w, "Failed to parse image UUID", http.StatusBadRequest)
}
err = file.ImageFileContentWrite(imageUUID, r.Body)
err = file.ImageFileFromReader(file.CollectionImageRaw, imageUUID, r.Body)
if err != nil {
renderShim(w, r, errRender(err))
return

View file

@ -16,7 +16,9 @@ func AddRoutes(r *mux.Router) {
// Authenticated endpoints
r.Handle("/audio/{uuid}", auth.NewEnsureAuth(apiAudioPost)).Methods("POST")
r.Handle("/audio/{uuid}/content", auth.NewEnsureAuth(apiAudioContentPost)).Methods("POST")
r.Handle("/avatar", authenticatedHandlerPostMultipart(avatarPost, file.CollectionAvatar)).Methods("POST")
avatar := resource.Avatar(router)
r.Handle("/avatar/{uuid}", authenticatedHandlerGetImage(avatar.ByIDGet)).Methods("GET").Name("avatar.ByIDGet")
r.Handle("/avatar", authenticatedHandlerPostMultipart(avatar.Create, file.CollectionAvatar)).Methods("POST")
r.Handle("/client/ios", auth.NewEnsureAuth(handleClientIos)).Methods("GET")
communication := resource.Communication(r)
r.Handle("/communication", authenticatedHandlerJSON(communication.List)).Methods("GET")