Add staff password reset, raise code upload limit, and guard restore sizing.
Admins and technical staff can reset passwords via PATCH /users/:id/password with scoped permissions for technical users; deploy/source uploads allow up to 10GiB and block deploy when allocated storage is smaller than uploaded archive or DB dump, with an inline error modal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -70,7 +70,7 @@ export class ApplicationsController {
|
||||
@ApiOperation({ summary: 'Upload application code (zip file)' })
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file', {
|
||||
limits: { fileSize: 200 * 1024 * 1024 }, // 200MB (WordPress sites can be large)
|
||||
limits: { fileSize: 10 * 1024 * 1024 * 1024 }, // 10 GiB max application archive
|
||||
}))
|
||||
async uploadCode(
|
||||
@Param('id') id: string,
|
||||
|
||||
@@ -44,6 +44,13 @@ class UpdateRoleDto {
|
||||
role: UserRole;
|
||||
}
|
||||
|
||||
class AdminSetPasswordDto {
|
||||
@IsString()
|
||||
@MinLength(8)
|
||||
@MaxLength(64)
|
||||
password: string;
|
||||
}
|
||||
|
||||
@ApiTags('Users')
|
||||
@ApiBearerAuth()
|
||||
@Controller('users')
|
||||
@@ -77,6 +84,21 @@ export class UsersController {
|
||||
return this.usersService.adminCreate(dto);
|
||||
}
|
||||
|
||||
@Patch(':id/password')
|
||||
@Roles(UserRole.ADMIN, UserRole.TECHNICAL)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Set user password (Admin: any role; Technical: standard users only)',
|
||||
})
|
||||
async setPassword(
|
||||
@Request() req: { user: { role: UserRole } },
|
||||
@Param('id') id: string,
|
||||
@Body() dto: AdminSetPasswordDto,
|
||||
) {
|
||||
await this.usersService.setPasswordByStaff(req.user.role, id, dto.password);
|
||||
return { message: 'Password updated' };
|
||||
}
|
||||
|
||||
@Patch(':id/role')
|
||||
@Roles(UserRole.ADMIN)
|
||||
@ApiOperation({ summary: 'Update user role (Admin only)' })
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
|
||||
import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
ConflictException,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository, ILike } from 'typeorm';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
@@ -106,4 +111,25 @@ export class UsersService {
|
||||
async activate(id: string): Promise<void> {
|
||||
await this.usersRepository.update(id, { isActive: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Staff-set password: admins may reset anyone; technical staff only standard (user) accounts.
|
||||
*/
|
||||
async setPasswordByStaff(
|
||||
actorRole: UserRole,
|
||||
targetUserId: string,
|
||||
plainPassword: string,
|
||||
): Promise<void> {
|
||||
const user = await this.findById(targetUserId);
|
||||
if (!user) {
|
||||
throw new NotFoundException('User not found');
|
||||
}
|
||||
if (actorRole === UserRole.TECHNICAL && user.role !== UserRole.USER) {
|
||||
throw new ForbiddenException(
|
||||
'Technical staff can only reset passwords for standard (user) accounts',
|
||||
);
|
||||
}
|
||||
user.password = await bcrypt.hash(plainPassword, 12);
|
||||
await this.usersRepository.save(user);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user