Begin switch to gorilla/mux

I'm realizing with this code that I'm going to have a problem if I want
to do HATEOAS-style APIs. chi just doesn't do resource-oriented API
design, and I'd have to build a lot of stuff myself.

I'm in the middle of swapping out the UI. Now is the time to make the
switch.
This commit is contained in:
Eli Ribble 2026-04-01 15:32:27 +00:00
parent c253e655b1
commit 5172400803
No known key found for this signature in database
4 changed files with 53 additions and 6 deletions

View file

@ -102,7 +102,12 @@ func authenticatedHandlerJSONPut[ReqType any](f handlerFunctionPutAuthenticated[
serializeError(w, e)
return
}
http.Redirect(w, r, path, http.StatusFound)
if path == "" {
w.WriteHeader(http.StatusNoContent)
return
}
w.Header().Set("Location", path)
http.Redirect(w, r, path, http.StatusCreated)
})
}
func parseRequest[ReqType any](r *http.Request) (*ReqType, *nhttp.ErrorWithStatus) {

View file

@ -3,11 +3,14 @@ package api
import (
"context"
"net/http"
"strconv"
"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/html"
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"
)
type contentURLAPI struct {
@ -96,7 +99,16 @@ func listUserSuggestion(ctx context.Context, r *http.Request, user platform.User
}, nil
}
func userPut(ctx context.Context, r *http.Request, user platform.User, updates platform.User) (string, *nhttp.ErrorWithStatus) {
//if updates.Avatar
func userPut(ctx context.Context, r *http.Request, user platform.User, updates platform.UserChangeRequest) (string, *nhttp.ErrorWithStatus) {
log.Info().Str("avatar", updates.Avatar).Msg("doing updates")
user_id_str := chi.URLParam(r, "id")
user_id, err := strconv.Atoi(user_id_str)
if err != nil {
return "", nhttp.NewErrorStatus(http.StatusBadRequest, "user update: %w", err)
}
err = platform.UserUpdate(ctx, user, user_id, updates)
if err != nil {
return "", nhttp.NewError("user update: %w", err)
}
return "", nil
}

View file

@ -15,6 +15,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/debug"
"github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
@ -154,6 +155,34 @@ func userSuggestionNonRoot(ctx context.Context, user User, query_arg string) ([]
}
return results, nil
}
type UserChangeRequest struct {
Avatar string `json:"avatar"`
DisplayName string `json:"display_name"`
}
func UserUpdate(ctx context.Context, user User, user_id int, updates UserChangeRequest) error {
setter := models.UserSetter{}
target_user, err := models.FindUser(ctx, db.PGInstance.BobDB, int32(user_id))
if err != nil {
return fmt.Errorf("find user: %w", err)
}
if user.model.Role != enums.UserroleRoot && target_user.OrganizationID != target_user.OrganizationID {
return fmt.Errorf("Current user (%d) isn't allowed to change this user (%d)", user.ID, target_user.ID)
}
if updates.Avatar != "" {
u, err := uuid.Parse(updates.Avatar)
if err != nil {
return fmt.Errorf("parse uuid: %w", err)
}
setter.Avatar = omitnull.From(u)
}
if updates.DisplayName != "" {
setter.DisplayName = omit.From(updates.DisplayName)
}
err = target_user.Update(ctx, db.PGInstance.BobDB, &setter)
return err
}
func userSuggestionRoot(ctx context.Context, user User, query_arg string) ([]*User, error) {
users, err := models.Users.Query(
sm.Where(

View file

@ -362,11 +362,12 @@ const saveChanges = async () => {
console.error("Failed to upload avatar", error);
}
}
const url = session.urls?.api.user;
if (!url) {
console.log("empty avatar url");
const u = user.value;
if (!u) {
console.log("empty user");
return;
}
const url = "/api" + u.uri;
const response = await fetch(url, {
method: "PUT",
headers: {