diff --git a/package.json b/package.json index fdfd24c..e353177 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@nestjs/throttler": "^6.3.0", "@nestjs/typeorm": "^10.0.2", "@types/bcrypt": "^5.0.2", + "aws-sdk": "^2.1692.0", "axios": "^1.7.9", "bcrypt": "^5.1.1", "cache-manager": "^6.3.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d6efe76..10e5cd2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: '@types/bcrypt': specifier: ^5.0.2 version: 5.0.2 + aws-sdk: + specifier: ^2.1692.0 + version: 2.1692.0 axios: specifier: ^1.7.9 version: 1.7.9 @@ -1408,6 +1411,10 @@ packages: avvio@9.1.0: resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + aws-sdk@2.1692.0: + resolution: {integrity: sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw==} + engines: {node: '>= 10.0.0'} + axios@1.7.9: resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} @@ -1488,6 +1495,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -2186,6 +2196,10 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events@1.1.1: + resolution: {integrity: sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==} + engines: {node: '>=0.4.x'} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -2593,6 +2607,9 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + ieee754@1.1.13: + resolution: {integrity: sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2654,6 +2671,10 @@ packages: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2820,6 +2841,9 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -3003,6 +3027,10 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + jmespath@0.16.0: + resolution: {integrity: sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==} + engines: {node: '>= 0.6.0'} + js-beautify@1.15.1: resolution: {integrity: sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==} engines: {node: '>=14'} @@ -3944,6 +3972,9 @@ packages: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} + punycode@1.3.2: + resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -3955,6 +3986,11 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + querystring@0.2.0: + resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} + engines: {node: '>=0.4.x'} + deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4119,6 +4155,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sax@1.2.1: + resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} + schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} @@ -4668,13 +4707,23 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url@0.10.3: + resolution: {integrity: sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + utils-merge@1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@8.0.0: + resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==} + hasBin: true + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -4798,6 +4847,14 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -6400,6 +6457,19 @@ snapshots: '@fastify/error': 4.0.0 fastq: 1.18.0 + aws-sdk@2.1692.0: + dependencies: + buffer: 4.9.2 + events: 1.1.1 + ieee754: 1.1.13 + jmespath: 0.16.0 + querystring: 0.2.0 + sax: 1.2.1 + url: 0.10.3 + util: 0.12.5 + uuid: 8.0.0 + xml2js: 0.6.2 + axios@1.7.9: dependencies: follow-redirects: 1.15.9 @@ -6523,6 +6593,12 @@ snapshots: buffer-from@1.1.2: {} + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -7313,6 +7389,8 @@ snapshots: eventemitter3@5.0.1: {} + events@1.1.1: {} + events@3.3.0: {} execa@0.10.0: @@ -7838,6 +7916,8 @@ snapshots: safer-buffer: 2.1.2 optional: true + ieee754@1.1.13: {} + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -7928,6 +8008,11 @@ snapshots: ipaddr.js@2.2.0: {} + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -8084,6 +8169,8 @@ snapshots: is-docker: 2.2.1 optional: true + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -8467,6 +8554,8 @@ snapshots: jiti@2.4.2: {} + jmespath@0.16.0: {} + js-beautify@1.15.1: dependencies: config-chain: 1.1.13 @@ -9701,6 +9790,8 @@ snapshots: punycode.js@2.3.1: optional: true + punycode@1.3.2: {} + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -9709,6 +9800,8 @@ snapshots: dependencies: side-channel: 1.1.0 + querystring@0.2.0: {} + queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} @@ -9876,6 +9969,8 @@ snapshots: safer-buffer@2.1.2: {} + sax@1.2.1: {} + schema-utils@3.3.0: dependencies: '@types/json-schema': 7.0.15 @@ -10413,10 +10508,25 @@ snapshots: dependencies: punycode: 2.3.1 + url@0.10.3: + dependencies: + punycode: 1.3.2 + querystring: 0.2.0 + util-deprecate@1.0.2: {} + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.0 + is-typed-array: 1.1.15 + which-typed-array: 1.1.18 + utils-merge@1.0.1: {} + uuid@8.0.0: {} + uuid@9.0.1: {} v8-compile-cache-lib@3.0.1: {} @@ -10597,6 +10707,13 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 + xml2js@0.6.2: + dependencies: + sax: 1.2.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + xtend@4.0.2: {} y18n@5.0.8: {} diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 2a503e4..f7ce2cf 100644 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -80,3 +80,11 @@ export const enum CategoryMessage { PARENT_ID_SHOULD_BE_UUID = "شناسه والد باید یک یو یو آی دی باشد", TITLE_EXIST = "دسته بندی با این نام قبلا ثبت شده است", } + +export const enum AnnouncementMessage { + TITLE_IS_REQUIRED = "عنوان اطلاعیه مورد نیاز است", + TITLE_STRING = "عنوان اطلاعیه باید یک رشته باشد", + CONTENT_IS_REQUIRED = "متن اطلاعیه مورد نیاز است", + CONTENT_IS_STRING = "متن اطلاعیه باید رشته باشد", + CONTENT_MUST_BE_LONGER = "متن اطلاعیه باید حداقل ۱۰ کاراکتر باشد", +} diff --git a/src/modules/announcements/DTO/create-announcement.dto.ts b/src/modules/announcements/DTO/create-announcement.dto.ts index 0a8dc34..c8c2dd8 100644 --- a/src/modules/announcements/DTO/create-announcement.dto.ts +++ b/src/modules/announcements/DTO/create-announcement.dto.ts @@ -1,9 +1,11 @@ import { ApiProperty } from "@nestjs/swagger"; -import { ArrayMinSize, IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, MinLength } from "class-validator"; +import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, MinLength } from "class-validator"; + +import { AnnouncementMessage } from "../../../common/enums/message.enum"; export class CreateAnnouncementDto { - @IsNotEmpty({ message: "عنوان نمی‌تواند خالی باشد" }) - @IsString({ message: "عنوان باید رشته باشد" }) + @IsNotEmpty({ message: AnnouncementMessage.TITLE_IS_REQUIRED }) + @IsString({ message: AnnouncementMessage.TITLE_STRING }) @ApiProperty({ type: String, description: "Title of the announcement", @@ -11,9 +13,9 @@ export class CreateAnnouncementDto { }) title: string; - @IsNotEmpty({ message: "متن اطلاعیه نمی‌تواند خالی باشد" }) - @IsString({ message: "متن اطلاعیه باید رشته باشد" }) - @MinLength(10, { message: "متن اطلاعیه باید حداقل ۱۰ کاراکتر باشد" }) + @IsNotEmpty({ message: AnnouncementMessage.CONTENT_IS_REQUIRED }) + @IsString({ message: AnnouncementMessage.CONTENT_IS_STRING }) + @MinLength(10, { message: AnnouncementMessage.CONTENT_MUST_BE_LONGER }) @ApiProperty({ type: String, description: "Content of the announcement", @@ -31,7 +33,6 @@ export class CreateAnnouncementDto { @IsOptional() @IsArray() - @ArrayMinSize(1, { message: "حداقل یک گروه باید انتخاب شود" }) @IsUUID("4", { each: true, message: "شناسه هر گروه باید یک UUID معتبر نسخه ۴ باشد", diff --git a/src/modules/users/providers/users.service.ts b/src/modules/users/providers/users.service.ts index 6fe69a0..c3d64f4 100644 --- a/src/modules/users/providers/users.service.ts +++ b/src/modules/users/providers/users.service.ts @@ -2,7 +2,7 @@ import { BadRequestException, Injectable, Logger } from "@nestjs/common"; import slugify from "slugify"; import { In, Not } from "typeorm"; -import { RoleRepository } from "./roles.repository"; +import { RoleRepository } from "../repositories/roles.repository"; // import { roles } from "../../../../database/seeders/role.seeder"; import { CommonMessage, UserMessage } from "../../../common/enums/message.enum"; import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto"; diff --git a/src/modules/users/providers/roles.repository.ts b/src/modules/users/repositories/roles.repository.ts similarity index 100% rename from src/modules/users/providers/roles.repository.ts rename to src/modules/users/repositories/roles.repository.ts diff --git a/src/modules/users/providers/user-group.repository.ts b/src/modules/users/repositories/user-group.repository.ts similarity index 100% rename from src/modules/users/providers/user-group.repository.ts rename to src/modules/users/repositories/user-group.repository.ts