From 99cddf1fd68735670779b9ec8b54d00b28412fe0 Mon Sep 17 00:00:00 2001 From: Ruben Hensen Date: Mon, 7 Apr 2025 16:22:56 +0200 Subject: [PATCH] feat: allow accounts with a quota of 0 GiB (#17413) * Allow 0GiB quotas in user create/edit form, remove unused translations * Make requireQuota check for null or 0 * Add unlimited quota change to the docs * Fix user dto formatting * Fix formating edit-user-form * Regenerate open-api files * Revert unnecessary i18n file changes * Re-add newline en.json * Resolve linting issues * Fix formatting edit-user-form * Re-add manifest --- .../administration/img/user-quota-size.webp | Bin 11806 -> 15964 bytes docs/docs/administration/user-management.mdx | 2 +- i18n/en.json | 4 +--- .../lib/model/user_admin_create_dto.dart | 2 +- .../lib/model/user_admin_update_dto.dart | 2 +- open-api/immich-openapi-specs.json | 4 ++-- server/src/dtos/user.dto.ts | 6 +++--- server/src/services/asset-media.service.ts | 2 +- .../components/forms/create-user-form.svelte | 4 ++-- .../components/forms/edit-user-form.svelte | 15 +++++++++++---- .../routes/admin/user-management/+page.svelte | 2 +- 11 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/docs/administration/img/user-quota-size.webp b/docs/docs/administration/img/user-quota-size.webp index 9b5464ba3c5f69c3ef1d898246502374be25c9f0..2989bba392f4a20b38eac0c7a5d5b2b42d514086 100644 GIT binary patch literal 15964 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

~4dNR6+jaP-gt%X%Vu3N!%U1?4vv6c~wjZ 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\"", "notification_email_host_description": "Host of the email server (e.g. smtp.immich.app)", @@ -929,7 +928,6 @@ "no_shared_albums_message": "Create an album to share photos and videos with people in your network", "not_in_any_album": "Not in any album", "note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the", - "note_unlimited_quota": "Note: Enter 0 for unlimited quota", "notes": "Notes", "notification_toggle_setting_description": "Enable email notifications", "notifications": "Notifications", @@ -1384,4 +1382,4 @@ "yes": "Yes", "you_dont_have_any_shared_links": "You don't have any shared links", "zoom_image": "Zoom Image" -} \ No newline at end of file +} diff --git a/mobile/openapi/lib/model/user_admin_create_dto.dart b/mobile/openapi/lib/model/user_admin_create_dto.dart index f2709be57b..4bd1266426 100644 --- a/mobile/openapi/lib/model/user_admin_create_dto.dart +++ b/mobile/openapi/lib/model/user_admin_create_dto.dart @@ -36,7 +36,7 @@ class UserAdminCreateDto { String password; - /// Minimum value: 1 + /// Minimum value: 0 int? quotaSizeInBytes; /// diff --git a/mobile/openapi/lib/model/user_admin_update_dto.dart b/mobile/openapi/lib/model/user_admin_update_dto.dart index 6c6f73ae8e..f0478c9b4c 100644 --- a/mobile/openapi/lib/model/user_admin_update_dto.dart +++ b/mobile/openapi/lib/model/user_admin_update_dto.dart @@ -45,7 +45,7 @@ class UserAdminUpdateDto { /// String? password; - /// Minimum value: 1 + /// Minimum value: 0 int? quotaSizeInBytes; /// diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index ac30e9ae97..4e8e7ab834 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -13624,7 +13624,7 @@ }, "quotaSizeInBytes": { "format": "int64", - "minimum": 1, + "minimum": 0, "nullable": true, "type": "integer" }, @@ -13763,7 +13763,7 @@ }, "quotaSizeInBytes": { "format": "int64", - "minimum": 1, + "minimum": 0, "nullable": true, "type": "integer" }, diff --git a/server/src/dtos/user.dto.ts b/server/src/dtos/user.dto.ts index 0177e9b475..afcd13f0e9 100644 --- a/server/src/dtos/user.dto.ts +++ b/server/src/dtos/user.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; -import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator'; +import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsString, Min } from 'class-validator'; import { User, UserAdmin } from 'src/database'; import { UserMetadataEntity, UserMetadataItem } from 'src/entities/user-metadata.entity'; import { UserEntity } from 'src/entities/user.entity'; @@ -77,7 +77,7 @@ export class UserAdminCreateDto { @Optional({ nullable: true }) @IsNumber() - @IsPositive() + @Min(0) @ApiProperty({ type: 'integer', format: 'int64' }) quotaSizeInBytes?: number | null; @@ -115,7 +115,7 @@ export class UserAdminUpdateDto { @Optional({ nullable: true }) @IsNumber() - @IsPositive() + @Min(0) @ApiProperty({ type: 'integer', format: 'int64' }) quotaSizeInBytes?: number | null; } diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 747d7e4514..1b8a038b9c 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -435,7 +435,7 @@ export class AssetMediaService extends BaseService { } private requireQuota(auth: AuthDto, size: number) { - if (auth.user.quotaSizeInBytes && auth.user.quotaSizeInBytes < auth.user.quotaUsageInBytes + size) { + if (auth.user.quotaSizeInBytes !== null && auth.user.quotaSizeInBytes < auth.user.quotaUsageInBytes + size) { throw new BadRequestException('Quota has been exceeded!'); } } diff --git a/web/src/lib/components/forms/create-user-form.svelte b/web/src/lib/components/forms/create-user-form.svelte index 87de0a9068..83b3154d4b 100644 --- a/web/src/lib/components/forms/create-user-form.svelte +++ b/web/src/lib/components/forms/create-user-form.svelte @@ -30,7 +30,7 @@ let quotaSize: string | undefined = $state(); let isCreatingUser = $state(false); - let quotaSizeInBytes = $derived(quotaSize ? convertToBytes(Number(quotaSize), ByteUnit.GiB) : null); + let quotaSizeInBytes = $derived(quotaSize === null ? null : convertToBytes(Number(quotaSize), ByteUnit.GiB)); let quotaSizeWarning = $derived( quotaSizeInBytes && userInteraction.serverInfo && quotaSizeInBytes > userInteraction.serverInfo.diskSizeRaw, ); @@ -113,7 +113,7 @@ - + {#if quotaSizeWarning} {$t('errors.quota_higher_than_disk_size')} {/if} diff --git a/web/src/lib/components/forms/edit-user-form.svelte b/web/src/lib/components/forms/edit-user-form.svelte index 2802ad3ab2..ab914e6430 100644 --- a/web/src/lib/components/forms/edit-user-form.svelte +++ b/web/src/lib/components/forms/edit-user-form.svelte @@ -28,7 +28,7 @@ onEditSuccess, }: Props = $props(); - let quotaSize = $state(user.quotaSizeInBytes ? convertFromBytes(user.quotaSizeInBytes, ByteUnit.GiB) : null); + let quotaSize = $state(user.quotaSizeInBytes === null ? null : convertFromBytes(user.quotaSizeInBytes, ByteUnit.GiB)); const previousQutoa = user.quotaSizeInBytes; @@ -48,7 +48,7 @@ email, name, storageLabel: storageLabel || '', - quotaSizeInBytes: quotaSize ? convertToBytes(Number(quotaSize), ByteUnit.GiB) : null, + quotaSizeInBytes: quotaSize === null ? null : convertToBytes(Number(quotaSize), ByteUnit.GiB), }, }); @@ -126,8 +126,15 @@

{$t('errors.quota_higher_than_disk_size')}

{/if} - -

{$t('admin.note_unlimited_quota')}

+
diff --git a/web/src/routes/admin/user-management/+page.svelte b/web/src/routes/admin/user-management/+page.svelte index 9ec2e9eab1..0ca17c4ed8 100644 --- a/web/src/routes/admin/user-management/+page.svelte +++ b/web/src/routes/admin/user-management/+page.svelte @@ -209,7 +209,7 @@ {immichUser.name}
- {#if immichUser.quotaSizeInBytes && immichUser.quotaSizeInBytes > 0} + {#if immichUser.quotaSizeInBytes !== null && immichUser.quotaSizeInBytes >= 0} {getByteUnitString(immichUser.quotaSizeInBytes, $locale)} {:else}