diff --git a/backend/internal/user/model.go b/backend/internal/user/model.go index d469996..7b76d4a 100644 --- a/backend/internal/user/model.go +++ b/backend/internal/user/model.go @@ -8,7 +8,7 @@ import ( ) type User struct { - ID int `json:"id" gorm:"primaryKey"` + ID int `gorm:"primaryKey"` Email string `json:"email" gorm:"uniqueIndex;size:255"` Name string `json:"name" gorm:"size:255"` Password string `json:"-" gorm:"size:255"` @@ -20,9 +20,9 @@ type User struct { Details *UserDetails `json:"details" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` Preferences *UserPreferences `json:"preferences" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` Avatar *string `json:"avatar" gorm:"size:512"` - CreatedAt *time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` - DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ts:"type=Nullable"` + CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` + DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ` } // UserTypes is stored as JSON array (e.g. ["internal","external"]). @@ -41,8 +41,8 @@ type UserProfile struct { Details *UserDetails `json:"details"` Preferences *UserPreferences `json:"preferences"` Avatar *string `json:"avatar"` - CreatedAt *time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` + CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` } // ToUserProfile maps a User to a full response without exposing the password hash. @@ -80,8 +80,8 @@ type UserPreferences struct { UseQuadcodeLogin bool `json:"useQuadcodeLogin"` SendNoticesMail bool `json:"sendNoticesMail"` Language string `json:"language"` - CreatedAt *time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` + CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` } // UserDetails holds optional profile data. @@ -97,8 +97,8 @@ type UserDetails struct { ZipCode string `json:"zipCode"` Country string `json:"country"` Phone string `json:"phone"` - CreatedAt *time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` + CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` } // UserDetails holds optional profile data. @@ -114,8 +114,8 @@ type Session struct { ExpiresAt time.Time `json:"expiresAt" ts:"type=Nullable" gorm:"index"` IPAddress string `json:"ipAddress" gorm:"size:64"` UserAgent string `json:"userAgent" gorm:"size:512"` - CreatedAt time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` + CreatedAt time.Time `json:"createdAt,omitempty" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ` } @@ -123,10 +123,10 @@ type PasswordResetToken struct { ID int `json:"id" gorm:"primaryKey"` UserID int `json:"userId" gorm:"index"` TokenHash string `json:"-" gorm:"size:64;uniqueIndex"` - ExpiresAt time.Time `json:"expiresAt" ts:"type=Nullable" gorm:"index"` - UsedAt *time.Time `json:"usedAt" ts:"type=Nullable"` - CreatedAt *time.Time `json:"createdAt" ts:"type=Nullable"` - UpdatedAt *time.Time `json:"updatedAt" ts:"type=Nullable"` + ExpiresAt time.Time `json:"expiresAt,omitempty" ts:"type=Date" gorm:"index"` + UsedAt *time.Time `json:"usedAt,omitempty" ts:"type=Date"` + CreatedAt *time.Time `json:"createdAt" ts:"type=Date"` + UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"` } @@ -170,9 +170,9 @@ type UpdateUserRequest struct { Permission auth.Permission `json:"permission"` Status UserStatus `json:"status"` Types UserTypes `json:"types"` - Avatar *string `json:"avatar"` - Details *UserDetails `json:"details"` - Preferences *UserPreferences `json:"preferences"` + Avatar *string `json:"avatar,omitempty"` + Details *UserDetails `json:"details,omitempty"` + Preferences *UserPreferences `json:"preferences,omitempty"` } // UserCreateRequest captures the minimal payload to create a user. @@ -184,7 +184,7 @@ type UserCreateRequest struct { Permission auth.Permission `json:"permission"` Status UserStatus `json:"status"` Types UserTypes `json:"types"` - Avatar *string `json:"avatar"` - Details *UserDetails `json:"details" ` - Preferences *UserPreferences `json:"preferences" ` + Avatar *string `json:"avatar,omitempty"` + Details *UserDetails `json:"details,omitempty"` + Preferences *UserPreferences `json:"preferences,omitempty"` } diff --git a/frontend/src/api/admin.ts b/frontend/src/api/admin.ts index 09f9cc5..89fb1ee 100644 --- a/frontend/src/api/admin.ts +++ b/frontend/src/api/admin.ts @@ -26,11 +26,6 @@ export const listUsers = async ( }; }; -export interface ListUsersRequest { - page: number; - pageSize: number; -} - export interface ListUsersResponse { items: users.User[]; page: number; @@ -41,3 +36,8 @@ export interface BlockUserRequest { uuid: string; action: string; } + +export interface ListUsersRequest { + page: number; + pageSize: number; +} diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts index ba8907a..8e12ec8 100644 --- a/frontend/src/api/api.ts +++ b/frontend/src/api/api.ts @@ -4,7 +4,7 @@ // // This file was generated by github.com/millevolte/ts-rpc // -// May 04, 2026 16:09:10 UTC +// May 05, 2026 14:14:16 UTC // export interface ApiRestResponse { diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index 4b8e49e..c951d35 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -1,5 +1,5 @@ import { api } from "./api"; -import type { Record, Nullable } from "./apiTypes.ts"; +import type { Nullable, Record } from "./apiTypes.ts"; // Typescript: TSEndpoint= path=/api/roles; name=getRoles; method=GET; response=auth.AllRoles @@ -13,13 +13,13 @@ export const getRoles = async (): Promise<{ error: Nullable; }; }; +export type EnumPermission = + (typeof EnumEnumPermission)[keyof typeof EnumEnumPermission]; + export type Permission = string; export type AllRoles = Record; -export type EnumPermission = - (typeof EnumEnumPermission)[keyof typeof EnumEnumPermission]; - export const EnumEnumPermission = { RoleSuperAdmin: "superadmin", RoleAdmin: "admin", diff --git a/frontend/src/api/users.ts b/frontend/src/api/users.ts index 5307ff0..0fdf12a 100644 --- a/frontend/src/api/users.ts +++ b/frontend/src/api/users.ts @@ -1,68 +1,8 @@ import { api } from "./api"; import type { Nullable } from "./apiTypes.ts"; +import type * as auth from "./auth.ts"; import type * as responses from "./responses.ts"; import type * as tokens from "./tokens.ts"; -import type * as auth from "./auth.ts"; - -// Typescript: TSEndpoint= path=/api/users; name=createUser; method=POST; request=users.UserCreateRequest; response=users.User - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 31 -export const createUser = async ( - data: UserCreateRequest, -): Promise<{ data: User; error: Nullable }> => { - return (await api.POST("/api/users", data)) as { - data: User; - error: Nullable; - }; -}; - -// Typescript: TSEndpoint= path=/api/auth/password/update; name=updatePassword; method=PUT; request=users.UpdatePasswordRequest; response=responses.SimpleResponse - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 61 -export const updatePassword = async ( - data: UpdatePasswordRequest, -): Promise<{ data: responses.SimpleResponse; error: Nullable }> => { - return (await api.PUT("/api/auth/password/update", data)) as { - data: responses.SimpleResponse; - error: Nullable; - }; -}; - -// Typescript: TSEndpoint= path=/api/users/:uuid; name=getUser; method=GET; response=users.User - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 28 -export const getUser = async ( - uuid: string, -): Promise<{ data: User; error: Nullable }> => { - return (await api.GET(`/api/users/${uuid}`)) as { - data: User; - error: Nullable; - }; -}; - -// Typescript: TSEndpoint= path=/api/users/:uuid; name=deleteUser; method=DELETE; response=responses.SimpleResponse - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 37 -export const deleteUser = async ( - uuid: string, -): Promise<{ data: responses.SimpleResponse; error: Nullable }> => { - return (await api.DELETE(`/api/users/${uuid}`)) as { - data: responses.SimpleResponse; - error: Nullable; - }; -}; - -// Typescript: TSEndpoint= path=/api/auth/login; name=login; method=POST; request=users.LoginRequest; response=tokens.TokenPair - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 43 -export const login = async ( - data: LoginRequest, -): Promise<{ data: tokens.TokenPair; error: Nullable }> => { - return (await api.POST("/api/auth/login", data)) as { - data: tokens.TokenPair; - error: Nullable; - }; -}; // Typescript: TSEndpoint= path=/api/auth/password/reset; name=resetPassword; method=POST; request=users.ResetPasswordRequest; response=responses.SimpleResponse @@ -76,30 +16,6 @@ export const resetPassword = async ( }; }; -// Typescript: TSEndpoint= path=/api/users/update; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 34 -export const updateUser = async ( - data: UpdateUserRequest, -): Promise<{ data: User; error: Nullable }> => { - return (await api.PUT("/api/users/update", data)) as { - data: User; - error: Nullable; - }; -}; - -// Typescript: TSEndpoint= path=/api/auth/register; name=register; method=POST; request=users.UserCreateRequest; response=users.User - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 49 -export const register = async ( - data: UserCreateRequest, -): Promise<{ data: User; error: Nullable }> => { - return (await api.POST("/api/auth/register", data)) as { - data: User; - error: Nullable; - }; -}; - // Typescript: TSEndpoint= path=/api/auth/password/valid; name=validToken; method=POST; request=string; response=responses.SimpleResponse // /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 58 @@ -125,18 +41,6 @@ export const me = async (): Promise<{ }; }; -// Typescript: TSEndpoint= path=/api/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair - -// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 46 -export const refresh = async ( - data: RefreshRequest, -): Promise<{ data: tokens.TokenPair; error: Nullable }> => { - return (await api.POST("/api/auth/refresh", data)) as { - data: tokens.TokenPair; - error: Nullable; - }; -}; - // Typescript: TSEndpoint= path=/api/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse // /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 52 @@ -149,27 +53,101 @@ export const forgotPassword = async ( }; }; -export interface ResetPasswordRequest { - token: string; - password: string; -} +// Typescript: TSEndpoint= path=/api/auth/password/update; name=updatePassword; method=PUT; request=users.UpdatePasswordRequest; response=responses.SimpleResponse -export interface UpdateUserRequest { - uuid: string; - name: string; - email: string; - password: string; - permission: auth.Permission; - status: UserStatus; - types: UserTypes; - avatar: Nullable; - details: Nullable; - preferences: Nullable; -} +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 61 +export const updatePassword = async ( + data: UpdatePasswordRequest, +): Promise<{ data: responses.SimpleResponse; error: Nullable }> => { + return (await api.PUT("/api/auth/password/update", data)) as { + data: responses.SimpleResponse; + error: Nullable; + }; +}; -export interface UpdatePasswordRequest { - password: string; -} +// Typescript: TSEndpoint= path=/api/users/:uuid; name=getUser; method=GET; response=users.User + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 28 +export const getUser = async ( + uuid: string, +): Promise<{ data: User; error: Nullable }> => { + return (await api.GET(`/api/users/${uuid}`)) as { + data: User; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/users/update; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 34 +export const updateUser = async ( + data: UpdateUserRequest, +): Promise<{ data: User; error: Nullable }> => { + return (await api.PUT("/api/users/update", data)) as { + data: User; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/users/:uuid; name=deleteUser; method=DELETE; response=responses.SimpleResponse + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 37 +export const deleteUser = async ( + uuid: string, +): Promise<{ data: responses.SimpleResponse; error: Nullable }> => { + return (await api.DELETE(`/api/users/${uuid}`)) as { + data: responses.SimpleResponse; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/auth/login; name=login; method=POST; request=users.LoginRequest; response=tokens.TokenPair + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 43 +export const login = async ( + data: LoginRequest, +): Promise<{ data: tokens.TokenPair; error: Nullable }> => { + return (await api.POST("/api/auth/login", data)) as { + data: tokens.TokenPair; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/auth/register; name=register; method=POST; request=users.UserCreateRequest; response=users.User + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 49 +export const register = async ( + data: UserCreateRequest, +): Promise<{ data: User; error: Nullable }> => { + return (await api.POST("/api/auth/register", data)) as { + data: User; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/users; name=createUser; method=POST; request=users.UserCreateRequest; response=users.User + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 31 +export const createUser = async ( + data: UserCreateRequest, +): Promise<{ data: User; error: Nullable }> => { + return (await api.POST("/api/users", data)) as { + data: User; + error: Nullable; + }; +}; + +// Typescript: TSEndpoint= path=/api/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair + +// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 46 +export const refresh = async ( + data: RefreshRequest, +): Promise<{ data: tokens.TokenPair; error: Nullable }> => { + return (await api.POST("/api/auth/refresh", data)) as { + data: tokens.TokenPair; + error: Nullable; + }; +}; export interface UserCreateRequest { name: string; @@ -183,37 +161,6 @@ export interface UserCreateRequest { preferences: Nullable; } -export interface User { - id: number; - email: string; - name: string; - permission: auth.Permission; - types: UserTypes; - status: UserStatus; - activatedAt: Nullable; - uuid: string; - details: Nullable; - preferences: Nullable; - avatar: Nullable; - createdAt: Nullable; - updatedAt: Nullable; -} - -export interface UserDetails { - id: number; - userId: number; - title: string; - firstName: string; - lastName: string; - address: string; - city: string; - zipCode: string; - country: string; - phone: string; - createdAt: Nullable; - updatedAt: Nullable; -} - export interface UserPreferences { id: number; userId: number; @@ -229,8 +176,32 @@ export interface UserPreferences { updatedAt: Nullable; } -export interface ForgotPasswordRequest { - email: string; +export interface RefreshRequest { + refresh_token: string; +} + +export interface ResetPasswordRequest { + token: string; + password: string; +} + +export interface UpdatePasswordRequest { + password: string; +} + +export interface UserDetails { + id: number; + userId: number; + title: string; + firstName: string; + lastName: string; + address: string; + city: string; + zipCode: string; + country: string; + phone: string; + createdAt: Nullable; + updatedAt: Nullable; } export interface LoginRequest { @@ -238,8 +209,36 @@ export interface LoginRequest { password: string; } -export interface RefreshRequest { - refresh_token: string; +export interface UpdateUserRequest { + uuid: string; + name: string; + email: string; + password: string; + permission: auth.Permission; + status: UserStatus; + types: UserTypes; + avatar: Nullable; + details: Nullable; + preferences: Nullable; +} + +export interface User { + email: string; + name: string; + permission: auth.Permission; + types: UserTypes; + status: UserStatus; + activatedAt: Nullable; + uuid: string; + details: Nullable; + preferences: Nullable; + avatar: Nullable; + createdAt?: Date; + updatedAt?: Date; +} + +export interface ForgotPasswordRequest { + email: string; } export type UserStatus = string;