feat: Photo persistence and user creation
- Change STORAGE_PATH from /tmp to /app/photos - Add photos_data volume to docker-compose.yml for persistence - Add createUser controller with bcrypt password hashing - Add POST /users route for employee creation
This commit is contained in:
parent
3a62e94ad8
commit
7607dff622
4 changed files with 64 additions and 3 deletions
|
|
@ -57,3 +57,60 @@ export const updateUser = async (request: FastifyRequest, reply: FastifyReply) =
|
||||||
return reply.code(500).send({ message: 'Failed to update user' });
|
return reply.code(500).send({ message: 'Failed to update user' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createUser = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
|
const data = request.body as {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
name?: string;
|
||||||
|
role?: string;
|
||||||
|
roleId?: string;
|
||||||
|
rate?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (!data.email || !data.password) {
|
||||||
|
return reply.code(400).send({ message: 'Email and password are required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if user already exists
|
||||||
|
const existing = await request.server.prisma.user.findUnique({
|
||||||
|
where: { email: data.email }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
return reply.code(409).send({ message: 'User with this email already exists' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash password with bcrypt
|
||||||
|
const bcrypt = await import('bcrypt');
|
||||||
|
const hashedPassword = await bcrypt.hash(data.password, 10);
|
||||||
|
|
||||||
|
// Create user
|
||||||
|
const user = await request.server.prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: data.email,
|
||||||
|
password: hashedPassword,
|
||||||
|
name: data.name || data.email.split('@')[0],
|
||||||
|
role: (data.role as any) || 'WORKER',
|
||||||
|
...(data.roleId && { roleId: data.roleId }),
|
||||||
|
...(data.rate !== undefined && { rate: data.rate }),
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
name: true,
|
||||||
|
role: true,
|
||||||
|
userRole: true,
|
||||||
|
rate: true,
|
||||||
|
createdAt: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply.code(201).send(user);
|
||||||
|
} catch (error) {
|
||||||
|
request.log.error(error);
|
||||||
|
return reply.code(500).send({ message: 'Failed to create user' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import path from 'path';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
|
|
||||||
// Storage base path - configurable via env
|
// Storage base path - uses mounted volume for persistence
|
||||||
const STORAGE_PATH = process.env.STORAGE_PATH || '/tmp/ca-grow-ops-manager/photos';
|
const STORAGE_PATH = process.env.STORAGE_PATH || '/app/photos';
|
||||||
|
|
||||||
// Image size configurations per spec
|
// Image size configurations per spec
|
||||||
const IMAGE_SIZES = {
|
const IMAGE_SIZES = {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { FastifyInstance } from 'fastify';
|
import { FastifyInstance } from 'fastify';
|
||||||
import { getUsers, updateUser } from '../controllers/users.controller';
|
import { getUsers, updateUser, createUser } from '../controllers/users.controller';
|
||||||
|
|
||||||
export async function userRoutes(server: FastifyInstance) {
|
export async function userRoutes(server: FastifyInstance) {
|
||||||
server.get('/', getUsers);
|
server.get('/', getUsers);
|
||||||
|
server.post('/', createUser);
|
||||||
server.patch('/:id', updateUser);
|
server.patch('/:id', updateUser);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ services:
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 40s
|
start_period: 40s
|
||||||
|
volumes:
|
||||||
|
- photos_data:/app/photos
|
||||||
|
|
||||||
go2rtc:
|
go2rtc:
|
||||||
image: alexxit/go2rtc:latest
|
image: alexxit/go2rtc:latest
|
||||||
|
|
@ -121,3 +123,4 @@ networks:
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
|
photos_data:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue