feat(server, web): quotas (#4471)
* feat: quotas * chore: open api * chore: update status box and upload error message --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsEmail, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator';
|
||||
import { Optional, toEmail, toSanitized } from '../../domain.util';
|
||||
|
||||
export class CreateUserDto {
|
||||
@@ -27,6 +28,12 @@ export class CreateUserDto {
|
||||
@Optional()
|
||||
@IsBoolean()
|
||||
memoriesEnabled?: boolean;
|
||||
|
||||
@Optional({ nullable: true })
|
||||
@IsNumber()
|
||||
@IsPositive()
|
||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||
quotaSizeInBytes?: number | null;
|
||||
}
|
||||
|
||||
export class CreateAdminDto {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UserAvatarColor } from '@app/infra/entities';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsString, IsUUID } from 'class-validator';
|
||||
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator';
|
||||
import { Optional, toEmail, toSanitized } from '../../domain.util';
|
||||
|
||||
export class UpdateUserDto {
|
||||
@@ -50,4 +50,10 @@ export class UpdateUserDto {
|
||||
@IsEnum(UserAvatarColor)
|
||||
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||
avatarColor?: UserAvatarColor;
|
||||
|
||||
@Optional({ nullable: true })
|
||||
@IsNumber()
|
||||
@IsPositive()
|
||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||
quotaSizeInBytes?: number | null;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ export class UserResponseDto extends UserDto {
|
||||
updatedAt!: Date;
|
||||
oauthId!: string;
|
||||
memoriesEnabled?: boolean;
|
||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||
quotaSizeInBytes!: number | null;
|
||||
@ApiProperty({ type: 'integer', format: 'int64' })
|
||||
quotaUsageInBytes!: number;
|
||||
}
|
||||
|
||||
export const mapSimpleUser = (entity: UserEntity): UserDto => {
|
||||
@@ -57,5 +61,7 @@ export function mapUser(entity: UserEntity): UserResponseDto {
|
||||
updatedAt: entity.updatedAt,
|
||||
oauthId: entity.oauthId,
|
||||
memoriesEnabled: entity.memoriesEnabled,
|
||||
quotaSizeInBytes: entity.quotaSizeInBytes,
|
||||
quotaUsageInBytes: entity.quotaUsageInBytes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -512,4 +512,11 @@ describe(UserService.name, () => {
|
||||
expect(storageMock.unlinkDir).toHaveBeenCalledWith('upload/library/admin', options);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleUserSyncUsage', () => {
|
||||
it('should sync usage', async () => {
|
||||
await sut.handleUserSyncUsage();
|
||||
expect(userMock.syncUsage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -127,6 +127,11 @@ export class UserService {
|
||||
return { admin, password, provided: !!providedPassword };
|
||||
}
|
||||
|
||||
async handleUserSyncUsage() {
|
||||
await this.userRepository.syncUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
async handleUserDeleteCheck() {
|
||||
const users = await this.userRepository.getDeletedUsers();
|
||||
await this.jobRepository.queueAll(
|
||||
|
||||
Reference in New Issue
Block a user