Refactor frontend components and enhance API integration
- Updated frontend-nuxt.mdc to specify usage of composables for API calls. - Added new AuthCard and ConfirmModal components for improved UI consistency. - Introduced UserAvatar component for user profile display, replacing previous Gravatar implementation. - Implemented useFormSubmit composable for handling form submissions with loading and error states. - Enhanced vitest.config.ts to include coverage reporting for composables and components. - Removed deprecated useAdminApi and useAuth composables to streamline API interactions. - Updated login and setup pages to utilize new components and composables for better user experience.
This commit is contained in:
@@ -32,8 +32,7 @@ func (h *Handlers) APIAdminUsers(rw http.ResponseWriter, req *http.Request) {
|
||||
JSON(rw, http.StatusOK, list)
|
||||
return
|
||||
}
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
s := h.requireAdmin(rw, req)
|
||||
@@ -65,14 +64,17 @@ func (h *Handlers) APIAdminUsers(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIAdminUserByName handles GET /map/api/admin/users/:name.
|
||||
func (h *Handlers) APIAdminUserByName(rw http.ResponseWriter, req *http.Request, name string) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
return
|
||||
}
|
||||
auths, found := h.Admin.GetUser(req.Context(), name)
|
||||
auths, found, err := h.Admin.GetUser(req.Context(), name)
|
||||
if err != nil {
|
||||
HandleServiceError(rw, err)
|
||||
return
|
||||
}
|
||||
out := struct {
|
||||
Username string `json:"username"`
|
||||
Auths []string `json:"auths"`
|
||||
@@ -85,8 +87,7 @@ func (h *Handlers) APIAdminUserByName(rw http.ResponseWriter, req *http.Request,
|
||||
|
||||
// APIAdminUserDelete handles DELETE /map/api/admin/users/:name.
|
||||
func (h *Handlers) APIAdminUserDelete(rw http.ResponseWriter, req *http.Request, name string) {
|
||||
if req.Method != http.MethodDelete {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodDelete) {
|
||||
return
|
||||
}
|
||||
s := h.requireAdmin(rw, req)
|
||||
@@ -106,8 +107,7 @@ func (h *Handlers) APIAdminUserDelete(rw http.ResponseWriter, req *http.Request,
|
||||
|
||||
// APIAdminSettingsGet handles GET /map/api/admin/settings.
|
||||
func (h *Handlers) APIAdminSettingsGet(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -127,8 +127,7 @@ func (h *Handlers) APIAdminSettingsGet(rw http.ResponseWriter, req *http.Request
|
||||
|
||||
// APIAdminSettingsPost handles POST /map/api/admin/settings.
|
||||
func (h *Handlers) APIAdminSettingsPost(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -152,8 +151,7 @@ func (h *Handlers) APIAdminSettingsPost(rw http.ResponseWriter, req *http.Reques
|
||||
|
||||
// APIAdminMaps handles GET /map/api/admin/maps.
|
||||
func (h *Handlers) APIAdminMaps(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -178,8 +176,7 @@ func (h *Handlers) APIAdminMapByID(rw http.ResponseWriter, req *http.Request, id
|
||||
JSONError(rw, http.StatusBadRequest, "bad request", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -208,8 +205,7 @@ func (h *Handlers) APIAdminMapToggleHidden(rw http.ResponseWriter, req *http.Req
|
||||
JSONError(rw, http.StatusBadRequest, "bad request", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -230,8 +226,7 @@ func (h *Handlers) APIAdminMapToggleHidden(rw http.ResponseWriter, req *http.Req
|
||||
|
||||
// APIAdminWipe handles POST /map/api/admin/wipe.
|
||||
func (h *Handlers) APIAdminWipe(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -327,8 +322,7 @@ func (h *Handlers) APIAdminHideMarker(rw http.ResponseWriter, req *http.Request)
|
||||
|
||||
// APIAdminRebuildZooms handles POST /map/api/admin/rebuildZooms.
|
||||
func (h *Handlers) APIAdminRebuildZooms(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -343,8 +337,7 @@ func (h *Handlers) APIAdminRebuildZooms(rw http.ResponseWriter, req *http.Reques
|
||||
|
||||
// APIAdminExport handles GET /map/api/admin/export.
|
||||
func (h *Handlers) APIAdminExport(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
@@ -359,8 +352,7 @@ func (h *Handlers) APIAdminExport(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIAdminMerge handles POST /map/api/admin/merge.
|
||||
func (h *Handlers) APIAdminMerge(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
if h.requireAdmin(rw, req) == nil {
|
||||
|
||||
@@ -31,8 +31,7 @@ type meUpdateRequest struct {
|
||||
|
||||
// APILogin handles POST /map/api/login.
|
||||
func (h *Handlers) APILogin(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
@@ -73,8 +72,7 @@ func (h *Handlers) APILogin(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APISetup handles GET /map/api/setup.
|
||||
func (h *Handlers) APISetup(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
JSON(rw, http.StatusOK, struct {
|
||||
@@ -84,8 +82,7 @@ func (h *Handlers) APISetup(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APILogout handles POST /map/api/logout.
|
||||
func (h *Handlers) APILogout(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
@@ -98,14 +95,12 @@ func (h *Handlers) APILogout(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIMe handles GET /map/api/me.
|
||||
func (h *Handlers) APIMe(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
out := meResponse{Username: s.Username, Auths: s.Auths}
|
||||
@@ -118,16 +113,14 @@ func (h *Handlers) APIMe(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIMeUpdate handles PATCH /map/api/me (update current user email).
|
||||
func (h *Handlers) APIMeUpdate(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPatch {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPatch) {
|
||||
return
|
||||
}
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
var body meUpdateRequest
|
||||
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
|
||||
JSONError(rw, http.StatusBadRequest, "bad request", "BAD_REQUEST")
|
||||
@@ -142,16 +135,14 @@ func (h *Handlers) APIMeUpdate(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIMeTokens handles POST /map/api/me/tokens.
|
||||
func (h *Handlers) APIMeTokens(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
if !s.Auths.Has(app.AUTH_UPLOAD) {
|
||||
JSONError(rw, http.StatusForbidden, "Forbidden", "FORBIDDEN")
|
||||
return
|
||||
@@ -166,16 +157,14 @@ func (h *Handlers) APIMeTokens(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIMePassword handles POST /map/api/me/password.
|
||||
func (h *Handlers) APIMePassword(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodPost) {
|
||||
return
|
||||
}
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
var body passwordRequest
|
||||
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
|
||||
JSONError(rw, http.StatusBadRequest, "bad request", "BAD_REQUEST")
|
||||
@@ -190,8 +179,7 @@ func (h *Handlers) APIMePassword(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIOAuthProviders handles GET /map/api/oauth/providers.
|
||||
func (h *Handlers) APIOAuthProviders(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
JSON(rw, http.StatusOK, services.OAuthProviders())
|
||||
@@ -199,8 +187,7 @@ func (h *Handlers) APIOAuthProviders(rw http.ResponseWriter, req *http.Request)
|
||||
|
||||
// APIOAuthLogin handles GET /map/api/oauth/:provider/login.
|
||||
func (h *Handlers) APIOAuthLogin(rw http.ResponseWriter, req *http.Request, provider string) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
redirect := req.URL.Query().Get("redirect")
|
||||
@@ -214,8 +201,7 @@ func (h *Handlers) APIOAuthLogin(rw http.ResponseWriter, req *http.Request, prov
|
||||
|
||||
// APIOAuthCallback handles GET /map/api/oauth/:provider/callback.
|
||||
func (h *Handlers) APIOAuthCallback(rw http.ResponseWriter, req *http.Request, provider string) {
|
||||
if req.Method != http.MethodGet {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
if !h.requireMethod(rw, req, http.MethodGet) {
|
||||
return
|
||||
}
|
||||
code := req.URL.Query().Get("code")
|
||||
|
||||
@@ -24,7 +24,7 @@ func (h *Handlers) ClientRouter(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
username, err := h.Auth.ValidateClientToken(ctx, matches[1])
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
HandleServiceError(rw, err)
|
||||
return
|
||||
}
|
||||
ctx = context.WithValue(ctx, app.ClientUsernameKey, username)
|
||||
@@ -47,10 +47,10 @@ func (h *Handlers) ClientRouter(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.FormValue("version") == app.ClientVersion {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusBadRequest)
|
||||
JSONError(rw, http.StatusBadRequest, "version mismatch", "BAD_REQUEST")
|
||||
}
|
||||
default:
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
JSONError(rw, http.StatusNotFound, "not found", "NOT_FOUND")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,11 @@ func (h *Handlers) clientLocate(rw http.ResponseWriter, req *http.Request) {
|
||||
gridID := req.FormValue("gridID")
|
||||
result, err := h.Client.Locate(req.Context(), gridID)
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
HandleServiceError(rw, err)
|
||||
return
|
||||
}
|
||||
rw.Header().Set("Content-Type", "text/plain")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write([]byte(result))
|
||||
}
|
||||
|
||||
@@ -75,8 +77,11 @@ func (h *Handlers) clientGridUpdate(rw http.ResponseWriter, req *http.Request) {
|
||||
result, err := h.Client.ProcessGridUpdate(req.Context(), grup)
|
||||
if err != nil {
|
||||
slog.Error("grid update failed", "error", err)
|
||||
HandleServiceError(rw, err)
|
||||
return
|
||||
}
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(rw).Encode(result.Response)
|
||||
}
|
||||
|
||||
@@ -87,6 +92,7 @@ func (h *Handlers) clientGridUpload(rw http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
if err := req.ParseMultipartForm(app.MultipartMaxMemory); err != nil {
|
||||
slog.Error("multipart parse error", "error", err)
|
||||
JSONError(rw, http.StatusBadRequest, "invalid multipart", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
id := req.FormValue("id")
|
||||
@@ -94,11 +100,13 @@ func (h *Handlers) clientGridUpload(rw http.ResponseWriter, req *http.Request) {
|
||||
file, _, err := req.FormFile("file")
|
||||
if err != nil {
|
||||
slog.Error("form file error", "error", err)
|
||||
JSONError(rw, http.StatusBadRequest, "missing file", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
if err := h.Client.ProcessGridUpload(req.Context(), id, extraData, file); err != nil {
|
||||
slog.Error("grid upload failed", "error", err)
|
||||
HandleServiceError(rw, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,10 +115,12 @@ func (h *Handlers) clientPositionUpdate(rw http.ResponseWriter, req *http.Reques
|
||||
buf, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
slog.Error("error reading position update", "error", err)
|
||||
JSONError(rw, http.StatusBadRequest, "failed to read body", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
if err := h.Client.UpdatePositions(req.Context(), buf); err != nil {
|
||||
slog.Error("position update failed", "error", err)
|
||||
HandleServiceError(rw, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +129,11 @@ func (h *Handlers) clientMarkerUpdate(rw http.ResponseWriter, req *http.Request)
|
||||
buf, err := io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
slog.Error("error reading marker update", "error", err)
|
||||
JSONError(rw, http.StatusBadRequest, "failed to read body", "BAD_REQUEST")
|
||||
return
|
||||
}
|
||||
if err := h.Client.UploadMarkers(req.Context(), buf); err != nil {
|
||||
slog.Error("marker update failed", "error", err)
|
||||
HandleServiceError(rw, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,25 @@ func New(
|
||||
}
|
||||
}
|
||||
|
||||
// requireMethod writes 405 and returns false if req.Method != method; otherwise returns true.
|
||||
func (h *Handlers) requireMethod(rw http.ResponseWriter, req *http.Request, method string) bool {
|
||||
if req.Method != method {
|
||||
JSONError(rw, http.StatusMethodNotAllowed, "method not allowed", "METHOD_NOT_ALLOWED")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// requireSession returns session or writes 401 and returns nil.
|
||||
func (h *Handlers) requireSession(rw http.ResponseWriter, req *http.Request) *app.Session {
|
||||
s := h.Auth.GetSession(req.Context(), req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// requireAdmin returns session if admin, or writes 401 and returns nil.
|
||||
func (h *Handlers) requireAdmin(rw http.ResponseWriter, req *http.Request) *app.Session {
|
||||
s := h.Auth.GetSession(req.Context(), req)
|
||||
|
||||
@@ -601,3 +601,79 @@ func TestAdminUserDelete(t *testing.T) {
|
||||
t.Fatalf("expected 200, got %d", rr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRouter_Locate(t *testing.T) {
|
||||
env := newTestEnv(t)
|
||||
env.createUser(t, "alice", "pass", app.Auths{app.AUTH_UPLOAD})
|
||||
ctx := context.Background()
|
||||
tokens := env.auth.GenerateTokenForUser(ctx, "alice")
|
||||
if len(tokens) == 0 {
|
||||
t.Fatal("expected token")
|
||||
}
|
||||
gd := app.GridData{ID: "g1", Map: 1, Coord: app.Coord{X: 2, Y: 3}}
|
||||
raw, _ := json.Marshal(gd)
|
||||
env.st.Update(ctx, func(tx *bbolt.Tx) error {
|
||||
return env.st.PutGrid(tx, "g1", raw)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/client/"+tokens[0]+"/locate?gridID=g1", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
env.h.ClientRouter(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", rr.Code, rr.Body.String())
|
||||
}
|
||||
if body := strings.TrimSpace(rr.Body.String()); body != "1;2;3" {
|
||||
t.Fatalf("expected body 1;2;3, got %q", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRouter_Locate_NotFound(t *testing.T) {
|
||||
env := newTestEnv(t)
|
||||
env.createUser(t, "alice", "pass", app.Auths{app.AUTH_UPLOAD})
|
||||
tokens := env.auth.GenerateTokenForUser(context.Background(), "alice")
|
||||
if len(tokens) == 0 {
|
||||
t.Fatal("expected token")
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/client/"+tokens[0]+"/locate?gridID=ghost", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
env.h.ClientRouter(rr, req)
|
||||
|
||||
if rr.Code != http.StatusNotFound {
|
||||
t.Fatalf("expected 404, got %d", rr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRouter_CheckVersion(t *testing.T) {
|
||||
env := newTestEnv(t)
|
||||
env.createUser(t, "alice", "pass", app.Auths{app.AUTH_UPLOAD})
|
||||
tokens := env.auth.GenerateTokenForUser(context.Background(), "alice")
|
||||
if len(tokens) == 0 {
|
||||
t.Fatal("expected token")
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/client/"+tokens[0]+"/checkVersion?version="+app.ClientVersion, nil)
|
||||
rr := httptest.NewRecorder()
|
||||
env.h.ClientRouter(rr, req)
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200 for matching version, got %d", rr.Code)
|
||||
}
|
||||
|
||||
req2 := httptest.NewRequest(http.MethodGet, "/client/"+tokens[0]+"/checkVersion?version=other", nil)
|
||||
rr2 := httptest.NewRecorder()
|
||||
env.h.ClientRouter(rr2, req2)
|
||||
if rr2.Code != http.StatusBadRequest {
|
||||
t.Fatalf("expected 400 for wrong version, got %d", rr2.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRouter_InvalidToken(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, "/client/badtoken/locate?gridID=g1", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
env := newTestEnv(t)
|
||||
env.h.ClientRouter(rr, req)
|
||||
if rr.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("expected 401, got %d", rr.Code)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ import (
|
||||
|
||||
// APIConfig handles GET /map/api/config.
|
||||
func (h *Handlers) APIConfig(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
config, err := h.Map.GetConfig(ctx, s.Auths)
|
||||
if err != nil {
|
||||
HandleServiceError(rw, err)
|
||||
@@ -36,8 +35,10 @@ type CharacterResponse struct {
|
||||
|
||||
// APIGetChars handles GET /map/api/v1/characters.
|
||||
func (h *Handlers) APIGetChars(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
if !h.canAccessMap(s) {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
@@ -64,12 +65,15 @@ func (h *Handlers) APIGetChars(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// APIGetMarkers handles GET /map/api/v1/markers.
|
||||
func (h *Handlers) APIGetMarkers(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
s := h.Auth.GetSession(ctx, req)
|
||||
s := h.requireSession(rw, req)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
if !h.canAccessMap(s) {
|
||||
JSONError(rw, http.StatusUnauthorized, "Unauthorized", "UNAUTHORIZED")
|
||||
return
|
||||
}
|
||||
ctx := req.Context()
|
||||
if !s.Auths.Has(app.AUTH_MARKERS) && !s.Auths.Has(app.AUTH_ADMIN) {
|
||||
JSON(rw, http.StatusOK, []interface{}{})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user