initialize git, basic setup for crm

This commit is contained in:
richardtekula
2025-11-18 13:53:28 +01:00
commit da01d586fc
47 changed files with 12776 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
import { db } from '../config/database.js';
import { users } from '../db/schema.js';
import { eq } from 'drizzle-orm';
import { hashPassword, generateTempPassword } from '../utils/password.js';
import { logUserCreation, logRoleChange } from '../services/audit.service.js';
import { formatErrorResponse, ConflictError, NotFoundError } from '../utils/errors.js';
/**
* Vytvorenie nového usera s temporary password (admin only)
* POST /api/admin/users
*/
export const createUser = async (req, res) => {
const { username, tempPassword, role, firstName, lastName } = req.body;
const adminId = req.userId;
const ipAddress = req.ip || req.connection.remoteAddress;
const userAgent = req.headers['user-agent'];
try {
// Skontroluj či username už neexistuje
const [existingUser] = await db
.select()
.from(users)
.where(eq(users.username, username))
.limit(1);
if (existingUser) {
throw new ConflictError('Username už existuje');
}
// Hash temporary password
const hashedTempPassword = await hashPassword(tempPassword);
// Vytvor usera
const [newUser] = await db
.insert(users)
.values({
username,
tempPassword: hashedTempPassword,
role: role || 'member',
firstName: firstName || null,
lastName: lastName || null,
changedPassword: false,
})
.returning();
// Log user creation
await logUserCreation(adminId, newUser.id, username, role || 'member', ipAddress, userAgent);
res.status(201).json({
success: true,
data: {
user: {
id: newUser.id,
username: newUser.username,
role: newUser.role,
tempPassword: tempPassword, // Vráti plain text password pre admina
},
},
message: 'Používateľ úspešne vytvorený',
});
} catch (error) {
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
res.status(error.statusCode || 500).json(errorResponse);
}
};
/**
* Zoznam všetkých userov (admin only)
* GET /api/admin/users
*/
export const getAllUsers = async (req, res) => {
try {
const allUsers = await db
.select({
id: users.id,
username: users.username,
email: users.email,
firstName: users.firstName,
lastName: users.lastName,
role: users.role,
changedPassword: users.changedPassword,
lastLogin: users.lastLogin,
createdAt: users.createdAt,
})
.from(users);
res.status(200).json({
success: true,
data: {
users: allUsers,
count: allUsers.length,
},
});
} catch (error) {
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
res.status(error.statusCode || 500).json(errorResponse);
}
};
/**
* Získanie konkrétneho usera (admin only)
* GET /api/admin/users/:userId
*/
export const getUserById = async (req, res) => {
const { userId } = req.params;
try {
const [user] = await db
.select({
id: users.id,
username: users.username,
email: users.email,
firstName: users.firstName,
lastName: users.lastName,
role: users.role,
changedPassword: users.changedPassword,
lastLogin: users.lastLogin,
createdAt: users.createdAt,
updatedAt: users.updatedAt,
})
.from(users)
.where(eq(users.id, userId))
.limit(1);
if (!user) {
throw new NotFoundError('Používateľ nenájdený');
}
res.status(200).json({
success: true,
data: { user },
});
} catch (error) {
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
res.status(error.statusCode || 500).json(errorResponse);
}
};
/**
* Zmena role usera (admin only)
* PATCH /api/admin/users/:userId/role
*/
export const changeUserRole = async (req, res) => {
const { userId } = req.params;
const { role } = req.body;
const adminId = req.userId;
const ipAddress = req.ip || req.connection.remoteAddress;
const userAgent = req.headers['user-agent'];
try {
// Získaj starú rolu
const [user] = await db
.select()
.from(users)
.where(eq(users.id, userId))
.limit(1);
if (!user) {
throw new NotFoundError('Používateľ nenájdený');
}
const oldRole = user.role;
// Update role
await db
.update(users)
.set({
role,
updatedAt: new Date(),
})
.where(eq(users.id, userId));
// Log role change
await logRoleChange(adminId, userId, oldRole, role, ipAddress, userAgent);
res.status(200).json({
success: true,
data: {
userId,
oldRole,
newRole: role,
},
message: 'Rola používateľa bola zmenená',
});
} catch (error) {
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
res.status(error.statusCode || 500).json(errorResponse);
}
};
/**
* Zmazanie usera (admin only)
* DELETE /api/admin/users/:userId
*/
export const deleteUser = async (req, res) => {
const { userId } = req.params;
try {
const [user] = await db
.select()
.from(users)
.where(eq(users.id, userId))
.limit(1);
if (!user) {
throw new NotFoundError('Používateľ nenájdený');
}
// Zabraň zmazaniu posledného admina
if (user.role === 'admin') {
const [adminCount] = await db
.select({ count: db.$count(users) })
.from(users)
.where(eq(users.role, 'admin'));
if (adminCount.count <= 1) {
throw new ConflictError('Nemôžete zmazať posledného administrátora');
}
}
await db.delete(users).where(eq(users.id, userId));
res.status(200).json({
success: true,
message: 'Používateľ bol zmazaný',
});
} catch (error) {
const errorResponse = formatErrorResponse(error, process.env.NODE_ENV === 'development');
res.status(error.statusCode || 500).json(errorResponse);
}
};