Fix jwt-token
This commit is contained in:
@@ -467,4 +467,323 @@ router.get('/system/info', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/management/tenants/:tenantId/users - Create user in specific tenant
|
||||
*/
|
||||
router.post('/tenants/:tenantId/users', async (req, res) => {
|
||||
try {
|
||||
const { tenantId } = req.params;
|
||||
const userData = req.body;
|
||||
|
||||
// Verify tenant exists
|
||||
const tenant = await Tenant.findByPk(tenantId);
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Tenant not found'
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user already exists in this tenant
|
||||
const existingUser = await User.findOne({
|
||||
where: {
|
||||
username: userData.username,
|
||||
tenant_id: tenantId
|
||||
}
|
||||
});
|
||||
|
||||
if (existingUser) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'User already exists in this tenant'
|
||||
});
|
||||
}
|
||||
|
||||
// Hash password
|
||||
const bcrypt = require('bcryptjs');
|
||||
const hashedPassword = await bcrypt.hash(userData.password, 10);
|
||||
|
||||
// Create user with tenant association
|
||||
const user = await User.create({
|
||||
...userData,
|
||||
password: hashedPassword,
|
||||
tenant_id: tenantId,
|
||||
created_by: req.managementUser.username
|
||||
});
|
||||
|
||||
// Remove password from response
|
||||
const userResponse = user.toJSON();
|
||||
delete userResponse.password;
|
||||
|
||||
console.log(`Management: Admin ${req.managementUser.username} created user ${userData.username} in tenant ${tenant.name}`);
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
data: userResponse,
|
||||
message: 'User created successfully'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error creating user:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to create user',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* PUT /api/management/tenants/:tenantId/users/:userId - Update user in tenant
|
||||
*/
|
||||
router.put('/tenants/:tenantId/users/:userId', async (req, res) => {
|
||||
try {
|
||||
const { tenantId, userId } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: userId,
|
||||
tenant_id: tenantId
|
||||
},
|
||||
include: [{
|
||||
model: Tenant,
|
||||
as: 'tenant',
|
||||
attributes: ['name']
|
||||
}]
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'User not found in this tenant'
|
||||
});
|
||||
}
|
||||
|
||||
// Hash password if provided
|
||||
if (updates.password) {
|
||||
const bcrypt = require('bcryptjs');
|
||||
updates.password = await bcrypt.hash(updates.password, 10);
|
||||
}
|
||||
|
||||
await user.update(updates);
|
||||
|
||||
// Remove password from response
|
||||
const userResponse = user.toJSON();
|
||||
delete userResponse.password;
|
||||
|
||||
console.log(`Management: Admin ${req.managementUser.username} updated user ${user.username} in tenant ${user.tenant.name}`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: userResponse,
|
||||
message: 'User updated successfully'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error updating user:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to update user',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* DELETE /api/management/tenants/:tenantId/users/:userId - Delete user from tenant
|
||||
*/
|
||||
router.delete('/tenants/:tenantId/users/:userId', async (req, res) => {
|
||||
try {
|
||||
const { tenantId, userId } = req.params;
|
||||
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: userId,
|
||||
tenant_id: tenantId
|
||||
},
|
||||
include: [{
|
||||
model: Tenant,
|
||||
as: 'tenant',
|
||||
attributes: ['name']
|
||||
}]
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'User not found in this tenant'
|
||||
});
|
||||
}
|
||||
|
||||
// Prevent deleting the last admin user
|
||||
if (user.role === 'admin') {
|
||||
const adminCount = await User.count({
|
||||
where: {
|
||||
tenant_id: tenantId,
|
||||
role: 'admin'
|
||||
}
|
||||
});
|
||||
|
||||
if (adminCount <= 1) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: 'Cannot delete the last admin user in tenant'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Management: Admin ${req.managementUser.username} deleting user ${user.username} from tenant ${user.tenant.name}`);
|
||||
|
||||
await user.destroy();
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'User deleted successfully'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error deleting user:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to delete user',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/management/tenants/:tenantId/users - Get all users in a tenant
|
||||
*/
|
||||
router.get('/tenants/:tenantId/users', async (req, res) => {
|
||||
try {
|
||||
const { tenantId } = req.params;
|
||||
const { limit = 50, offset = 0, search, role } = req.query;
|
||||
|
||||
// Verify tenant exists
|
||||
const tenant = await Tenant.findByPk(tenantId);
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Tenant not found'
|
||||
});
|
||||
}
|
||||
|
||||
const whereClause = { tenant_id: tenantId };
|
||||
|
||||
if (search) {
|
||||
whereClause[Op.or] = [
|
||||
{ username: { [Op.iLike]: `%${search}%` } },
|
||||
{ email: { [Op.iLike]: `%${search}%` } },
|
||||
{ first_name: { [Op.iLike]: `%${search}%` } },
|
||||
{ last_name: { [Op.iLike]: `%${search}%` } }
|
||||
];
|
||||
}
|
||||
|
||||
if (role) {
|
||||
whereClause.role = role;
|
||||
}
|
||||
|
||||
const users = await User.findAndCountAll({
|
||||
where: whereClause,
|
||||
attributes: { exclude: ['password'] },
|
||||
limit: Math.min(parseInt(limit), 100),
|
||||
offset: parseInt(offset),
|
||||
order: [['created_at', 'DESC']]
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: users.rows,
|
||||
pagination: {
|
||||
total: users.count,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
pages: Math.ceil(users.count / parseInt(limit))
|
||||
},
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
slug: tenant.slug
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error fetching tenant users:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to fetch tenant users',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/management/tenants/:tenantId/activate - Activate tenant
|
||||
*/
|
||||
router.post('/tenants/:tenantId/activate', async (req, res) => {
|
||||
try {
|
||||
const { tenantId } = req.params;
|
||||
|
||||
const tenant = await Tenant.findByPk(tenantId);
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Tenant not found'
|
||||
});
|
||||
}
|
||||
|
||||
await tenant.update({ is_active: true });
|
||||
|
||||
console.log(`Management: Admin ${req.managementUser.username} activated tenant ${tenant.name}`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: tenant,
|
||||
message: 'Tenant activated successfully'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error activating tenant:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to activate tenant'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/management/tenants/:tenantId/deactivate - Deactivate tenant
|
||||
*/
|
||||
router.post('/tenants/:tenantId/deactivate', async (req, res) => {
|
||||
try {
|
||||
const { tenantId } = req.params;
|
||||
|
||||
const tenant = await Tenant.findByPk(tenantId);
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Tenant not found'
|
||||
});
|
||||
}
|
||||
|
||||
await tenant.update({ is_active: false });
|
||||
|
||||
console.log(`Management: Admin ${req.managementUser.username} deactivated tenant ${tenant.name}`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: tenant,
|
||||
message: 'Tenant deactivated successfully'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Management: Error deactivating tenant:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to deactivate tenant'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user