feat(auth,security,scheduling): JWT revocation, S3 fix, notes validation, docs, tests
- JWT revocation with JTI (UUID v4): in-memory tracking, POST /api/logout, refresh handler revokes old JTI, RequireAuth rejects revoked tokens - Fix extractKey for S3 portfolio deletion: extracts full key path from URLs instead of just filename, preventing orphaned storage files - Notes validation: max=1000000 on all 13 Notes fields across 4 booking structs - CharCounter: grapheme-aware counter (Intl.Segmenter), threshold 750K, color-coded, integrated into 6 booking/admin components - loginInProgress: timestamp-based tracking, 30s staleness, 20-entry cap (429), ticker cleanup for stuck entries - Profile picture 15MB client-side limit, portfolio 20MB backend limit - Exceptional scheduling: expand query start to Monday of week - TodayCalendar: week-range fetching, closing time indicator, short-day lunch skip - NavBar: link reorder, mobile burger badge, slide transition, backdrop - ImageUpload: 20MB limit with visual feedback - formatDateISO: shared YYYY-MM-DD utility, shouldApplyLunchProtection helper - Update README.md and all Obsidian docs (Overview, Technical, Admin, Future Work) - Add 28 new tests: JWT (11), auth handlers (7), portfolio extractKey (5), notes validation (5). go build + go vet clean with test,dev tags
This commit is contained in:
@@ -33,7 +33,7 @@ type Booking struct {
|
||||
ID string `json:"id"`
|
||||
StartTime time.Time `json:"start_time"`
|
||||
Status string `json:"status"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
CreatedBy *string `json:"created_by,omitempty"`
|
||||
@@ -111,7 +111,7 @@ type Payment struct {
|
||||
type CreateBookingRequest struct {
|
||||
StartTime time.Time `json:"start_time" validate:"required"`
|
||||
ServiceIDs []string `json:"service_ids" validate:"required,min=1"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
UserID *string `json:"user_id,omitempty"`
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ type ProgressBookingRequest struct {
|
||||
// ConfirmBookingRequest represents the request payload for confirming a booking
|
||||
type ConfirmBookingRequest struct {
|
||||
ServiceOverrides []ServiceOverride `json:"service_overrides,omitempty"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
}
|
||||
|
||||
// ServiceOverride represents override values for a specific service in a booking
|
||||
@@ -142,7 +142,7 @@ type ServiceOverride struct {
|
||||
type UpdateBookingServicesRequest struct {
|
||||
ServiceIDs []string `json:"service_ids"`
|
||||
ServiceOverrides []ServiceOverride `json:"service_overrides,omitempty"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
}
|
||||
|
||||
// DeleteBookingRequest represents the request payload for deleting a booking with payment
|
||||
@@ -155,7 +155,7 @@ type DeleteBookingRequest struct {
|
||||
type AdminUserSummary struct {
|
||||
FullName string `json:"full_name"`
|
||||
ProfilePicURL *string `json:"profile_pic_url,omitempty"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
}
|
||||
|
||||
// AdminBookingSummary represents a complete booking summary for admin view
|
||||
@@ -184,7 +184,7 @@ type UserSummary struct {
|
||||
ReferralCode *string `json:"referral_code,omitempty"`
|
||||
ReferralCodeUses *int `json:"referral_code_uses,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=1000000"`
|
||||
}
|
||||
|
||||
type BookingServiceDetail struct {
|
||||
|
||||
Reference in New Issue
Block a user