From 45ca2fde06263217c51a081177c3f610e91c48db Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Mon, 10 Nov 2025 12:39:41 +0330 Subject: [PATCH] user --- package-lock.json | 19 +- package.json | 4 +- src/app.module.ts | 4 +- src/common/entities/base.entity.ts | 21 + src/common/enums/message.enum.ts | 998 +++++++++--------- src/modules/admin/entities/role.entity.ts | 14 + src/modules/auth/auth.controller.ts | 2 +- src/modules/auth/auth.module.ts | 4 +- .../auth}/guards/auth.admin.guard.ts | 0 .../auth}/guards/auth.guard.ts | 0 src/modules/auth/interfaces/IToken-payload.ts | 15 + .../auth/{ => services}/auth.service.ts | 12 +- src/modules/auth/services/tokens.service.ts | 154 +++ .../submition/entities/submition.entity.ts | 2 +- src/modules/submition/submition.controller.ts | 4 +- src/modules/uploader/uploader.controller.ts | 2 +- src/modules/user/entities/user.entity.ts | 68 -- .../{user => users}/dto/find-user.dto.ts | 0 .../{user => users}/dto/update-user.dto.ts | 0 .../users/entities/refresh-token.entity.ts | 19 + src/modules/users/entities/user.entity.ts | 34 + .../{user => users}/user.controller.ts | 4 +- src/modules/{user => users}/user.module.ts | 0 src/modules/{user => users}/user.service.ts | 0 24 files changed, 794 insertions(+), 586 deletions(-) create mode 100755 src/common/entities/base.entity.ts create mode 100644 src/modules/admin/entities/role.entity.ts rename src/{common => modules/auth}/guards/auth.admin.guard.ts (100%) rename src/{common => modules/auth}/guards/auth.guard.ts (100%) create mode 100755 src/modules/auth/interfaces/IToken-payload.ts rename src/modules/auth/{ => services}/auth.service.ts (88%) create mode 100755 src/modules/auth/services/tokens.service.ts delete mode 100644 src/modules/user/entities/user.entity.ts rename src/modules/{user => users}/dto/find-user.dto.ts (100%) rename src/modules/{user => users}/dto/update-user.dto.ts (100%) create mode 100644 src/modules/users/entities/refresh-token.entity.ts create mode 100644 src/modules/users/entities/user.entity.ts rename src/modules/{user => users}/user.controller.ts (91%) rename src/modules/{user => users}/user.module.ts (100%) rename src/modules/{user => users}/user.service.ts (100%) diff --git a/package-lock.json b/package-lock.json index 8acc658..6d1f2da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,9 +33,11 @@ "cache-manager": "^7.2.4", "class-transformer": "^0.5.1", "class-validator": "^0.14.2", + "dayjs": "^1.11.19", "fastify": "^5.6.1", "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "ulid": "^3.0.1" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", @@ -7344,6 +7346,12 @@ "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==", "license": "MIT" }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -13389,6 +13397,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ulid": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-3.0.1.tgz", + "integrity": "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q==", + "license": "MIT", + "bin": { + "ulid": "dist/cli.js" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", diff --git a/package.json b/package.json index 6dbcee1..4f8508d 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,11 @@ "cache-manager": "^7.2.4", "class-transformer": "^0.5.1", "class-validator": "^0.14.2", + "dayjs": "^1.11.19", "fastify": "^5.6.1", "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "ulid": "^3.0.1" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", diff --git a/src/app.module.ts b/src/app.module.ts index 5a5c322..8fd7828 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,7 +2,7 @@ import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Module } from '@nestjs/common'; import dataBaseConfig from './config/mikro-orm.config'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { UserModule } from './modules/user/user.module'; +import { UserModule } from './modules/users/user.module'; // import { CacheModule } from '@nestjs/cache-manager'; // import { cacheConfig } from './config/cache.config'; import { UtilsModule } from './modules/utils/utils.module'; @@ -42,7 +42,7 @@ import { SubmitionModule } from './modules/submition/submition.module'; limit: 5, // max requests per window }, ]), - SubmitionModule + SubmitionModule, ], controllers: [], // providers: [CacheService], diff --git a/src/common/entities/base.entity.ts b/src/common/entities/base.entity.ts new file mode 100755 index 0000000..8d76f08 --- /dev/null +++ b/src/common/entities/base.entity.ts @@ -0,0 +1,21 @@ +import { PrimaryKey, Property, sql, OptionalProps } from '@mikro-orm/core'; + +export abstract class BaseEntity { + [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'deletedAt'; + + @PrimaryKey({ type: 'string', columnType: 'char(26)' }) + id: string = ulid(); + + @Property({ default: sql.now(), type: 'timestamptz' }) + createdAt: Date = new Date(); + + @Property({ + onUpdate: () => new Date(), + defaultRaw: 'now()', + columnType: 'timestamptz', + }) + updatedAt: Date = new Date(); + + @Property({ nullable: true }) + deletedAt?: Date; +} diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 1dac965..ebde49d 100755 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -1,612 +1,612 @@ export const enum AuthMessage { - UNAUTHORIZED_ACCESS = "شما دسترسی لازم برای این عملیات را ندارید.", - PHONE_REGISTERED = "شماره ثبت شد", - INVALID_PHONE_FORMAT = "فرمت شماره تلفن صحیح نیست", - OTP_SENT = "کد یکبار مصرف به شماره شما ارسال شد.", - INVALID_PHONE = "شماره موبایل اشتباه می باشد", - INVALID_CREDENTIAL = "شماره موبایل یا رمز عبور اشتباه می باشد", - OTP_FAILED = "کد یا شماره موبایل اشتباه است", - LOGIN_SUCCESS = "ورود با موفقیت انجام شد", - PASSWORD_LOGIN_SUCCESS = "با موفقیت وارد شدید", - FORGOT_PASSWORD_SUCCESS = "درخواست فراموشی رمز عبور با موفقیت ثبت شد", - PASSWORD_SET_SUCCESS = "پسورد با موفقیت تنظیم شد", - PASSWORD_UPDATE_SUCCESS = "رمز عبور شما تغییر کرد", - INVALID_OTP = "کد صحیح نمی‌باشد یا منقضی شده است", - PASSWORD_MISMATCH = "رمز عبور یکسان نیست", - INVALID_PASSWORD = "ایمیل یا رمز عبور اشتباه است", - INVALID_REPEAT_PASSWORD = "تکرار رمز عبور اشتباه است", - EMAIL_NOT_EMPTY = "ایمیل نمیتواند خالی باشد.", - INVALID_EMAIL_FORMAT = "فرمت ایمیل صحیح نیست", - PasswordNotEmpty = "پسورد نمیتواند خالی باشد.", - USER_NOT_FOUND = "کاربری با این شماره وجود ندارد", - USER_EXISTS = "با این شماره قبلا ثبت نام شده است", - USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود", - INVALID_USER = "کاربری با این مشخصات یافت نشد", - PHONE_NOT_FOUND = "کاربری با این شماره یافت نشد", - TOKEN_EXPIRED = "توکن منقضی شده است", - TOKEN_INVALID = "توکن نامعتبر است", - BANNED = "در حال حاضر شما امکان دسترسی به این سرویس را ندارید", - PHONE_EXISTS = "شماره تلفن قبلا ثبت شده است", - ADMIN_CREATED = "ادمین با موفقیت ایجاد شد", - PERM_NOT_FOUND = "دسترسی یافت نشد", - INVALID_PASS_FORMAT = "فرمت رمز عبور صحیح نیست", - PHONE_NOT_EMPTY = "شماره تلفن نمیتواند خالی باشد", - PASSWORD_FORMAT_INVALID = "رمز عبور باید به صورت رشته باشد", - OTP_FORMAT_INVALID = "کد یکبار مصرف باید عددی و ۵ رقمی باشد", - PHONE_FORMAT_INVALID = "شماره تلفن باید معتبر و به فرمت ایران باشد", - TOKEN_NOT_EMPTY = "توکن نمی‌تواند خالی باشد", - PASSWORD_NOT_EMPTY = "رمز عبور نمی‌تواند خالی باشد", - PASSWORD_CHANGED_SUCCESSFULLY = "رمز عبور با موفقیت تغییر کرد", - PASSWORD_CONFIRMATION_NOT_EMPTY = "تایید رمز عبور نمی‌تواند خالی باشد", - PASSWORD_LENGTH = "رمز عبور باید حداقل ۸ کاراکتر باشد", - OTP_NOT_EMPTY = "کد یکبار مصرف نمی‌تواند خالی باشد", - LAST_PASSWORD_NOT_EMPTY = "رمز عبور قبلی نمی‌تواند خالی باشد", - FIRST_NAME_NOT_EMPTY = "نام نمی‌تواند خالی باشد", - LAST_NAME_NOT_EMPTY = "نام خانوادگی نمی‌تواند خالی باشد", - FIRST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = "نام باید بین ۲ تا ۵۰ کاراکتر باشد", - LAST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = "نام خانوادگی باید بین ۲ تا ۵۰ کاراکتر باشد", - BIRTH_DATE_NOT_EMPTY = "تاریخ تولد نمی‌تواند خالی باشد", - NATIONAL_CODE_INCORRECT = "کد ملی باید ۱۰ رقمی باشد", - NATIONAL_NOT_EMPTY = "کد ملی نمی‌تواند خالی باشد", - OTP_ALREADY_SENT = "کد یکبار مصرف قبلا ارسال شده است", - TOO_MANY_REQUESTS = "تعداد درخواست های شما بیش از حد مجاز است", - NOT_ADMIN = "شما دسترسی به بخش ادمین ندارید", - PHONE_SHOULD_BE_11_DIGIT = "شماره تلفن باید ۱۱ رقم باشد", - TIMESTAMP_NOT_EMPTY = "زمان نمی‌تواند خالی باشد", - ADMIN_CAN_NOT_LOGIN = "ادمین نمی‌تواند وارد شود", - NATIONAL_CODE_INVALID = "کد ملی نامعتبر است", - INVALID_REFRESH_TOKEN = "توکن رفرش نامعتبر است", - REFRESH_TOKEN_EXPIRED = "توکن رفرش منقضی شده است", - LOGOUT_SUCCESS = "خروج با موفقیت انجام شد", - CURRENT_PASSWORD_INVALID = "رمز عبور فعلی نامعتبر است", - TOKEN_EXPIRED_OR_INVALID = "توکن منقضی شده یا نامعتبر است", - ACCESS_DENIED = "دسترسی شما محدود شده است", - USER_ACCOUNT_INACTIVE = "حساب کاربری شما غیر فعال است", - TOKEN_MISSED_OR_EXPIRED = "توکن مفقود یا منقضی شده است", - OLD_PASSWORD_REQUIRED = "رمز عبور قبلی الزامی است", - PASSWORD_CHANGE_FAILED = "تغییر رمز عبور با مشکل روبرد شد", + UNAUTHORIZED_ACCESS = 'شما دسترسی لازم برای این عملیات را ندارید.', + PHONE_REGISTERED = 'شماره ثبت شد', + INVALID_PHONE_FORMAT = 'فرمت شماره تلفن صحیح نیست', + OTP_SENT = 'کد یکبار مصرف به شماره شما ارسال شد.', + INVALID_PHONE = 'شماره موبایل اشتباه می باشد', + INVALID_CREDENTIAL = 'شماره موبایل یا رمز عبور اشتباه می باشد', + OTP_FAILED = 'کد یا شماره موبایل اشتباه است', + LOGIN_SUCCESS = 'ورود با موفقیت انجام شد', + PASSWORD_LOGIN_SUCCESS = 'با موفقیت وارد شدید', + FORGOT_PASSWORD_SUCCESS = 'درخواست فراموشی رمز عبور با موفقیت ثبت شد', + PASSWORD_SET_SUCCESS = 'پسورد با موفقیت تنظیم شد', + PASSWORD_UPDATE_SUCCESS = 'رمز عبور شما تغییر کرد', + INVALID_OTP = 'کد صحیح نمی‌باشد یا منقضی شده است', + PASSWORD_MISMATCH = 'رمز عبور یکسان نیست', + INVALID_PASSWORD = 'ایمیل یا رمز عبور اشتباه است', + INVALID_REPEAT_PASSWORD = 'تکرار رمز عبور اشتباه است', + EMAIL_NOT_EMPTY = 'ایمیل نمیتواند خالی باشد.', + INVALID_EMAIL_FORMAT = 'فرمت ایمیل صحیح نیست', + PasswordNotEmpty = 'پسورد نمیتواند خالی باشد.', + USER_NOT_FOUND = 'کاربری با این شماره وجود ندارد', + USER_EXISTS = 'با این شماره قبلا ثبت نام شده است', + USER_REGISTER_SUCCESS = 'ثبت نام موفقیت آمیز بود', + INVALID_USER = 'کاربری با این مشخصات یافت نشد', + PHONE_NOT_FOUND = 'کاربری با این شماره یافت نشد', + TOKEN_EXPIRED = 'توکن منقضی شده است', + TOKEN_INVALID = 'توکن نامعتبر است', + BANNED = 'در حال حاضر شما امکان دسترسی به این سرویس را ندارید', + PHONE_EXISTS = 'شماره تلفن قبلا ثبت شده است', + ADMIN_CREATED = 'ادمین با موفقیت ایجاد شد', + PERM_NOT_FOUND = 'دسترسی یافت نشد', + INVALID_PASS_FORMAT = 'فرمت رمز عبور صحیح نیست', + PHONE_NOT_EMPTY = 'شماره تلفن نمیتواند خالی باشد', + PASSWORD_FORMAT_INVALID = 'رمز عبور باید به صورت رشته باشد', + OTP_FORMAT_INVALID = 'کد یکبار مصرف باید عددی و ۵ رقمی باشد', + PHONE_FORMAT_INVALID = 'شماره تلفن باید معتبر و به فرمت ایران باشد', + TOKEN_NOT_EMPTY = 'توکن نمی‌تواند خالی باشد', + PASSWORD_NOT_EMPTY = 'رمز عبور نمی‌تواند خالی باشد', + PASSWORD_CHANGED_SUCCESSFULLY = 'رمز عبور با موفقیت تغییر کرد', + PASSWORD_CONFIRMATION_NOT_EMPTY = 'تایید رمز عبور نمی‌تواند خالی باشد', + PASSWORD_LENGTH = 'رمز عبور باید حداقل ۸ کاراکتر باشد', + OTP_NOT_EMPTY = 'کد یکبار مصرف نمی‌تواند خالی باشد', + LAST_PASSWORD_NOT_EMPTY = 'رمز عبور قبلی نمی‌تواند خالی باشد', + FIRST_NAME_NOT_EMPTY = 'نام نمی‌تواند خالی باشد', + LAST_NAME_NOT_EMPTY = 'نام خانوادگی نمی‌تواند خالی باشد', + FIRST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = 'نام باید بین ۲ تا ۵۰ کاراکتر باشد', + LAST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = 'نام خانوادگی باید بین ۲ تا ۵۰ کاراکتر باشد', + BIRTH_DATE_NOT_EMPTY = 'تاریخ تولد نمی‌تواند خالی باشد', + NATIONAL_CODE_INCORRECT = 'کد ملی باید ۱۰ رقمی باشد', + NATIONAL_NOT_EMPTY = 'کد ملی نمی‌تواند خالی باشد', + OTP_ALREADY_SENT = 'کد یکبار مصرف قبلا ارسال شده است', + TOO_MANY_REQUESTS = 'تعداد درخواست های شما بیش از حد مجاز است', + NOT_ADMIN = 'شما دسترسی به بخش ادمین ندارید', + PHONE_SHOULD_BE_11_DIGIT = 'شماره تلفن باید ۱۱ رقم باشد', + TIMESTAMP_NOT_EMPTY = 'زمان نمی‌تواند خالی باشد', + ADMIN_CAN_NOT_LOGIN = 'ادمین نمی‌تواند وارد شود', + NATIONAL_CODE_INVALID = 'کد ملی نامعتبر است', + INVALID_REFRESH_TOKEN = 'توکن رفرش نامعتبر است', + REFRESH_TOKEN_EXPIRED = 'توکن رفرش منقضی شده است', + LOGOUT_SUCCESS = 'خروج با موفقیت انجام شد', + CURRENT_PASSWORD_INVALID = 'رمز عبور فعلی نامعتبر است', + TOKEN_EXPIRED_OR_INVALID = 'توکن منقضی شده یا نامعتبر است', + ACCESS_DENIED = 'دسترسی شما محدود شده است', + USER_ACCOUNT_INACTIVE = 'حساب کاربری شما غیر فعال است', + TOKEN_MISSED_OR_EXPIRED = 'توکن مفقود یا منقضی شده است', + OLD_PASSWORD_REQUIRED = 'رمز عبور قبلی الزامی است', + PASSWORD_CHANGE_FAILED = 'تغییر رمز عبور با مشکل روبرد شد', } export const enum UserMessage { - USER_NOT_FOUND = "کاربری با این مشخصات یافت نشد", - USER_EXISTS = "با این شماره قبلا ثبت نام شده است", - USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود", - EMAIL_ADDRESS_ALREADY_EXISTS = "ایمیل قبلا ثبت شده است", - EMAIL_USER_NOT_FOUND = "ایمیل یافت نشد", - EMAIL_USER_DELETED_SUCCESSFULLY = "ایمیل با موفقیت حذف شد", - FAILED_TO_DELETE_EMAIL_USER = "خطا در حذف ایمیل", - EMAIL_USER_QUOTA_UPDATED_SUCCESSFULLY = "ایمیل با موفقیت به روز رسانی شد", - FAILED_TO_UPDATE_EMAIL_USER_QUOTA = "خطا در به روز رسانی حجم ایمیل", - USERNAME_REQUIRED = "نام کاربری الزامی است", - USERNAME_STRING = "نام کاربری باید یک رشته باشد", - USERNAME_MIN_LENGTH = "نام کاربری باید حداقل ۲ کاراکتر باشد", - USERNAME_MATCHES = "نام کاربری فقط میتواند شامل حروف، اعداد، نقطه، خط زیر و خط فاصله باشد", - PASSWORD_MATCHES = "رمز عبور باید حداقل ۸ کاراکتر باشد و شامل حروف بزرگ، حروف کوچک، اعداد و علائم خاص باشد", - PASSWORD_STRING = "رمز عبور باید یک رشته باشد", - PASSWORD_REQUIRED = "رمز عبور الزامی است", - PASSWORD_MIN_LENGTH = "رمز عبور باید حداقل ۸ کاراکتر باشد", - DOMAIN_ID_STRING = "شناسه دامنه باید یک رشته باشد", - DOMAIN_ID_REQUIRED = "شناسه دامنه الزامی است", - DOMAIN_ID_UUID = "شناسه دامنه باید یک یو یو آی دی باشد", - DISPLAY_NAME_STRING = "نام نمایشی باید یک رشته باشد", - DISPLAY_NAME_OPTIONAL = "نام نمایشی اختیاری است", - QUOTA_NUMBER = "حجم ایمیل باید یک عدد باشد", - QUOTA_OPTIONAL = "حجم ایمیل اختیاری است", - QUOTA_NOT_EMPTY = "حجم ایمیل نمیتواند خالی باشد", - ALIASES_ARRAY = "الیاس ها باید یک آرایه باشد", - ALIASES_STRING = "الیاس ها باید یک رشته باشد", - ALIASES_OPTIONAL = "الیاس ها اختیاری است", - TITLE_STRING = "عنوان باید یک رشته باشد", - TITLE_OPTIONAL = "عنوان اختیاری است", - TITLE_NOT_EMPTY = "عنوان نمیتواند خالی باشد", - EMAIL_USER_CREATED_SUCCESSFULLY = "ایمیل با موفقیت ایجاد شد", - EMAIL_USER_UPDATED_SUCCESSFULLY = "ایمیل کاربر با موفقیت به‌روزرسانی شد", - STATUS_UPDATED = "وضعیت کاربر با موفقیت تغییر کرد", - TEMPLATE_UUID = "شناسه قالب باید یک یو یو آی دی باشد", - TEMPLATE_NOT_EMPTY = "شناسه قالب نمیتواند خالی باشد", - ALIASES_EMAIL = "آدرس ایمیل الیاس باید معتبر باشد", - FORWARDERS_EMAIL_VALID = "آدرس ایمیل فوروارد باید معتبر باشد", - FORWARDERS_ARRAY = "آدرس های فوروارد باید یک آرایه باشد", - FORWARDERS_STRING = "آدرس های فوروارد باید یک رشته باشد", - PROFILE_PICTURE_URL = "آدرس تصویر پروفایل باید یک آدرس اینترنتی معتبر باشد", - USER_UPDATED_SUCCESSFULLY = "کاربر با موفقیت به روز رسانی شد", - PROFILE_PICTURE_NOT_EMPTY = "تصویر پروفایل نمیتواند خالی باشد", - PUSH_TOKEN_NOT_FOUND = "توکن پوش نامعتبر است", - PUSH_TOKEN_ADDED_SUCCESSFULLY = "توکن پوش با موفقیت اضافه شد", - NO_PUSH_TOKENS_FOUND = "توکن پوشی برای این کاربر یافت نشد", - PUSH_TOKEN_REMOVED_SUCCESSFULLY = "توکن پوش با موفقیت حذف شد", + USER_NOT_FOUND = 'کاربری با این مشخصات یافت نشد', + USER_EXISTS = 'با این شماره قبلا ثبت نام شده است', + USER_REGISTER_SUCCESS = 'ثبت نام موفقیت آمیز بود', + EMAIL_ADDRESS_ALREADY_EXISTS = 'ایمیل قبلا ثبت شده است', + EMAIL_USER_NOT_FOUND = 'ایمیل یافت نشد', + EMAIL_USER_DELETED_SUCCESSFULLY = 'ایمیل با موفقیت حذف شد', + FAILED_TO_DELETE_EMAIL_USER = 'خطا در حذف ایمیل', + EMAIL_USER_QUOTA_UPDATED_SUCCESSFULLY = 'ایمیل با موفقیت به روز رسانی شد', + FAILED_TO_UPDATE_EMAIL_USER_QUOTA = 'خطا در به روز رسانی حجم ایمیل', + USERNAME_REQUIRED = 'نام کاربری الزامی است', + USERNAME_STRING = 'نام کاربری باید یک رشته باشد', + USERNAME_MIN_LENGTH = 'نام کاربری باید حداقل ۲ کاراکتر باشد', + USERNAME_MATCHES = 'نام کاربری فقط میتواند شامل حروف، اعداد، نقطه، خط زیر و خط فاصله باشد', + PASSWORD_MATCHES = 'رمز عبور باید حداقل ۸ کاراکتر باشد و شامل حروف بزرگ، حروف کوچک، اعداد و علائم خاص باشد', + PASSWORD_STRING = 'رمز عبور باید یک رشته باشد', + PASSWORD_REQUIRED = 'رمز عبور الزامی است', + PASSWORD_MIN_LENGTH = 'رمز عبور باید حداقل ۸ کاراکتر باشد', + DOMAIN_ID_STRING = 'شناسه دامنه باید یک رشته باشد', + DOMAIN_ID_REQUIRED = 'شناسه دامنه الزامی است', + DOMAIN_ID_UUID = 'شناسه دامنه باید یک یو یو آی دی باشد', + DISPLAY_NAME_STRING = 'نام نمایشی باید یک رشته باشد', + DISPLAY_NAME_OPTIONAL = 'نام نمایشی اختیاری است', + QUOTA_NUMBER = 'حجم ایمیل باید یک عدد باشد', + QUOTA_OPTIONAL = 'حجم ایمیل اختیاری است', + QUOTA_NOT_EMPTY = 'حجم ایمیل نمیتواند خالی باشد', + ALIASES_ARRAY = 'الیاس ها باید یک آرایه باشد', + ALIASES_STRING = 'الیاس ها باید یک رشته باشد', + ALIASES_OPTIONAL = 'الیاس ها اختیاری است', + TITLE_STRING = 'عنوان باید یک رشته باشد', + TITLE_OPTIONAL = 'عنوان اختیاری است', + TITLE_NOT_EMPTY = 'عنوان نمیتواند خالی باشد', + EMAIL_USER_CREATED_SUCCESSFULLY = 'ایمیل با موفقیت ایجاد شد', + EMAIL_USER_UPDATED_SUCCESSFULLY = 'ایمیل کاربر با موفقیت به‌روزرسانی شد', + STATUS_UPDATED = 'وضعیت کاربر با موفقیت تغییر کرد', + TEMPLATE_UUID = 'شناسه قالب باید یک یو یو آی دی باشد', + TEMPLATE_NOT_EMPTY = 'شناسه قالب نمیتواند خالی باشد', + ALIASES_EMAIL = 'آدرس ایمیل الیاس باید معتبر باشد', + FORWARDERS_EMAIL_VALID = 'آدرس ایمیل فوروارد باید معتبر باشد', + FORWARDERS_ARRAY = 'آدرس های فوروارد باید یک آرایه باشد', + FORWARDERS_STRING = 'آدرس های فوروارد باید یک رشته باشد', + PROFILE_PICTURE_URL = 'آدرس تصویر پروفایل باید یک آدرس اینترنتی معتبر باشد', + USER_UPDATED_SUCCESSFULLY = 'کاربر با موفقیت به روز رسانی شد', + PROFILE_PICTURE_NOT_EMPTY = 'تصویر پروفایل نمیتواند خالی باشد', + PUSH_TOKEN_NOT_FOUND = 'توکن پوش نامعتبر است', + PUSH_TOKEN_ADDED_SUCCESSFULLY = 'توکن پوش با موفقیت اضافه شد', + NO_PUSH_TOKENS_FOUND = 'توکن پوشی برای این کاربر یافت نشد', + PUSH_TOKEN_REMOVED_SUCCESSFULLY = 'توکن پوش با موفقیت حذف شد', } export const enum CommonMessage { - VALIDITY_TYPE_REQUIRED = "نوع اعتبار سنجی مورد نیاز است", - THIS_FILED_IS_REQUIRED = "این فیلد الزامی است", - VALID_FOR_CHOOSE = "معتبر برای انتخاب", - UPDATE_SUCCESS = "با موفقیت به روز رسانی شد", - CREATED = "با موفقیت ایجاد شد", - DELETED = "با موفقیت حذف شد", - ID_REQUIRED = "شناسه مورد نیاز است", - ID_SHOULD_BE_UUID = "شناسه باید یک یو یو آی دی باشد", - PaymentTypeQueryNotEmpty = "نوع پرداخت نمی‌تواند خالی باشد", - SEARCH_QUERY_STRING = "رشته جستجو باید یک رشته باشد", - UPDATED = "با موفقیت آپدیت شد", - IS_ACTIVE_SHOULD_BE_1_0 = "وضعیت باید یکی از مقادیر ۰ و ۱ باشد", - DATE_MUST_BE_DATE = "تاریخ باید یک تاریخ معتبر به صورت رشته باشد", + VALIDITY_TYPE_REQUIRED = 'نوع اعتبار سنجی مورد نیاز است', + THIS_FILED_IS_REQUIRED = 'این فیلد الزامی است', + VALID_FOR_CHOOSE = 'معتبر برای انتخاب', + UPDATE_SUCCESS = 'با موفقیت به روز رسانی شد', + CREATED = 'با موفقیت ایجاد شد', + DELETED = 'با موفقیت حذف شد', + ID_REQUIRED = 'شناسه مورد نیاز است', + ID_SHOULD_BE_UUID = 'شناسه باید یک یو یو آی دی باشد', + PaymentTypeQueryNotEmpty = 'نوع پرداخت نمی‌تواند خالی باشد', + SEARCH_QUERY_STRING = 'رشته جستجو باید یک رشته باشد', + UPDATED = 'با موفقیت آپدیت شد', + IS_ACTIVE_SHOULD_BE_1_0 = 'وضعیت باید یکی از مقادیر ۰ و ۱ باشد', + DATE_MUST_BE_DATE = 'تاریخ باید یک تاریخ معتبر به صورت رشته باشد', } export const enum UploaderMessage { - UPLOAD_FILE_INVALID = "فایل معتبر نیست", - UPLOAD_FILE_TOO_LARGE = "فایل بزرگتر از حد مجاز است . حداکثر حجم فایل [MAX_FILE_SIZE] مگابایت است", - UPLOAD_FILE_TYPE_NOT_SUPPORTED = "نوع فایل معتبر نیست . مجاز است : [MIME_TYPES]", - UPLOAD_FILE_SUCCESS = "فایل با موفقیت آپلود شد", + UPLOAD_FILE_INVALID = 'فایل معتبر نیست', + UPLOAD_FILE_TOO_LARGE = 'فایل بزرگتر از حد مجاز است . حداکثر حجم فایل [MAX_FILE_SIZE] مگابایت است', + UPLOAD_FILE_TYPE_NOT_SUPPORTED = 'نوع فایل معتبر نیست . مجاز است : [MIME_TYPES]', + UPLOAD_FILE_SUCCESS = 'فایل با موفقیت آپلود شد', } export const enum EmailMessage { - EMAIL_VERIFICATION = "تایید ایمیل", - EMAIL_SENDING_FAILED = "ارسال ایمیل با خطا مواجه شد", - LOGIN = "ورود به سیستم", - INVOICE = "فاکتور", - WALLET = "اعلان کیف پول", - TICKET = "تیکت پشتیبانی", - ANNOUNCEMENT = "اعلان", - PAYMENT_REMINDER = "یادآوری پرداخت", - PAYMENT_CANCELLATION = "لغو پرداخت", - EMAIL_SENDING_SUCCESS = "ارسال ایمیل با موفقیت انجام شد", - EMAIL_FORWARD_SUCCESS = "فوروارد ایمیل با موفقیت انجام شد", - EMAIL_STATUS_RETRIEVED_SUCCESSFULLY = "وضعیت ایمیل با موفقیت دریافت شد", - MESSAGES_SEARCHED_SUCCESSFULLY = "جستجوی ایمیل با موفقیت انجام شد", - MESSAGES_LISTED_SUCCESSFULLY = "لیست ایمیل ها با موفقیت دریافت شد", - MESSAGE_RETRIEVED_SUCCESSFULLY = "ایمیل با موفقیت دریافت شد", - MESSAGE_DELETED_SUCCESSFULLY = "ایمیل با موفقیت حذف شد", - USER_ID_REQUIRED = "شناسه کاربری مورد نیاز است", - USER_ID_MUST_BE_STRING = "شناسه کاربری باید یک رشته باشد", - MAILBOX_ID_REQUIRED = "شناسه میل باکس ایمیل مورد نیاز است", - MAILBOX_ID_MUST_BE_STRING = "شناسه میل باکس ایمیل باید یک رشته باشد", - QUEUE_ID_REQUIRED = "شناسه پیش‌نویس ایمیل مورد نیاز است", - QUEUE_ID_MUST_BE_STRING = "شناسه پیش‌نویس ایمیل باید یک رشته باشد", - MESSAGE_ID_MUST_BE_NUMBER = "شناسه ایمیل باید یک عدد باشد", - FROM_ADDRESS_REQUIRED = "آدرس از مورد نیاز است", + EMAIL_VERIFICATION = 'تایید ایمیل', + EMAIL_SENDING_FAILED = 'ارسال ایمیل با خطا مواجه شد', + LOGIN = 'ورود به سیستم', + INVOICE = 'فاکتور', + WALLET = 'اعلان کیف پول', + TICKET = 'تیکت پشتیبانی', + ANNOUNCEMENT = 'اعلان', + PAYMENT_REMINDER = 'یادآوری پرداخت', + PAYMENT_CANCELLATION = 'لغو پرداخت', + EMAIL_SENDING_SUCCESS = 'ارسال ایمیل با موفقیت انجام شد', + EMAIL_FORWARD_SUCCESS = 'فوروارد ایمیل با موفقیت انجام شد', + EMAIL_STATUS_RETRIEVED_SUCCESSFULLY = 'وضعیت ایمیل با موفقیت دریافت شد', + MESSAGES_SEARCHED_SUCCESSFULLY = 'جستجوی ایمیل با موفقیت انجام شد', + MESSAGES_LISTED_SUCCESSFULLY = 'لیست ایمیل ها با موفقیت دریافت شد', + MESSAGE_RETRIEVED_SUCCESSFULLY = 'ایمیل با موفقیت دریافت شد', + MESSAGE_DELETED_SUCCESSFULLY = 'ایمیل با موفقیت حذف شد', + USER_ID_REQUIRED = 'شناسه کاربری مورد نیاز است', + USER_ID_MUST_BE_STRING = 'شناسه کاربری باید یک رشته باشد', + MAILBOX_ID_REQUIRED = 'شناسه میل باکس ایمیل مورد نیاز است', + MAILBOX_ID_MUST_BE_STRING = 'شناسه میل باکس ایمیل باید یک رشته باشد', + QUEUE_ID_REQUIRED = 'شناسه پیش‌نویس ایمیل مورد نیاز است', + QUEUE_ID_MUST_BE_STRING = 'شناسه پیش‌نویس ایمیل باید یک رشته باشد', + MESSAGE_ID_MUST_BE_NUMBER = 'شناسه ایمیل باید یک عدد باشد', + FROM_ADDRESS_REQUIRED = 'آدرس از مورد نیاز است', // Validation Messages for Email DTOs - FROM_ADDRESS_MUST_BE_EMAIL = "آدرس فرستنده باید یک ایمیل معتبر باشد", + FROM_ADDRESS_MUST_BE_EMAIL = 'آدرس فرستنده باید یک ایمیل معتبر باشد', // Query validation messages - SEARCH_QUERY_PARAMETER_MUST_BE_STRING = "پارامتر جستجو باید یک رشته باشد", - MESSAGE_IDS_MUST_BE_STRING = "شناسه‌های پیام باید یک رشته باشد", - THREAD_ID_MUST_BE_STRING = "شناسه رشته گفتگو باید یک رشته باشد", - OR_QUERY_MUST_BE_OBJECT = "پارامتر OR باید یک شیء باشد", - DATE_START_MUST_BE_DATE_STRING = "تاریخ شروع باید یک رشته تاریخ معتبر باشد", - DATE_END_MUST_BE_DATE_STRING = "تاریخ پایان باید یک رشته تاریخ معتبر باشد", - TO_ADDRESS_MUST_BE_STRING = "آدرس گیرنده باید یک رشته باشد", - MIN_SIZE_MUST_BE_NUMBER = "حداقل اندازه باید یک عدد باشد", - MIN_SIZE_MUST_BE_NON_NEGATIVE = "حداقل اندازه نمی‌تواند منفی باشد", - MAX_SIZE_MUST_BE_NUMBER = "حداکثر اندازه باید یک عدد باشد", - MAX_SIZE_MUST_BE_NON_NEGATIVE = "حداکثر اندازه نمی‌تواند منفی باشد", - ATTACHMENTS_FILTER_MUST_BE_BOOLEAN = "فیلتر پیوست‌ها باید بولین باشد", - FLAGGED_FILTER_MUST_BE_BOOLEAN = "فیلتر پیام‌های علامت‌دار باید بولین باشد", - UNSEEN_FILTER_MUST_BE_BOOLEAN = "فیلتر پیام‌های خوانده‌نشده باید بولین باشد", - INCLUDE_HEADERS_MUST_BE_STRING = "لیست هدرها باید یک رشته باشد", - SEARCHABLE_FILTER_MUST_BE_BOOLEAN = "فیلتر قابل جستجو باید بولین باشد", - THREAD_COUNTERS_MUST_BE_BOOLEAN = "شمارنده رشته گفتگو باید بولین باشد", - ORDER_MUST_BE_VALID = "ترتیب باید یکی از مقادیر asc یا desc باشد", - NEXT_CURSOR_MUST_BE_STRING = "نشانگر صفحه بعد باید یک رشته باشد", - PREVIOUS_CURSOR_MUST_BE_STRING = "نشانگر صفحه قبل باید یک رشته باشد", + SEARCH_QUERY_PARAMETER_MUST_BE_STRING = 'پارامتر جستجو باید یک رشته باشد', + MESSAGE_IDS_MUST_BE_STRING = 'شناسه‌های پیام باید یک رشته باشد', + THREAD_ID_MUST_BE_STRING = 'شناسه رشته گفتگو باید یک رشته باشد', + OR_QUERY_MUST_BE_OBJECT = 'پارامتر OR باید یک شیء باشد', + DATE_START_MUST_BE_DATE_STRING = 'تاریخ شروع باید یک رشته تاریخ معتبر باشد', + DATE_END_MUST_BE_DATE_STRING = 'تاریخ پایان باید یک رشته تاریخ معتبر باشد', + TO_ADDRESS_MUST_BE_STRING = 'آدرس گیرنده باید یک رشته باشد', + MIN_SIZE_MUST_BE_NUMBER = 'حداقل اندازه باید یک عدد باشد', + MIN_SIZE_MUST_BE_NON_NEGATIVE = 'حداقل اندازه نمی‌تواند منفی باشد', + MAX_SIZE_MUST_BE_NUMBER = 'حداکثر اندازه باید یک عدد باشد', + MAX_SIZE_MUST_BE_NON_NEGATIVE = 'حداکثر اندازه نمی‌تواند منفی باشد', + ATTACHMENTS_FILTER_MUST_BE_BOOLEAN = 'فیلتر پیوست‌ها باید بولین باشد', + FLAGGED_FILTER_MUST_BE_BOOLEAN = 'فیلتر پیام‌های علامت‌دار باید بولین باشد', + UNSEEN_FILTER_MUST_BE_BOOLEAN = 'فیلتر پیام‌های خوانده‌نشده باید بولین باشد', + INCLUDE_HEADERS_MUST_BE_STRING = 'لیست هدرها باید یک رشته باشد', + SEARCHABLE_FILTER_MUST_BE_BOOLEAN = 'فیلتر قابل جستجو باید بولین باشد', + THREAD_COUNTERS_MUST_BE_BOOLEAN = 'شمارنده رشته گفتگو باید بولین باشد', + ORDER_MUST_BE_VALID = 'ترتیب باید یکی از مقادیر asc یا desc باشد', + NEXT_CURSOR_MUST_BE_STRING = 'نشانگر صفحه بعد باید یک رشته باشد', + PREVIOUS_CURSOR_MUST_BE_STRING = 'نشانگر صفحه قبل باید یک رشته باشد', - RECIPIENT_NAME_MUST_BE_STRING = "نام گیرنده باید یک رشته باشد", - RECIPIENT_ADDRESS_REQUIRED = "آدرس گیرنده مورد نیاز است", - RECIPIENT_ADDRESS_MUST_BE_EMAIL = "آدرس گیرنده باید یک ایمیل معتبر باشد", - HEADER_KEY_REQUIRED = "کلید هدر مورد نیاز است", - HEADER_KEY_MUST_BE_STRING = "کلید هدر باید یک رشته باشد", - HEADER_VALUE_REQUIRED = "مقدار هدر مورد نیاز است", - HEADER_VALUE_MUST_BE_STRING = "مقدار هدر باید یک رشته باشد", - ATTACHMENT_FILENAME_MUST_BE_STRING = "نام فایل پیوست باید یک رشته باشد", - ATTACHMENT_CONTENT_TYPE_MUST_BE_STRING = "نوع محتوای پیوست باید یک رشته باشد", - ATTACHMENT_ENCODING_MUST_BE_STRING = "کدگذاری پیوست باید یک رشته باشد", - ATTACHMENT_CONTENT_TRANSFER_ENCODING_MUST_BE_STRING = "کدگذاری انتقال محتوای پیوست باید یک رشته باشد", - ATTACHMENT_CONTENT_DISPOSITION_INVALID = "نحوه نمایش پیوست باید inline یا attachment باشد", - ATTACHMENT_CONTENT_REQUIRED = "محتوای پیوست مورد نیاز است", - ATTACHMENT_CONTENT_MUST_BE_STRING = "محتوای پیوست باید یک رشته باشد", - ATTACHMENT_CID_MUST_BE_STRING = "شناسه محتوای پیوست باید یک رشته باشد", - DRAFT_MAILBOX_REQUIRED = "شناسه صندوق پیش‌نویس مورد نیاز است", - DRAFT_MAILBOX_MUST_BE_STRING = "شناسه صندوق پیش‌نویس باید یک رشته باشد", - DRAFT_ID_REQUIRED = "شناسه پیش‌نویس مورد نیاز است", - DRAFT_ID_MUST_BE_NUMBER = "شناسه پیش‌نویس باید یک عدد باشد", - ENVELOPE_FROM_REQUIRED = "آدرس فرستنده در envelope مورد نیاز است", - ENVELOPE_TO_REQUIRED = "آدرس گیرنده در envelope مورد نیاز است", - ENVELOPE_TO_MUST_BE_ARRAY = "آدرس گیرنده در envelope باید یک آرایه باشد", - MAILBOX_MUST_BE_STRING = "شناسه صندوق باید یک رشته باشد", - REPLY_TO_MUST_BE_VALID = "آدرس پاسخ باید معتبر باشد", - TO_ADDRESSES_REQUIRED = "آدرس‌های گیرنده مورد نیاز است", - TO_ADDRESSES_MUST_BE_ARRAY = "آدرس‌های گیرنده باید یک آرایه باشد", - CC_ADDRESSES_MUST_BE_ARRAY = "آدرس‌های کپی کربن باید یک آرایه باشد", - BCC_ADDRESSES_MUST_BE_ARRAY = "آدرس‌های کپی مخفی باید یک آرایه باشد", - HEADERS_MUST_BE_ARRAY = "هدرهای سفارشی باید یک آرایه باشد", - SUBJECT_MUST_BE_STRING = "موضوع ایمیل باید یک رشته باشد", - TEXT_CONTENT_MUST_BE_STRING = "محتوای متنی باید یک رشته باشد", - HTML_CONTENT_MUST_BE_STRING = "محتوای HTML باید یک رشته باشد", - ATTACHMENTS_MUST_BE_ARRAY = "پیوست‌ها باید یک آرایه باشد", - SESSION_ID_MUST_BE_STRING = "شناسه جلسه باید یک رشته باشد", - IP_ADDRESS_MUST_BE_STRING = "آدرس IP باید یک رشته باشد", - IS_DRAFT_MUST_BE_BOOLEAN = "وضعیت پیش‌نویس باید بولین باشد", - SEND_TIME_MUST_BE_DATE = "زمان ارسال باید یک تاریخ معتبر باشد", - UPLOAD_ONLY_MUST_BE_BOOLEAN = "حالت فقط آپلود باید بولین باشد", - ENVELOPE_MUST_BE_VALID = "envelope باید معتبر باشد", + RECIPIENT_NAME_MUST_BE_STRING = 'نام گیرنده باید یک رشته باشد', + RECIPIENT_ADDRESS_REQUIRED = 'آدرس گیرنده مورد نیاز است', + RECIPIENT_ADDRESS_MUST_BE_EMAIL = 'آدرس گیرنده باید یک ایمیل معتبر باشد', + HEADER_KEY_REQUIRED = 'کلید هدر مورد نیاز است', + HEADER_KEY_MUST_BE_STRING = 'کلید هدر باید یک رشته باشد', + HEADER_VALUE_REQUIRED = 'مقدار هدر مورد نیاز است', + HEADER_VALUE_MUST_BE_STRING = 'مقدار هدر باید یک رشته باشد', + ATTACHMENT_FILENAME_MUST_BE_STRING = 'نام فایل پیوست باید یک رشته باشد', + ATTACHMENT_CONTENT_TYPE_MUST_BE_STRING = 'نوع محتوای پیوست باید یک رشته باشد', + ATTACHMENT_ENCODING_MUST_BE_STRING = 'کدگذاری پیوست باید یک رشته باشد', + ATTACHMENT_CONTENT_TRANSFER_ENCODING_MUST_BE_STRING = 'کدگذاری انتقال محتوای پیوست باید یک رشته باشد', + ATTACHMENT_CONTENT_DISPOSITION_INVALID = 'نحوه نمایش پیوست باید inline یا attachment باشد', + ATTACHMENT_CONTENT_REQUIRED = 'محتوای پیوست مورد نیاز است', + ATTACHMENT_CONTENT_MUST_BE_STRING = 'محتوای پیوست باید یک رشته باشد', + ATTACHMENT_CID_MUST_BE_STRING = 'شناسه محتوای پیوست باید یک رشته باشد', + DRAFT_MAILBOX_REQUIRED = 'شناسه صندوق پیش‌نویس مورد نیاز است', + DRAFT_MAILBOX_MUST_BE_STRING = 'شناسه صندوق پیش‌نویس باید یک رشته باشد', + DRAFT_ID_REQUIRED = 'شناسه پیش‌نویس مورد نیاز است', + DRAFT_ID_MUST_BE_NUMBER = 'شناسه پیش‌نویس باید یک عدد باشد', + ENVELOPE_FROM_REQUIRED = 'آدرس فرستنده در envelope مورد نیاز است', + ENVELOPE_TO_REQUIRED = 'آدرس گیرنده در envelope مورد نیاز است', + ENVELOPE_TO_MUST_BE_ARRAY = 'آدرس گیرنده در envelope باید یک آرایه باشد', + MAILBOX_MUST_BE_STRING = 'شناسه صندوق باید یک رشته باشد', + REPLY_TO_MUST_BE_VALID = 'آدرس پاسخ باید معتبر باشد', + TO_ADDRESSES_REQUIRED = 'آدرس‌های گیرنده مورد نیاز است', + TO_ADDRESSES_MUST_BE_ARRAY = 'آدرس‌های گیرنده باید یک آرایه باشد', + CC_ADDRESSES_MUST_BE_ARRAY = 'آدرس‌های کپی کربن باید یک آرایه باشد', + BCC_ADDRESSES_MUST_BE_ARRAY = 'آدرس‌های کپی مخفی باید یک آرایه باشد', + HEADERS_MUST_BE_ARRAY = 'هدرهای سفارشی باید یک آرایه باشد', + SUBJECT_MUST_BE_STRING = 'موضوع ایمیل باید یک رشته باشد', + TEXT_CONTENT_MUST_BE_STRING = 'محتوای متنی باید یک رشته باشد', + HTML_CONTENT_MUST_BE_STRING = 'محتوای HTML باید یک رشته باشد', + ATTACHMENTS_MUST_BE_ARRAY = 'پیوست‌ها باید یک آرایه باشد', + SESSION_ID_MUST_BE_STRING = 'شناسه جلسه باید یک رشته باشد', + IP_ADDRESS_MUST_BE_STRING = 'آدرس IP باید یک رشته باشد', + IS_DRAFT_MUST_BE_BOOLEAN = 'وضعیت پیش‌نویس باید بولین باشد', + SEND_TIME_MUST_BE_DATE = 'زمان ارسال باید یک تاریخ معتبر باشد', + UPLOAD_ONLY_MUST_BE_BOOLEAN = 'حالت فقط آپلود باید بولین باشد', + ENVELOPE_MUST_BE_VALID = 'envelope باید معتبر باشد', // Message operations - MESSAGE_MARKED_AS_SEEN_SUCCESSFULLY = "پیام با موفقیت به عنوان خوانده شده علامت گذاری شد", - ALL_MESSAGES_MARKED_AS_READ_SUCCESSFULLY = "تمام پیام ها با موفقیت به عنوان خوانده شده علامت گذاری شدند", - MESSAGE_MARK_AS_SEEN_FAILED = "علامت گذاری پیام با خطا مواجه شد", - SENT_MESSAGES_RETRIEVED_SUCCESSFULLY = "پیام های ارسالی با موفقیت دریافت شد", - SENT_MESSAGES_RETRIEVAL_FAILED = "دریافت پیام های ارسالی با خطا مواجه شد", - TRASH_MESSAGES_RETRIEVED_SUCCESSFULLY = "پیام های حذف شده با موفقیت دریافت شد", - TRASH_MESSAGES_RETRIEVAL_FAILED = "دریافت پیام های حذف شده با خطا مواجه شد", - DRAFT_UPDATED_SUCCESSFULLY = "پیش نویس با موفقیت به روز رسانی شد", - DRAFT_SENT_SUCCESSFULLY = "پیش نویس با موفقیت ارسال شد", - DRAFT_DELETED_SUCCESSFULLY = "پیش نویس با موفقیت حذف شد", - MESSAGE_MOVED_TO_ARCHIVE_SUCCESSFULLY = "پیام با موفقیت به آرشیو منتقل شد", - MESSAGE_MOVED_TO_FAVORITE_SUCCESSFULLY = "پیام با موفقیت به علاقه مندی ها منتقل شد", - MESSAGE_MOVED_TO_TRASH_SUCCESSFULLY = "پیام با موفقیت به سطل زباله منتقل شد", - MESSAGE_MOVED_TO_JUNK_SUCCESSFULLY = "پیام با موفقیت به جانک منتقل شد", - MESSAGE_MOVED_TO_INBOX_FROM_ARCHIVE_SUCCESSFULLY = "پیام با موفقیت از آرشیو به صندوق ورودی منتقل شد", - MESSAGE_MOVED_TO_INBOX_FROM_FAVORITE_SUCCESSFULLY = "پیام با موفقیت از علاقه مندی ها به صندوق ورودی منتقل شد", - MESSAGE_MOVED_TO_INBOX_FROM_TRASH_SUCCESSFULLY = "پیام با موفقیت از سطل زباله به صندوق ورودی منتقل شد", - MESSAGE_MOVED_TO_INBOX_FROM_JUNK_SUCCESSFULLY = "پیام با موفقیت از جانک به صندوق ورودی منتقل شد", - MESSAGE_NOT_FOUND = "پیام یافت نشد", + MESSAGE_MARKED_AS_SEEN_SUCCESSFULLY = 'پیام با موفقیت به عنوان خوانده شده علامت گذاری شد', + ALL_MESSAGES_MARKED_AS_READ_SUCCESSFULLY = 'تمام پیام ها با موفقیت به عنوان خوانده شده علامت گذاری شدند', + MESSAGE_MARK_AS_SEEN_FAILED = 'علامت گذاری پیام با خطا مواجه شد', + SENT_MESSAGES_RETRIEVED_SUCCESSFULLY = 'پیام های ارسالی با موفقیت دریافت شد', + SENT_MESSAGES_RETRIEVAL_FAILED = 'دریافت پیام های ارسالی با خطا مواجه شد', + TRASH_MESSAGES_RETRIEVED_SUCCESSFULLY = 'پیام های حذف شده با موفقیت دریافت شد', + TRASH_MESSAGES_RETRIEVAL_FAILED = 'دریافت پیام های حذف شده با خطا مواجه شد', + DRAFT_UPDATED_SUCCESSFULLY = 'پیش نویس با موفقیت به روز رسانی شد', + DRAFT_SENT_SUCCESSFULLY = 'پیش نویس با موفقیت ارسال شد', + DRAFT_DELETED_SUCCESSFULLY = 'پیش نویس با موفقیت حذف شد', + MESSAGE_MOVED_TO_ARCHIVE_SUCCESSFULLY = 'پیام با موفقیت به آرشیو منتقل شد', + MESSAGE_MOVED_TO_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت به علاقه مندی ها منتقل شد', + MESSAGE_MOVED_TO_TRASH_SUCCESSFULLY = 'پیام با موفقیت به سطل زباله منتقل شد', + MESSAGE_MOVED_TO_JUNK_SUCCESSFULLY = 'پیام با موفقیت به جانک منتقل شد', + MESSAGE_MOVED_TO_INBOX_FROM_ARCHIVE_SUCCESSFULLY = 'پیام با موفقیت از آرشیو به صندوق ورودی منتقل شد', + MESSAGE_MOVED_TO_INBOX_FROM_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت از علاقه مندی ها به صندوق ورودی منتقل شد', + MESSAGE_MOVED_TO_INBOX_FROM_TRASH_SUCCESSFULLY = 'پیام با موفقیت از سطل زباله به صندوق ورودی منتقل شد', + MESSAGE_MOVED_TO_INBOX_FROM_JUNK_SUCCESSFULLY = 'پیام با موفقیت از جانک به صندوق ورودی منتقل شد', + MESSAGE_NOT_FOUND = 'پیام یافت نشد', // Bulk action messages - BULK_ACTION_COMPLETED_SUCCESSFULLY = "[count] پیام با موفقیت [action] شد", - BULK_ACTION_PARTIALLY_COMPLETED = "[successful] از [total] پیام [action] شد. [failed] پیام با خطا مواجه شد", - BULK_ACTION_FAILED = "هیچ پیامی [action] نشد. تمام [total] تلاش ناموفق بود", + BULK_ACTION_COMPLETED_SUCCESSFULLY = '[count] پیام با موفقیت [action] شد', + BULK_ACTION_PARTIALLY_COMPLETED = '[successful] از [total] پیام [action] شد. [failed] پیام با خطا مواجه شد', + BULK_ACTION_FAILED = 'هیچ پیامی [action] نشد. تمام [total] تلاش ناموفق بود', // Bulk action display names - BULK_ACTION_SEEN = "خوانده شده علامت‌گذاری", - BULK_ACTION_DELETE = "حذف", - BULK_ACTION_ARCHIVE = "آرشیو", - BULK_ACTION_UNARCHIVE = "از آرشیو خارج", - BULK_ACTION_FAVORITE = "به علاقه مندی ها منتقل", - BULK_ACTION_UNFAVORITE = "از علاقه مندی ها حذف", - BULK_ACTION_JUNK = "به جانک منتقل", - BULK_ACTION_NOTJUNK = "از جانک از حذف", - BULK_ACTION_TRASH = "به سطل زباله منتقل", - BULK_ACTION_RESTORE = "از سطل زباله بازیابی", - BULK_ACTION_PROCESSED = "پردازش", - USER_NOT_FOUND = "کاربر یافت نشد", - PRIORITY_MUST_BE_ONE_OF_HIGH_NORMAL_LOW = "اولویت باید یکی از مقادیر high, normal, low باشد", - SUBJECT_REQUIRED = "موضوع ایمیل مورد نیاز است", - ALL_MESSAGES_DELETED_SUCCESSFULLY = "همه پیام ها با موفقیت حذف شدند", - MAILBOX_ID_MUST_BE_MONGO_ID = "شناسه میل باکس ایمیل باید یک آی دی معتبر باشد", - MESSAGE_MARKED_AS_UNSEEN_SUCCESSFULLY = "پیام با موفقیت به عنوان خوانده نشده علامت گذاری شد", - MESSAGE_MARK_AS_UNSEEN_FAILED = "علامت گذاری پیام به عنوان خوانده نشده با خطا مواجه شد", - ATTACHMENT_ID_MUST_BE_STRING = "شناسه پیوست باید یک رشته باشد", - IS_FORWARD_MUST_BE_BOOLEAN = "IS_FORWARD_MUST_BE_BOOLEAN", + BULK_ACTION_SEEN = 'خوانده شده علامت‌گذاری', + BULK_ACTION_DELETE = 'حذف', + BULK_ACTION_ARCHIVE = 'آرشیو', + BULK_ACTION_UNARCHIVE = 'از آرشیو خارج', + BULK_ACTION_FAVORITE = 'به علاقه مندی ها منتقل', + BULK_ACTION_UNFAVORITE = 'از علاقه مندی ها حذف', + BULK_ACTION_JUNK = 'به جانک منتقل', + BULK_ACTION_NOTJUNK = 'از جانک از حذف', + BULK_ACTION_TRASH = 'به سطل زباله منتقل', + BULK_ACTION_RESTORE = 'از سطل زباله بازیابی', + BULK_ACTION_PROCESSED = 'پردازش', + USER_NOT_FOUND = 'کاربر یافت نشد', + PRIORITY_MUST_BE_ONE_OF_HIGH_NORMAL_LOW = 'اولویت باید یکی از مقادیر high, normal, low باشد', + SUBJECT_REQUIRED = 'موضوع ایمیل مورد نیاز است', + ALL_MESSAGES_DELETED_SUCCESSFULLY = 'همه پیام ها با موفقیت حذف شدند', + MAILBOX_ID_MUST_BE_MONGO_ID = 'شناسه میل باکس ایمیل باید یک آی دی معتبر باشد', + MESSAGE_MARKED_AS_UNSEEN_SUCCESSFULLY = 'پیام با موفقیت به عنوان خوانده نشده علامت گذاری شد', + MESSAGE_MARK_AS_UNSEEN_FAILED = 'علامت گذاری پیام به عنوان خوانده نشده با خطا مواجه شد', + ATTACHMENT_ID_MUST_BE_STRING = 'شناسه پیوست باید یک رشته باشد', + IS_FORWARD_MUST_BE_BOOLEAN = 'IS_FORWARD_MUST_BE_BOOLEAN', // Favorite/Star messages (Gmail-like behavior) - MESSAGE_MARKED_AS_FAVORITE_SUCCESSFULLY = "پیام با موفقیت به عنوان مورد علاقه علامت گذاری شد", - MESSAGE_REMOVED_FROM_FAVORITE_SUCCESSFULLY = "پیام با موفقیت از مورد علاقه حذف شد", - TRASH_EMPTYED_SUCCESSFULLY = "سطل زباله با موفقیت خالی شد", - SPAM_EMPTYED_SUCCESSFULLY = "همه پیام های اسپم با موفقیت حذف شدند", - SAVE_DRAFT_SUCCESS = "پیش نویس با موفقیت ذخیره شد", - HTML_CONTENT_REQUIRED = "محتوای HTML مورد نیاز است", - TEXT_CONTENT_REQUIRED = "TEXT_CONTENT_REQUIRED", + MESSAGE_MARKED_AS_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت به عنوان مورد علاقه علامت گذاری شد', + MESSAGE_REMOVED_FROM_FAVORITE_SUCCESSFULLY = 'پیام با موفقیت از مورد علاقه حذف شد', + TRASH_EMPTYED_SUCCESSFULLY = 'سطل زباله با موفقیت خالی شد', + SPAM_EMPTYED_SUCCESSFULLY = 'همه پیام های اسپم با موفقیت حذف شدند', + SAVE_DRAFT_SUCCESS = 'پیش نویس با موفقیت ذخیره شد', + HTML_CONTENT_REQUIRED = 'محتوای HTML مورد نیاز است', + TEXT_CONTENT_REQUIRED = 'TEXT_CONTENT_REQUIRED', } export const enum WebSocketMessage { // Connection Messages - WS_CONNECTION_ESTABLISHED = "اتصال وب سوکت با موفقیت برقرار شد", - WS_CONNECTION_FAILED = "اتصال وب سوکت ناموفق بود", - WS_AUTHENTICATION_REQUIRED = "احراز هویت وب سوکت مورد نیاز است", - WS_AUTHENTICATION_FAILED = "احراز هویت وب سوکت ناموفق بود", - WS_AUTHENTICATION_SUCCESS = "احراز هویت وب سوکت با موفقیت انجام شد", - WS_INVALID_TOKEN = "توکن وب سوکت نامعتبر است", - WS_TOKEN_EXPIRED = "توکن وب سوکت منقضی شده است", + WS_CONNECTION_ESTABLISHED = 'اتصال وب سوکت با موفقیت برقرار شد', + WS_CONNECTION_FAILED = 'اتصال وب سوکت ناموفق بود', + WS_AUTHENTICATION_REQUIRED = 'احراز هویت وب سوکت مورد نیاز است', + WS_AUTHENTICATION_FAILED = 'احراز هویت وب سوکت ناموفق بود', + WS_AUTHENTICATION_SUCCESS = 'احراز هویت وب سوکت با موفقیت انجام شد', + WS_INVALID_TOKEN = 'توکن وب سوکت نامعتبر است', + WS_TOKEN_EXPIRED = 'توکن وب سوکت منقضی شده است', // Room Management Messages - JOINED_ROOM_SUCCESS = "با موفقیت به اتاق متصل شدید", - LEFT_ROOM_SUCCESS = "با موفقیت از اتاق خارج شدید", - ROOM_NOT_FOUND = "اتاق یافت نشد", - UNAUTHORIZED_ROOM_ACCESS = "دسترسی غیرمجاز به اتاق", + JOINED_ROOM_SUCCESS = 'با موفقیت به اتاق متصل شدید', + LEFT_ROOM_SUCCESS = 'با موفقیت از اتاق خارج شدید', + ROOM_NOT_FOUND = 'اتاق یافت نشد', + UNAUTHORIZED_ROOM_ACCESS = 'دسترسی غیرمجاز به اتاق', // Session Management Messages - WS_SESSION_CREATED = "جلسه وب سوکت ایجاد شد", - WS_SESSION_JOINED = "به جلسه وب سوکت پیوستید", - WS_SESSION_LEFT = "از جلسه وب سوکت خارج شدید", - WS_SESSION_EXPIRED = "جلسه وب سوکت منقضی شده است", - WS_SESSION_NOT_FOUND = "جلسه وب سوکت یافت نشد", + WS_SESSION_CREATED = 'جلسه وب سوکت ایجاد شد', + WS_SESSION_JOINED = 'به جلسه وب سوکت پیوستید', + WS_SESSION_LEFT = 'از جلسه وب سوکت خارج شدید', + WS_SESSION_EXPIRED = 'جلسه وب سوکت منقضی شده است', + WS_SESSION_NOT_FOUND = 'جلسه وب سوکت یافت نشد', // Error Messages - WS_CONNECTION_ERROR = "خطا در اتصال وب سوکت", - INVALID_EVENT = "رویداد نامعتبر", - INVALID_DATA = "داده نامعتبر", - WS_RATE_LIMIT_EXCEEDED = "تعداد درخواست‌های وب سوکت از حد مجاز بیشتر است", - INTERNAL_ERROR = "خطای داخلی سرور", + WS_CONNECTION_ERROR = 'خطا در اتصال وب سوکت', + INVALID_EVENT = 'رویداد نامعتبر', + INVALID_DATA = 'داده نامعتبر', + WS_RATE_LIMIT_EXCEEDED = 'تعداد درخواست‌های وب سوکت از حد مجاز بیشتر است', + INTERNAL_ERROR = 'خطای داخلی سرور', // Notification Messages - NEW_MESSAGE_NOTIFICATION = "پیام جدید دریافت شد", - MESSAGE_STATUS_UPDATED = "وضعیت پیام به‌روزرسانی شد", - MESSAGE_MOVED_NOTIFICATION = "پیام جابجا شد", - MESSAGE_DELETED_NOTIFICATION = "پیام حذف شد", + NEW_MESSAGE_NOTIFICATION = 'پیام جدید دریافت شد', + MESSAGE_STATUS_UPDATED = 'وضعیت پیام به‌روزرسانی شد', + MESSAGE_MOVED_NOTIFICATION = 'پیام جابجا شد', + MESSAGE_DELETED_NOTIFICATION = 'پیام حذف شد', // General Messages - OPERATION_SUCCESS = "عملیات با موفقیت انجام شد", - OPERATION_FAILED = "عملیات ناموفق بود", - PERMISSION_DENIED = "مجوز دسترسی ندارید", - RESOURCE_NOT_FOUND = "منبع یافت نشد", + OPERATION_SUCCESS = 'عملیات با موفقیت انجام شد', + OPERATION_FAILED = 'عملیات ناموفق بود', + PERMISSION_DENIED = 'مجوز دسترسی ندارید', + RESOURCE_NOT_FOUND = 'منبع یافت نشد', // Authentication errors - AUTHENTICATION_REQUIRED = "احراز هویت ضروری است", - INVALID_TOKEN = "توکن احراز هویت نامعتبر است", - TOKEN_EXPIRED = "توکن منقضی شده است", - UNAUTHORIZED_ACCESS = "دسترسی غیرمجاز", - USER_NOT_AUTHENTICATED = "کاربر احراز هویت نشده است", + AUTHENTICATION_REQUIRED = 'احراز هویت ضروری است', + INVALID_TOKEN = 'توکن احراز هویت نامعتبر است', + TOKEN_EXPIRED = 'توکن منقضی شده است', + UNAUTHORIZED_ACCESS = 'دسترسی غیرمجاز', + USER_NOT_AUTHENTICATED = 'کاربر احراز هویت نشده است', // Connection errors - CONNECTION_FAILED = "اتصال برقرار نشد", - WEBSOCKET_ERROR = "خطا در ارتباط WebSocket", - CONNECTION_TIMEOUT = "زمان اتصال به پایان رسید", - CONNECTION_REFUSED = "اتصال رد شد", + CONNECTION_FAILED = 'اتصال برقرار نشد', + WEBSOCKET_ERROR = 'خطا در ارتباط WebSocket', + CONNECTION_TIMEOUT = 'زمان اتصال به پایان رسید', + CONNECTION_REFUSED = 'اتصال رد شد', // Session errors - SESSION_NOT_FOUND = "جلسه چت یافت نشد", - SESSION_CREATION_FAILED = "ایجاد جلسه چت با شکست مواجه شد", - SESSION_ACCESS_DENIED = "دسترسی به جلسه چت مجاز نیست", - SESSION_EXPIRED = "جلسه چت منقضی شده است", - SESSION_ALREADY_EXISTS = "جلسه چت قبلاً وجود دارد", + SESSION_NOT_FOUND = 'جلسه چت یافت نشد', + SESSION_CREATION_FAILED = 'ایجاد جلسه چت با شکست مواجه شد', + SESSION_ACCESS_DENIED = 'دسترسی به جلسه چت مجاز نیست', + SESSION_EXPIRED = 'جلسه چت منقضی شده است', + SESSION_ALREADY_EXISTS = 'جلسه چت قبلاً وجود دارد', // Message errors - MESSAGE_TOO_LONG = "پیام از حداکثر طول مجاز تجاوز کرده است", - MESSAGE_EMPTY = "پیام نمی‌تواند خالی باشد", - MESSAGE_SEND_FAILED = "ارسال پیام با شکست مواجه شد", - INVALID_MESSAGE_FORMAT = "فرمت پیام نامعتبر است", + MESSAGE_TOO_LONG = 'پیام از حداکثر طول مجاز تجاوز کرده است', + MESSAGE_EMPTY = 'پیام نمی‌تواند خالی باشد', + MESSAGE_SEND_FAILED = 'ارسال پیام با شکست مواجه شد', + INVALID_MESSAGE_FORMAT = 'فرمت پیام نامعتبر است', // Rate limiting - RATE_LIMIT_EXCEEDED = "تعداد پیام‌های ارسالی بیش از حد مجاز است", - TOO_MANY_CONNECTIONS = "تعداد اتصالات بیش از حد مجاز است", + RATE_LIMIT_EXCEEDED = 'تعداد پیام‌های ارسالی بیش از حد مجاز است', + TOO_MANY_CONNECTIONS = 'تعداد اتصالات بیش از حد مجاز است', // Service errors - LLM_SERVICE_ERROR = "سرویس هوش مصنوعی موقتاً در دسترس نیست", - SERVICE_UNAVAILABLE = "سرویس موقتاً در دسترس نیست", - INTERNAL_SERVER_ERROR = ".خطای داخلی سرور", + LLM_SERVICE_ERROR = 'سرویس هوش مصنوعی موقتاً در دسترس نیست', + SERVICE_UNAVAILABLE = 'سرویس موقتاً در دسترس نیست', + INTERNAL_SERVER_ERROR = '.خطای داخلی سرور', // Validation errors - INVALID_SESSION_ID = "شناسه جلسه نامعتبر است", - INVALID_USER_ID = "شناسه کاربر نامعتبر است", - INVALID_MESSAGE_ID = "شناسه پیام نامعتبر است", - REQUIRED_FIELD_MISSING = "فیلد ضروری موجود نیست", + INVALID_SESSION_ID = 'شناسه جلسه نامعتبر است', + INVALID_USER_ID = 'شناسه کاربر نامعتبر است', + INVALID_MESSAGE_ID = 'شناسه پیام نامعتبر است', + REQUIRED_FIELD_MISSING = 'فیلد ضروری موجود نیست', // Success messages - AUTHENTICATED = "احراز هویت موفقیت‌آمیز", - SESSION_CREATED = "جلسه چت با موفقیت ایجاد شد", - CHAT_JOINED = "با موفقیت به چت متصل شدید", - MESSAGE_SENT = "پیام ارسال شد", - CONNECTION_ESTABLISHED = "اتصال برقرار شد", + AUTHENTICATED = 'احراز هویت موفقیت‌آمیز', + SESSION_CREATED = 'جلسه چت با موفقیت ایجاد شد', + CHAT_JOINED = 'با موفقیت به چت متصل شدید', + MESSAGE_SENT = 'پیام ارسال شد', + CONNECTION_ESTABLISHED = 'اتصال برقرار شد', } export const enum SmsMessage { - SEND_SMS_ERROR = "خطا در ارسال پیامک", + SEND_SMS_ERROR = 'خطا در ارسال پیامک', } export const enum BusinessMessage { - NOT_FOUND = "کسب و کار یافت نشد", - BUSINESS_ID_REQUIRED = "شناسه کسب و کار مورد نیاز است", - SLUG_REQUIRED = "اسلاگ مورد نیاز است", - SLUG_MUST_BE_STRING = "اسلاگ باید یک رشته باشد", - DOMAIN_INVALID = "دامنه وارد شده معتبر نیست", - DOMAIN_UPDATED = "دامنه با موفقیت به‌روزرسانی شد", - DOMAIN_VERIFICATION_INITIATED = "فرآیند تایید دامنه آغاز شد", - DOMAIN_VERIFICATION_FAILED = "تایید دامنه با خطا مواجه شد", - DOMAIN_VERIFICATION_SUCCESS = "دامنه با موفقیت تایید شد", - DOMAIN_VERIFICATION_METHOD_INVALID = "روش تایید دامنه نامعتبر است", - DOMAIN_ALREADY_VERIFIED = "این دامنه قبلا تایید شده است", - DOMAIN_REQUIRED = "دامنه مورد نیاز است", - DOMAIN_MUST_BE_STRING = "دامنه باید یک رشته باشد", - STAFF_NOT_FOUND = "کاربر ادمین یافت نشد", - ZARINPAL_MERCHANT_ID_REQUIRED = "شناسه مرچنت زرین پال مورد نیاز است", - ZARINPAL_MERCHANT_ID_STRING = "شناسه مرچنت زرین پال باید یک رشته باشد", - LOGO_URL_REQUIRED = "آدرس تصویر لوگو مورد نیاز است", - LOGO_URL_STRING = "آدرس تصویر لوگو باید یک رشته باشد", - LOGO_URL_INVALID = "آدرس تصویر لوگو معتبر نیست", - BUSINESS_SETTINGS_UPDATED = "تنظیمات کسب و کار با موفقیت به روز رسانی شد", - NAME_REQUIRED = "نام کسب و کار مورد نیاز است", - NAME_STRING = "نام کسب و کار باید یک رشته باشد", - DOMAIN_CONNECTED = "دامنه با موفقیت متصل شد", - DOMAIN_NOT_CONNECTED = "دامنه به سرور ما متصل نشد", - DOMAIN_NOT_FOUND = "دامنه یافت نشد", - DOMAIN_VERIFICATION_TOKEN_REQUIRED = "توکن تایید دامنه مورد نیاز است", - INSUFFICIENT_QUOTA = "حجم شما برای ساخت ایمیل کافی نمی باشد، لطفا حجم را افزایش دهید", - QUOTA_DOWNGRADE_NOT_ALLOWED = "کاهش حجم ایمیل مجاز نیست، فقط می‌توانید حجم را افزایش دهید", - QUOTA_AMOUNT_REQUIRED = "مقدار حجم مورد نیاز است", - QUOTA_AMOUNT_MUST_BE_NUMBER = "مقدار حجم باید یک عدد باشد", - QUOTA_AMOUNT_MUST_BE_POSITIVE = "مقدار حجم باید مثبت باشد", - CALLBACK_URL_MUST_BE_STRING = "آدرس بازگشت باید یک رشته باشد", - CALLBACK_URL_INVALID = "آدرس بازگشت معتبر نیست", - PURCHASE_DESCRIPTION_MUST_BE_STRING = "توضیحات خرید باید یک رشته باشد", - QUOTA_PURCHASE_SUCCESS = "درخواست خرید حجم با موفقیت ثبت شد", - QUOTA_PURCHASE_FAILED = "خرید حجم با خطا مواجه شد", - PAYMENT_GATEWAY_ERROR = "خطا در اتصال به درگاه پرداخت", - QUOTA_UPDATED = "حجم ایمیل با موفقیت به روز شد", - USER_DOES_NOT_HAVE_ACCESS_TO_SERVICE = "کاربر دسترسی به این سرویس را ندارد", + NOT_FOUND = 'کسب و کار یافت نشد', + BUSINESS_ID_REQUIRED = 'شناسه کسب و کار مورد نیاز است', + SLUG_REQUIRED = 'اسلاگ مورد نیاز است', + SLUG_MUST_BE_STRING = 'اسلاگ باید یک رشته باشد', + DOMAIN_INVALID = 'دامنه وارد شده معتبر نیست', + DOMAIN_UPDATED = 'دامنه با موفقیت به‌روزرسانی شد', + DOMAIN_VERIFICATION_INITIATED = 'فرآیند تایید دامنه آغاز شد', + DOMAIN_VERIFICATION_FAILED = 'تایید دامنه با خطا مواجه شد', + DOMAIN_VERIFICATION_SUCCESS = 'دامنه با موفقیت تایید شد', + DOMAIN_VERIFICATION_METHOD_INVALID = 'روش تایید دامنه نامعتبر است', + DOMAIN_ALREADY_VERIFIED = 'این دامنه قبلا تایید شده است', + DOMAIN_REQUIRED = 'دامنه مورد نیاز است', + DOMAIN_MUST_BE_STRING = 'دامنه باید یک رشته باشد', + STAFF_NOT_FOUND = 'کاربر ادمین یافت نشد', + ZARINPAL_MERCHANT_ID_REQUIRED = 'شناسه مرچنت زرین پال مورد نیاز است', + ZARINPAL_MERCHANT_ID_STRING = 'شناسه مرچنت زرین پال باید یک رشته باشد', + LOGO_URL_REQUIRED = 'آدرس تصویر لوگو مورد نیاز است', + LOGO_URL_STRING = 'آدرس تصویر لوگو باید یک رشته باشد', + LOGO_URL_INVALID = 'آدرس تصویر لوگو معتبر نیست', + BUSINESS_SETTINGS_UPDATED = 'تنظیمات کسب و کار با موفقیت به روز رسانی شد', + NAME_REQUIRED = 'نام کسب و کار مورد نیاز است', + NAME_STRING = 'نام کسب و کار باید یک رشته باشد', + DOMAIN_CONNECTED = 'دامنه با موفقیت متصل شد', + DOMAIN_NOT_CONNECTED = 'دامنه به سرور ما متصل نشد', + DOMAIN_NOT_FOUND = 'دامنه یافت نشد', + DOMAIN_VERIFICATION_TOKEN_REQUIRED = 'توکن تایید دامنه مورد نیاز است', + INSUFFICIENT_QUOTA = 'حجم شما برای ساخت ایمیل کافی نمی باشد، لطفا حجم را افزایش دهید', + QUOTA_DOWNGRADE_NOT_ALLOWED = 'کاهش حجم ایمیل مجاز نیست، فقط می‌توانید حجم را افزایش دهید', + QUOTA_AMOUNT_REQUIRED = 'مقدار حجم مورد نیاز است', + QUOTA_AMOUNT_MUST_BE_NUMBER = 'مقدار حجم باید یک عدد باشد', + QUOTA_AMOUNT_MUST_BE_POSITIVE = 'مقدار حجم باید مثبت باشد', + CALLBACK_URL_MUST_BE_STRING = 'آدرس بازگشت باید یک رشته باشد', + CALLBACK_URL_INVALID = 'آدرس بازگشت معتبر نیست', + PURCHASE_DESCRIPTION_MUST_BE_STRING = 'توضیحات خرید باید یک رشته باشد', + QUOTA_PURCHASE_SUCCESS = 'درخواست خرید حجم با موفقیت ثبت شد', + QUOTA_PURCHASE_FAILED = 'خرید حجم با خطا مواجه شد', + PAYMENT_GATEWAY_ERROR = 'خطا در اتصال به درگاه پرداخت', + QUOTA_UPDATED = 'حجم ایمیل با موفقیت به روز شد', + USER_DOES_NOT_HAVE_ACCESS_TO_SERVICE = 'کاربر دسترسی به این سرویس را ندارد', } export const enum DomainMessage { // Domain Ownership & Verification - NOT_BELONG_TO_BUSINESS = "دامنه به این کسب و کار تعلق ندارد", - NOT_VERIFIED = "دامنه باید تایید شده باشد", - DOMAIN_NOT_FOUND = "دامنه یافت نشد", - DOMAIN_ALREADY_EXISTS = "دامنه [name] قبلا ثبت شده است", - DOMAIN_DELETED_SUCCESSFULLY = "دامنه با موفقیت حذف شد", - VERIFICATION_NOT_FOUND = "تایید دامنه یافت نشد", - NO_DOMAIN_FOUND = "دامنه ای یافت نشد", - DOMAIN_CHECKED = "دامنه با موفقیت بررسی شد", + NOT_BELONG_TO_BUSINESS = 'دامنه به این کسب و کار تعلق ندارد', + NOT_VERIFIED = 'دامنه باید تایید شده باشد', + DOMAIN_NOT_FOUND = 'دامنه یافت نشد', + DOMAIN_ALREADY_EXISTS = 'دامنه [name] قبلا ثبت شده است', + DOMAIN_DELETED_SUCCESSFULLY = 'دامنه با موفقیت حذف شد', + VERIFICATION_NOT_FOUND = 'تایید دامنه یافت نشد', + NO_DOMAIN_FOUND = 'دامنه ای یافت نشد', + DOMAIN_CHECKED = 'دامنه با موفقیت بررسی شد', // Domain Creation & Setup - DOMAIN_CREATED_WITH_RECORDS = "دامنه [name] با موفقیت ایجاد شد و تمام رکوردهای مورد نیاز تولید گردید", - ALL_REQUIRED_RECORDS_GENERATED = "تمام رکوردهای مورد نیاز (MX, SPF, DMARC, DKIM) به طور خودکار برای شما تولید شده‌اند", - ESTIMATED_PROPAGATION_TIME = "تغییرات DNS معمولاً ۱۵ دقیقه تا ۴۸ ساعت در سراسر جهان منتشر می‌شود", + DOMAIN_CREATED_WITH_RECORDS = 'دامنه [name] با موفقیت ایجاد شد و تمام رکوردهای مورد نیاز تولید گردید', + ALL_REQUIRED_RECORDS_GENERATED = 'تمام رکوردهای مورد نیاز (MX, SPF, DMARC, DKIM) به طور خودکار برای شما تولید شده‌اند', + ESTIMATED_PROPAGATION_TIME = 'تغییرات DNS معمولاً ۱۵ دقیقه تا ۴۸ ساعت در سراسر جهان منتشر می‌شود', // DNS Records Instructions - ADD_MX_RECORD = "یک رکورد MX با نام [name] که به [value] با اولویت [priority] اشاره کند اضافه کنید", - ADD_TXT_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید", - ADD_DKIM_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (کلید عمومی DKIM)", - ADD_DMARC_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (سیاست DMARC)", - ADD_CNAME_RECORD = "یک رکورد CNAME با نام [name] که به [value] اشاره کند اضافه کنید", - ADD_GENERIC_RECORD = "یک رکورد [type] با نام [name] و مقدار [value] اضافه کنید", + ADD_MX_RECORD = 'یک رکورد MX با نام [name] که به [value] با اولویت [priority] اشاره کند اضافه کنید', + ADD_TXT_RECORD = 'یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید', + ADD_DKIM_RECORD = 'یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (کلید عمومی DKIM)', + ADD_DMARC_RECORD = 'یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (سیاست DMARC)', + ADD_CNAME_RECORD = 'یک رکورد CNAME با نام [name] که به [value] اشاره کند اضافه کنید', + ADD_GENERIC_RECORD = 'یک رکورد [type] با نام [name] و مقدار [value] اضافه کنید', // Domain Setup Steps - STEP_LOGIN_DNS_PANEL = "وارد پنل مدیریت DNS ثبت کننده دامنه خود شوید", - STEP_ADD_ALL_RECORDS = "تمام رکوردهای DNS مورد نیاز لیست شده در بالا را به زون DNS دامنه خود اضافه کنید", - STEP_INCLUDE_ALL_TYPES = "مطمئن شوید که رکوردهای MX، SPF، DMARC و DKIM را برای عملکرد کامل ایمیل شامل کرده‌اید", - STEP_WAIT_PROPAGATION = "منتظر انتشار DNS بمانید (معمولاً ۱۵ دقیقه تا ۴۸ ساعت)", + STEP_LOGIN_DNS_PANEL = 'وارد پنل مدیریت DNS ثبت کننده دامنه خود شوید', + STEP_ADD_ALL_RECORDS = 'تمام رکوردهای DNS مورد نیاز لیست شده در بالا را به زون DNS دامنه خود اضافه کنید', + STEP_INCLUDE_ALL_TYPES = 'مطمئن شوید که رکوردهای MX، SPF، DMARC و DKIM را برای عملکرد کامل ایمیل شامل کرده‌اید', + STEP_WAIT_PROPAGATION = 'منتظر انتشار DNS بمانید (معمولاً ۱۵ دقیقه تا ۴۸ ساعت)', STEP_USE_CHECK_ENDPOINT = "از نقطه پایانی 'بررسی DNS' برای تایید تنظیم صحیح رکوردهای خود استفاده کنید", - STEP_DOMAIN_READY = "پس از تایید، دامنه شما برای سرویس‌های ایمیل آماده خواهد بود!", + STEP_DOMAIN_READY = 'پس از تایید، دامنه شما برای سرویس‌های ایمیل آماده خواهد بود!', // Status Messages - RECORDS_PENDING_VERIFICATION = "[count] رکورد DNS هنوز در انتظار تایید هستند", - ALL_REQUIRED_RECORDS_MUST_BE_CONFIGURED = "تمام [count] رکورد مورد نیاز باید برای کار درست ایمیل تنظیم شوند", - DOMAIN_FULLY_VERIFIED = "دامنه شما به طور کامل تایید شده و برای ایمیل آماده است!", - EMAIL_ACCOUNTS_READY = "اکنون می‌توانید حساب‌های ایمیل ایجاد کرده و شروع به ارسال/دریافت ایمیل کنید", + RECORDS_PENDING_VERIFICATION = '[count] رکورد DNS هنوز در انتظار تایید هستند', + ALL_REQUIRED_RECORDS_MUST_BE_CONFIGURED = 'تمام [count] رکورد مورد نیاز باید برای کار درست ایمیل تنظیم شوند', + DOMAIN_FULLY_VERIFIED = 'دامنه شما به طور کامل تایید شده و برای ایمیل آماده است!', + EMAIL_ACCOUNTS_READY = 'اکنون می‌توانید حساب‌های ایمیل ایجاد کرده و شروع به ارسال/دریافت ایمیل کنید', // Verification Status - DOMAIN_VERIFICATION_INITIATED = "فرآیند تایید دامنه آغاز شد", - DOMAIN_VERIFICATION_FAILED = "تایید دامنه با خطا مواجه شد", - DOMAIN_VERIFICATION_SUCCESS = "دامنه با موفقیت تایید شد", - DOMAIN_VERIFICATION_PENDING = "تایید دامنه در انتظار است", + DOMAIN_VERIFICATION_INITIATED = 'فرآیند تایید دامنه آغاز شد', + DOMAIN_VERIFICATION_FAILED = 'تایید دامنه با خطا مواجه شد', + DOMAIN_VERIFICATION_SUCCESS = 'دامنه با موفقیت تایید شد', + DOMAIN_VERIFICATION_PENDING = 'تایید دامنه در انتظار است', // DNS Record Status - DNS_RECORD_VERIFIED = "رکورد DNS تایید شد", - DNS_RECORD_FAILED = "رکورد DNS تایید نشد", - DNS_RECORD_NOT_FOUND_OR_MISMATCH = "رکورد DNS یافت نشد یا مقدار مطابقت ندارد", + DNS_RECORD_VERIFIED = 'رکورد DNS تایید شد', + DNS_RECORD_FAILED = 'رکورد DNS تایید نشد', + DNS_RECORD_NOT_FOUND_OR_MISMATCH = 'رکورد DNS یافت نشد یا مقدار مطابقت ندارد', // DKIM Messages - DKIM_ENABLED_AUTOMATICALLY = "DKIM به طور خودکار برای دامنه [name] فعال شد", - DKIM_FAILED_TO_CREATE = "ایجاد DKIM برای دامنه [name] ناموفق بود", - DKIM_ENABLED_SUCCESSFULLY = "DKIM برای دامنه [name] با موفقیت فعال شد", + DKIM_ENABLED_AUTOMATICALLY = 'DKIM به طور خودکار برای دامنه [name] فعال شد', + DKIM_FAILED_TO_CREATE = 'ایجاد DKIM برای دامنه [name] ناموفق بود', + DKIM_ENABLED_SUCCESSFULLY = 'DKIM برای دامنه [name] با موفقیت فعال شد', // Error Messages - FAILED_TO_VERIFY_DOMAIN = "تایید دامنه [name] ناموفق بود", - FAILED_TO_SETUP_MAIL_SERVER = "راه‌اندازی دامنه [name] در سرور ایمیل ناموفق بود", - DOMAIN_CREATION_FAILED = "ایجاد دامنه ناموفق بود", - DNS_VERIFICATION_ATTEMPTS_EXCEEDED = "تعداد تلاش‌های تایید DNS از حد مجاز بیشتر شد", + FAILED_TO_VERIFY_DOMAIN = 'تایید دامنه [name] ناموفق بود', + FAILED_TO_SETUP_MAIL_SERVER = 'راه‌اندازی دامنه [name] در سرور ایمیل ناموفق بود', + DOMAIN_CREATION_FAILED = 'ایجاد دامنه ناموفق بود', + DNS_VERIFICATION_ATTEMPTS_EXCEEDED = 'تعداد تلاش‌های تایید DNS از حد مجاز بیشتر شد', // Service Messages - DOMAIN_UPDATED_SUCCESSFULLY = "دامنه بروزرسانی شد", - VERIFICATION_TOKEN_PREFIX = "توکن تایید: [token]", - RECORD_NEEDS_FIXING = "رکورد [type] برای [name] نیاز به اصلاح دارد: [error]", - RECORD_PENDING_VERIFICATION_DETAIL = "رکورد [type] برای [name] هنوز در انتظار تایید است. لطفا مطمئن شوید که انتشار DNS کامل شده است.", - RECORD_DESCRIPTION_EMAIL_FUNCTIONALITY = "رکورد [type] برای عملکرد ایمیل", - BUSINESS_ALREADY_HAS_DOMAIN = "این کسب و کار قبلا دامنه ای دارد", - CAN_NOT_USE_THIS_DOMAIN = "این دامنه نمیتواند ثبت شود", + DOMAIN_UPDATED_SUCCESSFULLY = 'دامنه بروزرسانی شد', + VERIFICATION_TOKEN_PREFIX = 'توکن تایید: [token]', + RECORD_NEEDS_FIXING = 'رکورد [type] برای [name] نیاز به اصلاح دارد: [error]', + RECORD_PENDING_VERIFICATION_DETAIL = 'رکورد [type] برای [name] هنوز در انتظار تایید است. لطفا مطمئن شوید که انتشار DNS کامل شده است.', + RECORD_DESCRIPTION_EMAIL_FUNCTIONALITY = 'رکورد [type] برای عملکرد ایمیل', + BUSINESS_ALREADY_HAS_DOMAIN = 'این کسب و کار قبلا دامنه ای دارد', + CAN_NOT_USE_THIS_DOMAIN = 'این دامنه نمیتواند ثبت شود', } export const enum MailServerMessage { - FAILED_TO_CREATE_ACCOUNT = "خطا در ایجاد ایمیل", - FAILED_TO_CREATE_DKIM_KEY = "خطا در ایجاد کلید DKIM", + FAILED_TO_CREATE_ACCOUNT = 'خطا در ایجاد ایمیل', + FAILED_TO_CREATE_DKIM_KEY = 'خطا در ایجاد کلید DKIM', } export const enum DnsRecordMessage { - DNS_RECORD_NOT_FOUND = "رکورد DNS یافت نشد", - DNS_RECORD_DELETED = "رکورد DNS با موفقیت حذف شد", + DNS_RECORD_NOT_FOUND = 'رکورد DNS یافت نشد', + DNS_RECORD_DELETED = 'رکورد DNS با موفقیت حذف شد', } export const enum RoleMessage { - NOT_FOUND = "نقش یافت نشد", + NOT_FOUND = 'نقش یافت نشد', } export const enum SignatureMessage { - NAME_NOT_EMPTY = "نام امضاء نمیتواند خالی باشد", - NAME_MAX_LENGTH = "نام امضاء نمیتواند بیشتر از حداکثر طول مجاز باشد", - NAME_STRING = "نام امضاء باید یک رشته باشد", - TEXT_CONTENT_NOT_EMPTY = "محتوای متنی امضاء نمیتواند خالی باشد", - TEXT_CONTENT_STRING = "محتوای متنی امضاء باید یک رشته باشد", - TEXT_CONTENT_MAX_LENGTH = "محتوای متنی امضاء نمیتواند بیشتر از حداکثر طول مجاز باشد", - IS_ACTIVE_NOT_EMPTY = "وضعیت فعال بودن نمیتواند خالی باشد", - IS_ACTIVE_BOOLEAN = "وضعیت فعال بودن باید بولین باشد", - IS_DEFAULT_NOT_EMPTY = "وضعیت پیش فرض نمیتواند خالی باشد", - IS_DEFAULT_BOOLEAN = "وضعیت پیش فرض باید بولین باشد", - CREATED = "امضاء با موفقیت ایجاد شد", - NOT_FOUND = "امضاء یافت نشد", - DELETED = "امضاء با موفقیت حذف شد", - TOGGLE_ACTIVE = "وضعیت امضاء با موفقیت تغییر کرد", + NAME_NOT_EMPTY = 'نام امضاء نمیتواند خالی باشد', + NAME_MAX_LENGTH = 'نام امضاء نمیتواند بیشتر از حداکثر طول مجاز باشد', + NAME_STRING = 'نام امضاء باید یک رشته باشد', + TEXT_CONTENT_NOT_EMPTY = 'محتوای متنی امضاء نمیتواند خالی باشد', + TEXT_CONTENT_STRING = 'محتوای متنی امضاء باید یک رشته باشد', + TEXT_CONTENT_MAX_LENGTH = 'محتوای متنی امضاء نمیتواند بیشتر از حداکثر طول مجاز باشد', + IS_ACTIVE_NOT_EMPTY = 'وضعیت فعال بودن نمیتواند خالی باشد', + IS_ACTIVE_BOOLEAN = 'وضعیت فعال بودن باید بولین باشد', + IS_DEFAULT_NOT_EMPTY = 'وضعیت پیش فرض نمیتواند خالی باشد', + IS_DEFAULT_BOOLEAN = 'وضعیت پیش فرض باید بولین باشد', + CREATED = 'امضاء با موفقیت ایجاد شد', + NOT_FOUND = 'امضاء یافت نشد', + DELETED = 'امضاء با موفقیت حذف شد', + TOGGLE_ACTIVE = 'وضعیت امضاء با موفقیت تغییر کرد', } export const enum TemplateMessage { - TEMPLATE_NOT_FOUND = "قالب یافت نشد", - TEMPLATE_CREATED_SUCCESSFULLY = "قالب با موفقیت ایجاد شد", - TEMPLATE_UPDATED_SUCCESSFULLY = "قالب با موفقیت به روزرسانی شد", - TEMPLATE_DELETED_SUCCESSFULLY = "قالب با موفقیت حذف شد", - TEMPLATE_RETRIEVED_SUCCESSFULLY = "قالب با موفقیت دریافت شد", - TEMPLATES_LISTED_SUCCESSFULLY = "لیست قالب ها با موفقیت دریافت شد", - TEMPLATE_NAME_REQUIRED = "نام قالب الزامی است", - TEMPLATE_NAME_STRING = "نام قالب باید یک رشته باشد", - TEMPLATE_NAME_MAX_LENGTH = "نام قالب نمیتواند بیشتر از ۲۵۵ کاراکتر باشد", - TEMPLATE_STRUCTURE_REQUIRED = "ساختار قالب الزامی است", - TEMPLATE_STRUCTURE_VALID = "ساختار قالب باید معتبر باشد", - TEMPLATE_RAW_HTML_STRING = "HTML خام باید یک رشته باشد", - TEMPLATE_BUSINESS_ID_REQUIRED = "شناسه کسب و کار الزامی است", - TEMPLATE_BUSINESS_ID_UUID = "شناسه کسب و کار باید یک UUID معتبر باشد", - TEMPLATE_ID_REQUIRED = "شناسه قالب الزامی است", - TEMPLATE_ID_UUID = "شناسه قالب باید یک UUID معتبر باشد", - TEMPLATE_ACCESS_DENIED = "شما دسترسی به این قالب را ندارید", - TEMPLATE_BUSINESS_NOT_FOUND = "کسب و کار مالک قالب یافت نشد", - SEARCH_STRING = "نام برای جستجو باید یک رشته باشد", - TEMPLATE_SELECTED_SUCCESSFULLY = "وضعیت قالب با موفقیت تغییر کرد", - TEMPLATE_THUMBNAIL_URL_VALID = "آدرس تصویر قالب باید یک آدرس معتبر باشد", - TEMPLATE_RAW_HTML_REQUIRED = "HTML خام قالب الزامی است", + TEMPLATE_NOT_FOUND = 'قالب یافت نشد', + TEMPLATE_CREATED_SUCCESSFULLY = 'قالب با موفقیت ایجاد شد', + TEMPLATE_UPDATED_SUCCESSFULLY = 'قالب با موفقیت به روزرسانی شد', + TEMPLATE_DELETED_SUCCESSFULLY = 'قالب با موفقیت حذف شد', + TEMPLATE_RETRIEVED_SUCCESSFULLY = 'قالب با موفقیت دریافت شد', + TEMPLATES_LISTED_SUCCESSFULLY = 'لیست قالب ها با موفقیت دریافت شد', + TEMPLATE_NAME_REQUIRED = 'نام قالب الزامی است', + TEMPLATE_NAME_STRING = 'نام قالب باید یک رشته باشد', + TEMPLATE_NAME_MAX_LENGTH = 'نام قالب نمیتواند بیشتر از ۲۵۵ کاراکتر باشد', + TEMPLATE_STRUCTURE_REQUIRED = 'ساختار قالب الزامی است', + TEMPLATE_STRUCTURE_VALID = 'ساختار قالب باید معتبر باشد', + TEMPLATE_RAW_HTML_STRING = 'HTML خام باید یک رشته باشد', + TEMPLATE_BUSINESS_ID_REQUIRED = 'شناسه کسب و کار الزامی است', + TEMPLATE_BUSINESS_ID_UUID = 'شناسه کسب و کار باید یک UUID معتبر باشد', + TEMPLATE_ID_REQUIRED = 'شناسه قالب الزامی است', + TEMPLATE_ID_UUID = 'شناسه قالب باید یک UUID معتبر باشد', + TEMPLATE_ACCESS_DENIED = 'شما دسترسی به این قالب را ندارید', + TEMPLATE_BUSINESS_NOT_FOUND = 'کسب و کار مالک قالب یافت نشد', + SEARCH_STRING = 'نام برای جستجو باید یک رشته باشد', + TEMPLATE_SELECTED_SUCCESSFULLY = 'وضعیت قالب با موفقیت تغییر کرد', + TEMPLATE_THUMBNAIL_URL_VALID = 'آدرس تصویر قالب باید یک آدرس معتبر باشد', + TEMPLATE_RAW_HTML_REQUIRED = 'HTML خام قالب الزامی است', } export const enum NotificationMessage { - TITLE_IS_REQUIRED = "عنوان اعلان الزامی است", - TITLE_STRING = "عنوان اعلان باید یک رشته باشد", - MESSAGE_IS_REQUIRED = "متن اعلان الزامی است", - MESSAGE_STRING = "متن اعلان باید یک رشته باشد", - USERID_IS_REQUIRED = "شناسه کاربر الزامی است", - USERID_IS_STRING = "شناسه کاربر باید یک رشته باشد", - USERID_IS_UUID = "شناسه کاربر باید یک UUID معتبر باشد", - TYPE_IS_REQUIRED = "نوع اعلان الزامی است", - TYPE_ENUM = "نوع اعلان باید یک enum معتبر باشد", - NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED = "اعلان یافت نشد یا دسترسی آن را ندارید", - LOGIN_MESSAGE = "ورود با موفقیت انجام شد در تاریخ [loginDate]", - LOGIN = "ورود", - NEW_EMAIL = "ایمیل جدید", - NEW_EMAIL_MESSAGE = "یک ایمیل جدید با موضوع [subject] دریافت شد", - CHANGE_PASSWORD_MESSAGE = "رمز عبور شما با موفقیت تغییر کرد", - CHANGE_PASSWORD = "تغییر رمز عبور", + TITLE_IS_REQUIRED = 'عنوان اعلان الزامی است', + TITLE_STRING = 'عنوان اعلان باید یک رشته باشد', + MESSAGE_IS_REQUIRED = 'متن اعلان الزامی است', + MESSAGE_STRING = 'متن اعلان باید یک رشته باشد', + USERID_IS_REQUIRED = 'شناسه کاربر الزامی است', + USERID_IS_STRING = 'شناسه کاربر باید یک رشته باشد', + USERID_IS_UUID = 'شناسه کاربر باید یک UUID معتبر باشد', + TYPE_IS_REQUIRED = 'نوع اعلان الزامی است', + TYPE_ENUM = 'نوع اعلان باید یک enum معتبر باشد', + NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED = 'اعلان یافت نشد یا دسترسی آن را ندارید', + LOGIN_MESSAGE = 'ورود با موفقیت انجام شد در تاریخ [loginDate]', + LOGIN = 'ورود', + NEW_EMAIL = 'ایمیل جدید', + NEW_EMAIL_MESSAGE = 'یک ایمیل جدید با موضوع [subject] دریافت شد', + CHANGE_PASSWORD_MESSAGE = 'رمز عبور شما با موفقیت تغییر کرد', + CHANGE_PASSWORD = 'تغییر رمز عبور', } export const enum SettingMessageEnum { - SMS_MUST_BE_BOOLEAN = "تنظیمات ارسال پیامک باید یک boolean باشد", - EMAIL_MUST_BE_BOOLEAN = "تنظیمات ارسال ایمیل باید یک boolean باشد", - NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED = "اعلان یافت نشد یا دسترسی آن را ندارید", + SMS_MUST_BE_BOOLEAN = 'تنظیمات ارسال پیامک باید یک boolean باشد', + EMAIL_MUST_BE_BOOLEAN = 'تنظیمات ارسال ایمیل باید یک boolean باشد', + NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED = 'اعلان یافت نشد یا دسترسی آن را ندارید', } export const enum AiMessage { - NO_RESPONSE_FROM_AI_MODEL = "خطا در دریافت پاسخ از مدل AI", - MESSAGE_NOT_FOUND_OR_ACCESS_DENIED = "ایمیل یافت نشد یا دسترسی آن را ندارید", - EMAIL_CONTENT_IS_EMPTY_OR_COULD_NOT_BE_EXTRACTED = "محتوای ایمیل خالی است یا قابل استخراج نیست", - DESCRIPTION_IS_REQUIRED = "شرح و هدف قالب الزامی است", - DESCRIPTION_MUST_BE_A_STRING = "شرح قالب باید یک رشته باشد", - DESCRIPTION_MUST_BE_AT_LEAST_10_CHARACTERS = "شرح قالب باید حداقل ۱۰ کاراکتر باشد", - DESCRIPTION_MUST_BE_LESS_THAN_500_CHARACTERS = "شرح قالب نمی‌تواند بیشتر از ۵۰۰ کاراکتر باشد", - THEME_MUST_BE_A_VALID_VALUE = "تم قالب باید یکی از مقادیر مجاز باشد", - STYLE_MUST_BE_A_VALID_VALUE = "سبک قالب باید یکی از مقادیر مجاز باشد", - PURPOSE_MUST_BE_A_VALID_VALUE = "هدف قالب باید یکی از مقادیر مجاز باشد", - TEMPLATE_NAME_MUST_BE_A_STRING = "نام قالب باید یک رشته باشد", - TEMPLATE_NAME_MUST_BE_LESS_THAN_100_CHARACTERS = "نام قالب نمی‌تواند بیشتر از ۱۰۰ کاراکتر باشد", - PREFERRED_COLORS_MUST_BE_A_STRING = "رنگ‌های ترجیحی باید یک رشته باشد", - PREFERRED_COLORS_MUST_BE_LESS_THAN_200_CHARACTERS = "رنگ‌های ترجیحی نمی‌تواند بیشتر از ۲۰۰ کاراکتر باشد", - PREFERRED_COLORS_IS_REQUIRED = "رنگ‌های ترجیحی الزامی است", + NO_RESPONSE_FROM_AI_MODEL = 'خطا در دریافت پاسخ از مدل AI', + MESSAGE_NOT_FOUND_OR_ACCESS_DENIED = 'ایمیل یافت نشد یا دسترسی آن را ندارید', + EMAIL_CONTENT_IS_EMPTY_OR_COULD_NOT_BE_EXTRACTED = 'محتوای ایمیل خالی است یا قابل استخراج نیست', + DESCRIPTION_IS_REQUIRED = 'شرح و هدف قالب الزامی است', + DESCRIPTION_MUST_BE_A_STRING = 'شرح قالب باید یک رشته باشد', + DESCRIPTION_MUST_BE_AT_LEAST_10_CHARACTERS = 'شرح قالب باید حداقل ۱۰ کاراکتر باشد', + DESCRIPTION_MUST_BE_LESS_THAN_500_CHARACTERS = 'شرح قالب نمی‌تواند بیشتر از ۵۰۰ کاراکتر باشد', + THEME_MUST_BE_A_VALID_VALUE = 'تم قالب باید یکی از مقادیر مجاز باشد', + STYLE_MUST_BE_A_VALID_VALUE = 'سبک قالب باید یکی از مقادیر مجاز باشد', + PURPOSE_MUST_BE_A_VALID_VALUE = 'هدف قالب باید یکی از مقادیر مجاز باشد', + TEMPLATE_NAME_MUST_BE_A_STRING = 'نام قالب باید یک رشته باشد', + TEMPLATE_NAME_MUST_BE_LESS_THAN_100_CHARACTERS = 'نام قالب نمی‌تواند بیشتر از ۱۰۰ کاراکتر باشد', + PREFERRED_COLORS_MUST_BE_A_STRING = 'رنگ‌های ترجیحی باید یک رشته باشد', + PREFERRED_COLORS_MUST_BE_LESS_THAN_200_CHARACTERS = 'رنگ‌های ترجیحی نمی‌تواند بیشتر از ۲۰۰ کاراکتر باشد', + PREFERRED_COLORS_IS_REQUIRED = 'رنگ‌های ترجیحی الزامی است', } export const enum TwoFactorMessage { - TWO_FACTOR_SETUP_INITIATED = "راه‌اندازی احراز هویت دو مرحله‌ای با موفقیت آغاز شد", - TWO_FACTOR_ENABLED_SUCCESSFULLY = "احراز هویت دو مرحله‌ای با موفقیت فعال شد", - TWO_FACTOR_DISABLED_SUCCESSFULLY = "احراز هویت دو مرحله‌ای با موفقیت غیرفعال شد", - TWO_FACTOR_SETUP_FAILED = "راه‌اندازی احراز هویت دو مرحله‌ای ناموفق بود", - TWO_FACTOR_ENABLE_FAILED = "فعال‌سازی احراز هویت دو مرحله‌ای ناموفق بود", - TWO_FACTOR_TOKEN_VERIFIED_SUCCESSFULLY = "کد احراز هویت دو مرحله‌ای با موفقیت تأیید شد", - TWO_FACTOR_TOKEN_VERIFIED_FAILED = "کد احراز هویت دو مرحله‌ای نامعتبر می‌باشد", - TWO_FACTOR_NOT_ENABLED = "احراز هویت دو مرحله‌ای فعال نیست", - TWO_FACTOR_BACKUP_CODES_GENERATED_SUCCESSFULLY = "کدهای پشتیبان با موفقیت تولید شدند", - TWO_FACTOR_BACKUP_CODE_VERIFIED_SUCCESSFULLY = "کد پشتیبان با موفقیت تأیید شد", - TWO_FACTOR_BACKUP_CODE_VERIFIED_FAILED = "کد پشتیبان نامعتبر است", - TWO_FACTOR_TOKEN_REQUIRED = "کد احراز هویت دو مرحله‌ای الزامی است", - TWO_FACTOR_TOKEN_INVALID = "کد احراز هویت دو مرحله‌ای نامعتبر است", + TWO_FACTOR_SETUP_INITIATED = 'راه‌اندازی احراز هویت دو مرحله‌ای با موفقیت آغاز شد', + TWO_FACTOR_ENABLED_SUCCESSFULLY = 'احراز هویت دو مرحله‌ای با موفقیت فعال شد', + TWO_FACTOR_DISABLED_SUCCESSFULLY = 'احراز هویت دو مرحله‌ای با موفقیت غیرفعال شد', + TWO_FACTOR_SETUP_FAILED = 'راه‌اندازی احراز هویت دو مرحله‌ای ناموفق بود', + TWO_FACTOR_ENABLE_FAILED = 'فعال‌سازی احراز هویت دو مرحله‌ای ناموفق بود', + TWO_FACTOR_TOKEN_VERIFIED_SUCCESSFULLY = 'کد احراز هویت دو مرحله‌ای با موفقیت تأیید شد', + TWO_FACTOR_TOKEN_VERIFIED_FAILED = 'کد احراز هویت دو مرحله‌ای نامعتبر می‌باشد', + TWO_FACTOR_NOT_ENABLED = 'احراز هویت دو مرحله‌ای فعال نیست', + TWO_FACTOR_BACKUP_CODES_GENERATED_SUCCESSFULLY = 'کدهای پشتیبان با موفقیت تولید شدند', + TWO_FACTOR_BACKUP_CODE_VERIFIED_SUCCESSFULLY = 'کد پشتیبان با موفقیت تأیید شد', + TWO_FACTOR_BACKUP_CODE_VERIFIED_FAILED = 'کد پشتیبان نامعتبر است', + TWO_FACTOR_TOKEN_REQUIRED = 'کد احراز هویت دو مرحله‌ای الزامی است', + TWO_FACTOR_TOKEN_INVALID = 'کد احراز هویت دو مرحله‌ای نامعتبر است', } diff --git a/src/modules/admin/entities/role.entity.ts b/src/modules/admin/entities/role.entity.ts new file mode 100644 index 0000000..39204d8 --- /dev/null +++ b/src/modules/admin/entities/role.entity.ts @@ -0,0 +1,14 @@ +import { Collection, Entity, Enum, OneToMany } from '@mikro-orm/core'; + +import { User } from '../../users/entities/user.entity'; +import { BaseEntity } from '../../../common/entities/base.entity'; +import { RoleEnum } from '../enums/role.enum'; + +@Entity() +export class Role extends BaseEntity { + @Enum({ items: () => RoleEnum, nativeEnumName: 'role_enum', default: RoleEnum.USER }) + name!: RoleEnum; + + @OneToMany(() => User, user => user.role) + users = new Collection(this); +} diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 4c2eb77..2880e5f 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -1,5 +1,5 @@ import { Controller, Post, Body } from '@nestjs/common'; -import { AuthService } from './auth.service'; +import { AuthService } from './services/auth.service'; import { RequestOtpDto } from './dto/request-otp.dto'; import { ApiTags, ApiOperation, ApiBody, ApiResponse } from '@nestjs/swagger'; import { VerifyOtpDto } from './dto/verify-otp.dto copy'; diff --git a/src/modules/auth/auth.module.ts b/src/modules/auth/auth.module.ts index cf83db6..f864691 100644 --- a/src/modules/auth/auth.module.ts +++ b/src/modules/auth/auth.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; -import { AuthService } from './auth.service'; +import { AuthService } from './services/auth.service'; import { AuthController } from './auth.controller'; import { UtilsModule } from '../utils/utils.module'; -import { UserModule } from '../user/user.module'; +import { UserModule } from '../users/user.module'; import { JwtModule } from '@nestjs/jwt'; import { ConfigService } from '@nestjs/config'; import { AdminModule } from '../admin/admin.module'; diff --git a/src/common/guards/auth.admin.guard.ts b/src/modules/auth/guards/auth.admin.guard.ts similarity index 100% rename from src/common/guards/auth.admin.guard.ts rename to src/modules/auth/guards/auth.admin.guard.ts diff --git a/src/common/guards/auth.guard.ts b/src/modules/auth/guards/auth.guard.ts similarity index 100% rename from src/common/guards/auth.guard.ts rename to src/modules/auth/guards/auth.guard.ts diff --git a/src/modules/auth/interfaces/IToken-payload.ts b/src/modules/auth/interfaces/IToken-payload.ts new file mode 100755 index 0000000..fe727ab --- /dev/null +++ b/src/modules/auth/interfaces/IToken-payload.ts @@ -0,0 +1,15 @@ +import { RoleEnum } from "../../users/enums/role.enum"; + +export interface ILocalTokenPayload { + id: string; + role: RoleEnum; + wildduckUserId: string; +} + +export interface IConsoleTokenPayload { + id: string; + permissions?: string[]; + isAdmin?: boolean; +} + +export interface ITokenPayload extends ILocalTokenPayload, IConsoleTokenPayload {} diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/services/auth.service.ts similarity index 88% rename from src/modules/auth/auth.service.ts rename to src/modules/auth/services/auth.service.ts index e205c78..5dc3758 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/services/auth.service.ts @@ -1,12 +1,12 @@ import { Injectable, BadRequestException, UnauthorizedException, NotFoundException } from '@nestjs/common'; -import { RequestOtpDto } from './dto/request-otp.dto'; -import { CacheService } from '../utils/cache.service'; -import { SmsService } from '../utils/sms.service'; -import { UserService } from '../user/user.service'; +import { RequestOtpDto } from '../dto/request-otp.dto'; +import { CacheService } from '../../utils/cache.service'; +import { SmsService } from '../../utils/sms.service'; +import { UserService } from '../../users/user.service'; import { randomInt } from 'crypto'; import { JwtService } from '@nestjs/jwt'; -import { AdminService } from '../admin/admin.service'; -import { AuthEntityType } from 'src/common/guards/auth.guard'; +import { AdminService } from '../../admin/admin.service'; +import { AuthEntityType } from 'src/modules/auth/guards/auth.guard'; @Injectable() export class AuthService { diff --git a/src/modules/auth/services/tokens.service.ts b/src/modules/auth/services/tokens.service.ts new file mode 100755 index 0000000..1360476 --- /dev/null +++ b/src/modules/auth/services/tokens.service.ts @@ -0,0 +1,154 @@ +import { randomBytes } from 'node:crypto'; + +import { EntityManager } from '@mikro-orm/postgresql'; +import { BadRequestException, Injectable, Logger, UnauthorizedException } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { JwtService } from '@nestjs/jwt'; +import dayjs from 'dayjs'; + +import { AuthMessage, UserMessage } from '../../../common/enums/message.enum'; +import { RefreshToken } from '../../users/entities/refresh-token.entity'; +import { User } from '../../users/entities/user.entity'; +import { ITokenPayload } from '../interfaces/IToken-payload'; + +@Injectable() +export class TokensService { + private readonly logger = new Logger(TokensService.name); + constructor( + private readonly configService: ConfigService, + private readonly jwtService: JwtService, + private readonly em: EntityManager, + ) {} + + async generateTokens(user: User, em?: EntityManager) { + return this.generateAccessAndRefreshToken( + { + id: user.id, + role: user.role.name, + }, + em, + ); + } + + private async generateAccessAndRefreshToken(payload: ITokenPayload, em?: EntityManager) { + const accessExpire = this.configService.getOrThrow('ACCESS_TOKEN_EXPIRE'); + const refreshExpire = this.configService.getOrThrow('REFRESH_TOKEN_EXPIRE'); + + const accessToken = await this.jwtService.signAsync(payload, { expiresIn: `${accessExpire}m` }); + const refreshToken = await this.generateRefreshToken(); + + await this.storeRefreshToken(payload.id, refreshToken, em); + + return { + accessToken: { token: accessToken, expire: dayjs().add(accessExpire, 'minute').valueOf() }, + refreshToken: { token: refreshToken, expire: dayjs().add(refreshExpire, 'day').valueOf() }, + }; + } + + async storeRefreshToken(userId: string, refreshToken: string, em?: EntityManager) { + const entityManager = em || this.em.fork(); + const isExternalTransaction = !!em && em.isInTransaction(); + + try { + // Only start transaction if no external EntityManager with transaction is provided + if (!isExternalTransaction && !entityManager.isInTransaction()) { + await entityManager.begin(); + } + + const refreshExpire = this.configService.getOrThrow('REFRESH_TOKEN_EXPIRE'); + const expiresAt = dayjs().add(refreshExpire, 'day').toDate(); + + const user = await entityManager.findOne(User, { id: userId }); + if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND); + + const token = entityManager.create(RefreshToken, { + token: refreshToken, + user, + expiresAt, + }); + + // Use persist instead of persistAndFlush when in transaction + if (isExternalTransaction) { + await entityManager.persist(token); + } else { + await entityManager.persistAndFlush(token); + if (entityManager.isInTransaction()) { + await entityManager.commit(); + } + } + } catch (error) { + this.logger.error(error); + // Only rollback if we started the transaction + if (!isExternalTransaction && entityManager.isInTransaction()) { + await entityManager.rollback(); + } + throw error; + } + } + + async refreshToken(oldRefreshToken: string) { + const entityManager = this.em.fork(); + + try { + await entityManager.begin(); + + const token = await entityManager.findOne( + RefreshToken, + { token: oldRefreshToken }, + { + populate: ['user', 'user.role'], + }, + ); + + if (!token) throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN); + + if (dayjs(token.expiresAt).isBefore(dayjs())) { + await entityManager.remove(token); + await entityManager.flush(); + await entityManager.commit(); + throw new UnauthorizedException(AuthMessage.REFRESH_TOKEN_EXPIRED); + } + + // Remove the old token + await entityManager.remove(token); + + // Generate new tokens within the same transaction + const tokens = await this.generateTokens(token.user, entityManager); + + // Commit the transaction + await entityManager.flush(); + await entityManager.commit(); + + return tokens; + } catch (error) { + this.logger.error(error); + if (entityManager.isInTransaction()) { + await entityManager.rollback(); + } + throw error; + } + } + + async invalidateRefreshToken(userId: string) { + const entityManager = this.em.fork(); + + try { + await entityManager.begin(); + + await entityManager.nativeDelete(RefreshToken, { user: { id: userId } }); + this.logger.log(`Successfully deleted all refresh tokens for user ${userId}`); + + await entityManager.commit(); + } catch (error) { + this.logger.error(error); + if (entityManager.isInTransaction()) { + await entityManager.rollback(); + } + throw error; + } + } + + private async generateRefreshToken() { + return randomBytes(32).toString('hex'); + } +} diff --git a/src/modules/submition/entities/submition.entity.ts b/src/modules/submition/entities/submition.entity.ts index e44f24f..c3e2e27 100644 --- a/src/modules/submition/entities/submition.entity.ts +++ b/src/modules/submition/entities/submition.entity.ts @@ -1,5 +1,5 @@ import { Entity, Enum, PrimaryKey, Property, OptionalProps, ManyToOne } from '@mikro-orm/core'; -import { User } from '../../user/entities/user.entity'; +import { User } from '../../users/entities/user.entity'; export enum SubmitionStatus { finished = 'تکمیل', diff --git a/src/modules/submition/submition.controller.ts b/src/modules/submition/submition.controller.ts index 79c3fb5..b0da0d9 100644 --- a/src/modules/submition/submition.controller.ts +++ b/src/modules/submition/submition.controller.ts @@ -13,11 +13,11 @@ import { Delete, } from '@nestjs/common'; import { ApiTags, ApiBearerAuth, ApiOperation, ApiBody, ApiParam } from '@nestjs/swagger'; -import { AuthGuard, type AuthRequest } from 'src/common/guards/auth.guard'; +import { AuthGuard, type AuthRequest } from 'src/modules/auth/guards/auth.guard'; import { SubmitionService } from './submition.service'; import { UpdateSubmissioncDto } from './dto/update-submission.dto'; import { UpdateDocsDto } from './dto/update-docs.dto'; -import { AdminAuthGuard } from 'src/common/guards/auth.admin.guard'; +import { AdminAuthGuard } from 'src/modules/auth/guards/auth.admin.guard'; import { FindSubmitionsDto } from './dto/find-submitions.dto'; import { CreateSubmissioncDto } from './dto/create-submission.dto'; import { SubmitionStatus } from './entities/submition.entity'; diff --git a/src/modules/uploader/uploader.controller.ts b/src/modules/uploader/uploader.controller.ts index 737a700..9bbc20c 100644 --- a/src/modules/uploader/uploader.controller.ts +++ b/src/modules/uploader/uploader.controller.ts @@ -4,7 +4,7 @@ import { ApiBody, ApiConsumes, ApiOperation, ApiBearerAuth } from '@nestjs/swagg import { UploadMultipleFileDto, UploadSingleFileDto } from './DTO/upload-file.dto'; import { UploaderService } from './providers/uploader.service'; -import { AuthGuard } from 'src/common/guards/auth.guard'; +import { AuthGuard } from 'src/modules/auth/guards/auth.guard'; @Controller('uploader') export class UploaderController { diff --git a/src/modules/user/entities/user.entity.ts b/src/modules/user/entities/user.entity.ts deleted file mode 100644 index b2226a9..0000000 --- a/src/modules/user/entities/user.entity.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Entity, Enum, PrimaryKey, Property, OptionalProps, OneToMany, Collection } from '@mikro-orm/core'; -import { Submition } from '../../submition/entities/submition.entity'; - -export enum EducationLevel { - diploma = 'دیپلم', - associate = 'کاردانی', - bachelor = 'کارشناسی', - master = 'کارشناسی ارشد', - phd = 'دکتری', -} - -export enum UserStatus { - finished = 'finished', - pending = 'pending', -} - -@Entity({ tableName: 'users' }) -export class User { - [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt'; - - @OneToMany(() => Submition, submition => submition.user) - submissions = new Collection(this); - - @PrimaryKey() - id!: number; - - @Property({ nullable: true }) - firstName?: string; - - @Property({ nullable: true }) - lastName?: string; - - @Property({ nullable: true }) - fatherName?: string; - - @Property({ unique: true }) - phone!: string; - - @Property({ nullable: true }) - isMale?: boolean; - - @Property({ unique: true, nullable: true }) - nationalCode?: string; - - @Property({ nullable: true }) - personalCode?: string; - - @Property({ nullable: true }) - hireType?: string; - - @Property({ nullable: true }) - workLocation?: string; - - @Property({ default: 0, nullable: true }) - workExperienceYear?: number; - - @Enum({ items: () => EducationLevel, nullable: true }) - education?: EducationLevel; - - @Enum({ items: () => UserStatus, nullable: true, default: UserStatus.pending }) - status?: UserStatus; - - @Property({ defaultRaw: 'now()', columnType: 'timestamptz' }) - createdAt: Date = new Date(); - - @Property({ onUpdate: () => new Date(), defaultRaw: 'now()', columnType: 'timestamptz' }) - updatedAt: Date = new Date(); -} diff --git a/src/modules/user/dto/find-user.dto.ts b/src/modules/users/dto/find-user.dto.ts similarity index 100% rename from src/modules/user/dto/find-user.dto.ts rename to src/modules/users/dto/find-user.dto.ts diff --git a/src/modules/user/dto/update-user.dto.ts b/src/modules/users/dto/update-user.dto.ts similarity index 100% rename from src/modules/user/dto/update-user.dto.ts rename to src/modules/users/dto/update-user.dto.ts diff --git a/src/modules/users/entities/refresh-token.entity.ts b/src/modules/users/entities/refresh-token.entity.ts new file mode 100644 index 0000000..f7231d2 --- /dev/null +++ b/src/modules/users/entities/refresh-token.entity.ts @@ -0,0 +1,19 @@ +import { Entity, ManyToOne, Opt, Property } from "@mikro-orm/core"; + +import { User } from "./user.entity"; +import { BaseEntity } from "../../../common/entities/base.entity"; + +@Entity() +export class RefreshToken extends BaseEntity { + @Property({ type: "varchar", length: 255 }) + token!: string; + + @ManyToOne(() => User, { deleteRule: "cascade" }) + user!: User; + + @Property({ type: "timestamptz" }) + expiresAt!: Date; + + @Property({ default: false }) + isRevoked: boolean & Opt; +} diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts new file mode 100644 index 0000000..ea50518 --- /dev/null +++ b/src/modules/users/entities/user.entity.ts @@ -0,0 +1,34 @@ +import { Entity, Enum, Property, Filter, BaseEntity } from '@mikro-orm/core'; + +export enum EducationLevel { + diploma = 'دیپلم', + associate = 'کاردانی', + bachelor = 'کارشناسی', + master = 'کارشناسی ارشد', + phd = 'دکتری', +} + +export enum UserStatus { + finished = 'finished', + pending = 'pending', +} + +@Filter({ name: 'notDeleted', cond: { deletedAt: null }, default: true }) +@Entity({ tableName: 'users' }) +export class User extends BaseEntity { + @Property({ nullable: true }) + firstName?: string; + + @Property({ nullable: true }) + lastName?: string; + + @Property({ unique: true }) + phone!: string; + + @Enum({ + items: () => UserStatus, + nullable: true, + default: UserStatus.pending, + }) + status?: UserStatus; +} diff --git a/src/modules/user/user.controller.ts b/src/modules/users/user.controller.ts similarity index 91% rename from src/modules/user/user.controller.ts rename to src/modules/users/user.controller.ts index 12b5d38..92bef0b 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/users/user.controller.ts @@ -1,10 +1,10 @@ import { Controller, Get, Patch, Body, Req, UseGuards, Query, ValidationPipe } from '@nestjs/common'; import { ApiTags, ApiBearerAuth, ApiOperation, ApiBody } from '@nestjs/swagger'; -import { AuthGuard, type AuthRequest } from 'src/common/guards/auth.guard'; +import { AuthGuard, type AuthRequest } from 'src/modules/auth/guards/auth.guard'; import { UserService } from './user.service'; import { UpdateUserDto } from './dto/update-user.dto'; import { FindUsersDto } from './dto/find-user.dto'; -import { AdminAuthGuard } from 'src/common/guards/auth.admin.guard'; +import { AdminAuthGuard } from 'src/modules/auth/guards/auth.admin.guard'; @ApiTags('User') @Controller('user') diff --git a/src/modules/user/user.module.ts b/src/modules/users/user.module.ts similarity index 100% rename from src/modules/user/user.module.ts rename to src/modules/users/user.module.ts diff --git a/src/modules/user/user.service.ts b/src/modules/users/user.service.ts similarity index 100% rename from src/modules/user/user.service.ts rename to src/modules/users/user.service.ts