Convert user and role IDs from number to UUID string
Updated backend and frontend to use UUID strings instead of integers for user and role IDs to match PostgreSQL database schema (UUID type). Backend changes: - Updated User and UserPublic interfaces: id and role_id now string (UUID) - Updated JwtPayload: userId and roleId now string - Updated user validators: role_id validation changed from number to UUID string - Removed parseInt() calls in user controller (getUserById, updateUser, deleteUser, changePassword) - Updated all user service function signatures to accept string IDs - Updated create() and update() functions to accept role_id as string Frontend changes: - Updated User interface in users API: role_id is string - Updated CreateUserInput and UpdateUserInput: role_id is string - Added role filter in UsersPage sidebar - Removed number conversion logic (parseInt) This fixes the "invalid input syntax for type uuid" error when creating/updating users.
This commit is contained in:
@@ -67,9 +67,9 @@ export async function getUserById(
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const userId = parseInt(req.params.id, 10);
|
||||
const userId = req.params.id;
|
||||
|
||||
if (isNaN(userId)) {
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid user ID',
|
||||
@@ -80,7 +80,7 @@ export async function getUserById(
|
||||
// Check if user is admin or requesting their own data
|
||||
const requestingUser = req.user;
|
||||
const isAdmin = requestingUser?.role === 'ADMIN';
|
||||
const isSelf = requestingUser?.id === userId.toString();
|
||||
const isSelf = requestingUser?.id === userId;
|
||||
|
||||
if (!isAdmin && !isSelf) {
|
||||
res.status(403).json({
|
||||
@@ -166,9 +166,9 @@ export async function updateUser(
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const userId = parseInt(req.params.id, 10);
|
||||
const userId = req.params.id;
|
||||
|
||||
if (isNaN(userId)) {
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid user ID',
|
||||
@@ -178,7 +178,7 @@ export async function updateUser(
|
||||
|
||||
const requestingUser = req.user;
|
||||
const isAdmin = requestingUser?.role === 'ADMIN';
|
||||
const isSelf = requestingUser?.id === userId.toString();
|
||||
const isSelf = requestingUser?.id === userId;
|
||||
|
||||
if (!isAdmin && !isSelf) {
|
||||
res.status(403).json({
|
||||
@@ -243,9 +243,9 @@ export async function deleteUser(
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const userId = parseInt(req.params.id, 10);
|
||||
const userId = req.params.id;
|
||||
|
||||
if (isNaN(userId)) {
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid user ID',
|
||||
@@ -254,7 +254,7 @@ export async function deleteUser(
|
||||
}
|
||||
|
||||
// Prevent admin from deleting themselves
|
||||
if (req.user?.id === userId.toString()) {
|
||||
if (req.user?.id === userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Cannot deactivate your own account',
|
||||
@@ -294,9 +294,9 @@ export async function changePassword(
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const userId = parseInt(req.params.id, 10);
|
||||
const userId = req.params.id;
|
||||
|
||||
if (isNaN(userId)) {
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid user ID',
|
||||
@@ -305,7 +305,7 @@ export async function changePassword(
|
||||
}
|
||||
|
||||
// Only allow users to change their own password
|
||||
if (req.user?.id !== userId.toString()) {
|
||||
if (req.user?.id !== userId) {
|
||||
res.status(403).json({
|
||||
success: false,
|
||||
error: 'You can only change your own password',
|
||||
|
||||
@@ -148,7 +148,7 @@ export async function getAll(
|
||||
* @param id - User ID
|
||||
* @returns User without password_hash or null if not found
|
||||
*/
|
||||
export async function getById(id: number): Promise<UserPublic | null> {
|
||||
export async function getById(id: string): Promise<UserPublic | null> {
|
||||
const result = await query(
|
||||
`
|
||||
SELECT
|
||||
@@ -234,7 +234,7 @@ export async function create(data: {
|
||||
password: string;
|
||||
name: string;
|
||||
avatar_url?: string | null;
|
||||
role_id: number;
|
||||
role_id: string;
|
||||
is_active?: boolean;
|
||||
}): Promise<UserPublic> {
|
||||
// Check if email already exists
|
||||
@@ -275,12 +275,12 @@ export async function create(data: {
|
||||
* @returns Updated user without password_hash
|
||||
*/
|
||||
export async function update(
|
||||
id: number,
|
||||
id: string,
|
||||
data: {
|
||||
email?: string;
|
||||
name?: string;
|
||||
avatar_url?: string | null;
|
||||
role_id?: number;
|
||||
role_id?: string;
|
||||
is_active?: boolean;
|
||||
}
|
||||
): Promise<UserPublic | null> {
|
||||
@@ -357,7 +357,7 @@ export async function update(
|
||||
* @param id - User ID
|
||||
* @returns True if deleted, false if user not found
|
||||
*/
|
||||
export async function deleteUser(id: number): Promise<boolean> {
|
||||
export async function deleteUser(id: string): Promise<boolean> {
|
||||
const result = await query(
|
||||
`
|
||||
UPDATE users
|
||||
@@ -379,7 +379,7 @@ export async function deleteUser(id: number): Promise<boolean> {
|
||||
* @returns True if password changed, throws error if verification fails
|
||||
*/
|
||||
export async function changePassword(
|
||||
id: number,
|
||||
id: string,
|
||||
currentPassword: string,
|
||||
newPassword: string
|
||||
): Promise<boolean> {
|
||||
@@ -421,7 +421,7 @@ export async function changePassword(
|
||||
* @param id - User ID
|
||||
* @returns True if updated, false if user not found
|
||||
*/
|
||||
export async function updateLastLogin(id: number): Promise<boolean> {
|
||||
export async function updateLastLogin(id: string): Promise<boolean> {
|
||||
const result = await query(
|
||||
`
|
||||
UPDATE users
|
||||
|
||||
@@ -23,12 +23,12 @@ export interface Role {
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: number;
|
||||
id: string;
|
||||
email: string;
|
||||
password_hash: string;
|
||||
name: string;
|
||||
avatar_url: string | null;
|
||||
role_id: number;
|
||||
role_id: string;
|
||||
role?: Role;
|
||||
is_active: boolean;
|
||||
last_login: Date | null;
|
||||
@@ -37,11 +37,11 @@ export interface User {
|
||||
}
|
||||
|
||||
export interface UserPublic {
|
||||
id: number;
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
avatar_url: string | null;
|
||||
role_id: number;
|
||||
role_id: string;
|
||||
role?: Role;
|
||||
is_active: boolean;
|
||||
last_login: Date | null;
|
||||
@@ -50,9 +50,9 @@ export interface UserPublic {
|
||||
}
|
||||
|
||||
export interface JwtPayload {
|
||||
userId: number;
|
||||
userId: string;
|
||||
email: string;
|
||||
roleId: number;
|
||||
roleId: string;
|
||||
roleName: string;
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
|
||||
@@ -28,9 +28,8 @@ export const createUserSchema = z.object({
|
||||
.optional()
|
||||
.nullable(),
|
||||
role_id: z
|
||||
.number({ required_error: 'Role ID is required' })
|
||||
.int('Role ID must be an integer')
|
||||
.positive('Role ID must be a positive number'),
|
||||
.string({ required_error: 'Role ID is required' })
|
||||
.uuid('Role ID must be a valid UUID'),
|
||||
is_active: z.boolean().default(true),
|
||||
});
|
||||
|
||||
@@ -56,9 +55,8 @@ export const updateUserSchema = z.object({
|
||||
.optional()
|
||||
.nullable(),
|
||||
role_id: z
|
||||
.number()
|
||||
.int('Role ID must be an integer')
|
||||
.positive('Role ID must be a positive number')
|
||||
.string()
|
||||
.uuid('Role ID must be a valid UUID')
|
||||
.optional(),
|
||||
is_active: z.boolean().optional(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user