├── tmp └── uploads │ └── .gitkeep ├── .gitignore ├── src ├── entities │ ├── colors │ │ ├── IColor.ts │ │ └── dtos │ │ │ └── ColorCreateRequest.ts │ ├── payment-method │ │ ├── IPaymentMethod.ts │ │ └── dtos │ │ │ └── PaymentMethodCreateRequest.ts │ ├── user │ │ ├── IUserView.ts │ │ ├── dtos │ │ │ ├── UserCreateRequest.ts │ │ │ └── UserUpdateRequest.ts │ │ ├── IUserPublic.ts │ │ └── IUser.ts │ ├── print-price │ │ ├── dtos │ │ │ ├── PrintPriceUpdateRequest.ts │ │ │ └── PrintPriceCreateRequest.ts │ │ └── IPrintPrice.ts │ ├── product-category │ │ ├── IProductCategory.ts │ │ └── dtos │ │ │ └── ProductCategoryCreateRequest.ts │ ├── notification │ │ ├── dtos │ │ │ ├── NotificationUpdateReadRequest.ts │ │ │ └── NotificationCreateRequest.ts │ │ └── INotification.ts │ ├── support-request │ │ ├── dtos │ │ │ ├── SupportRequestCreateRequest.ts │ │ │ └── SupportRequestUpdateResolvedRequest.ts │ │ └── ISupportRequest.ts │ ├── refresh-token │ │ ├── IRefreshToken.ts │ │ └── dtos │ │ │ └── RefreshTokenCreateRequest.ts │ ├── revoked-token │ │ ├── IRevokedToken.ts │ │ └── dtos │ │ │ └── RevokedTokenCreateOrUpdateRequest.ts │ ├── shopping-cart │ │ ├── dtos │ │ │ └── ShoppingCartAddProductRequest.ts │ │ └── IShoppingCart.ts │ ├── validator-token │ │ ├── IValidatorToken.ts │ │ └── dtos │ │ │ └── ValidatorTokenCreateRequest.ts │ ├── shopping-cart-product │ │ ├── dtos │ │ │ ├── ShoppingCartProductUpdateRequest.ts │ │ │ └── ShoppingCartProductCreateRequest.ts │ │ └── IShoppingCartProduct.ts │ ├── password-recovery-token │ │ ├── IPasswordRecoveryToken.ts │ │ └── dtos │ │ │ └── PasswordRecoveryTokenCreateRequest.ts │ ├── print-order │ │ ├── dtos │ │ │ └── PrintOrderCreateRequest.ts │ │ ├── print │ │ │ ├── dtos │ │ │ │ └── PrintCreateRequest.ts │ │ │ └── IPrint.ts │ │ └── IPrintOrder.ts │ ├── purchase-order-product │ │ ├── dtos │ │ │ └── PurchaseOrderProductCreateRequest.ts │ │ └── IPurchaseOrderProduct.ts │ ├── failed-image-uploaded │ │ ├── IFailedImageUploaded.ts │ │ └── dtos │ │ │ └── FailedImageUploadedCreateRequest.ts │ ├── purchase-order │ │ └── dtos │ │ │ ├── PurchaseOrderUpdateRequest.ts │ │ │ └── PurchaseOrderCreateRequest.ts │ └── product │ │ ├── dtos │ │ ├── ProductCreateRequest.ts │ │ └── ProductUpdateRequest.ts │ │ └── IProduct.ts ├── shared │ ├── filters │ │ ├── PurchaseOrderFilter.ts │ │ ├── RefreshTokenFilter.ts │ │ ├── PasswordRecoveryTokenFilter.ts │ │ ├── PrintFilter.ts │ │ └── PrintOrderFilter.ts │ ├── ListValidatorTokenBy.ts │ └── NotFoundHTMLTemplate.ts ├── modules │ ├── auth │ │ ├── signout │ │ │ ├── SignOutDTO.ts │ │ │ ├── index.ts │ │ │ └── SignOutController.ts │ │ ├── refresh-token │ │ │ ├── RefreshTokenDTO.ts │ │ │ ├── index.ts │ │ │ └── RefreshTokenController.ts │ │ ├── validate │ │ │ ├── ValidateTokenDTO.ts │ │ │ ├── index.ts │ │ │ └── ValidateTokenController.ts │ │ ├── signin │ │ │ ├── SignInDTO.ts │ │ │ ├── index.ts │ │ │ └── SignInController.ts │ │ ├── signup │ │ │ ├── SignUpDTO.ts │ │ │ ├── SignUpController.ts │ │ │ └── index.ts │ │ ├── validate-email │ │ │ ├── index.ts │ │ │ ├── ValidateEmailController.ts │ │ │ └── ValidateEmailUseCase.ts │ │ └── send-new-validate-email │ │ │ ├── SendNewValidateEmailController.ts │ │ │ └── index.ts │ ├── user │ │ ├── recovery-password │ │ │ ├── RecoveryPasswordDTO.ts │ │ │ ├── RecoveryPasswordController.ts │ │ │ └── index.ts │ │ ├── delete-account │ │ │ ├── UserDeleteAccountDTO.ts │ │ │ ├── index.ts │ │ │ └── UserDeleteAccountController.ts │ │ ├── set-password │ │ │ ├── SetPasswordDTO.ts │ │ │ ├── index.ts │ │ │ └── SetPasswordController.ts │ │ ├── updatePassword │ │ │ ├── UpdateUserPasswordDTO.ts │ │ │ ├── index.ts │ │ │ └── UpdateUserPasswordController.ts │ │ ├── listAll │ │ │ ├── ListUsersController.ts │ │ │ ├── ListUsersUseCases.ts │ │ │ └── index.ts │ │ ├── listInactives │ │ │ ├── index.ts │ │ │ ├── ListInactiveUsersUseCases.ts │ │ │ └── ListInactiveUsersController.ts │ │ ├── validate-recovery-password-token │ │ │ ├── index.ts │ │ │ ├── ValidateRecoveryPasswordTokenUseCase.ts │ │ │ └── ValidateRecoveryPasswordTokenController.ts │ │ ├── delete │ │ │ ├── DeleteUserController.ts │ │ │ └── index.ts │ │ ├── update │ │ │ ├── index.ts │ │ │ └── UpdateUserController.ts │ │ ├── listById │ │ │ ├── index.ts │ │ │ ├── ListUserByIdController.ts │ │ │ └── ListUserByIdUseCases.ts │ │ ├── create │ │ │ ├── index.ts │ │ │ └── CreateUserController.ts │ │ └── listByEmail │ │ │ ├── index.ts │ │ │ └── ListUserByEmailController.ts │ ├── print-order │ │ ├── create │ │ │ ├── dtos │ │ │ │ └── RejectedPrintResponse.ts │ │ │ ├── CreatePrintOrderController.ts │ │ │ └── index.ts │ │ ├── delete │ │ │ ├── DeletePrintOrderController.ts │ │ │ └── index.ts │ │ ├── listAll │ │ │ ├── index.ts │ │ │ └── ListPrintOrdersController.ts │ │ ├── listById │ │ │ ├── ListPrintOrderByIdController.ts │ │ │ ├── index.ts │ │ │ └── ListPrintOrderByIdUseCases.ts │ │ ├── listByUserId │ │ │ ├── ListPrintOrdersByUserIdController.ts │ │ │ └── index.ts │ │ ├── updateStatus │ │ │ └── UpdatePrintOrderStatusController.ts │ │ └── listByUserIdStatus │ │ │ └── index.ts │ ├── print │ │ ├── listByProperties │ │ │ ├── index.ts │ │ │ ├── ListPrintsUseCases.ts │ │ │ └── ListPrintsController.ts │ │ └── create │ │ │ └── CreatePrintController.ts │ ├── product │ │ ├── delete │ │ │ ├── index.ts │ │ │ └── DeleteProductController.ts │ │ ├── listById │ │ │ ├── index.ts │ │ │ ├── ListProductByIdController.ts │ │ │ └── ListProductByIdUseCases.ts │ │ ├── listAll │ │ │ ├── index.ts │ │ │ └── ListProductsController.ts │ │ ├── create │ │ │ ├── index.ts │ │ │ └── CreateProductController.ts │ │ └── update │ │ │ └── index.ts │ ├── colors │ │ ├── listAll │ │ │ ├── ListColorsUseCases.ts │ │ │ ├── ListColorsController.ts │ │ │ └── index.ts │ │ ├── delete │ │ │ ├── DeleteColorController.ts │ │ │ └── index.ts │ │ ├── create │ │ │ ├── index.ts │ │ │ └── CreateColorController.ts │ │ ├── listByColor │ │ │ ├── index.ts │ │ │ ├── ListByColorController.ts │ │ │ └── ListByColorUseCases.ts │ │ └── listById │ │ │ ├── ListColorByIdController.ts │ │ │ ├── index.ts │ │ │ └── ListColorByIdUseCases.ts │ ├── shopping-cart │ │ ├── listAll │ │ │ ├── index.ts │ │ │ ├── ListShoppingCartsController.ts │ │ │ └── ListShoppingCartsUseCases.ts │ │ ├── listShoppingCartProduct │ │ │ ├── index.ts │ │ │ └── ListShoppingCartProductController.ts │ │ ├── deleteShoppingCartProducts │ │ │ ├── index.ts │ │ │ └── DeleteShoppingCartProductsController.ts │ │ ├── listByUserId │ │ │ ├── index.ts │ │ │ └── ListShoppingCartByUserIdController.ts │ │ └── addShoppingCartProduct │ │ │ ├── index.ts │ │ │ └── AddShoppingCartProductController.ts │ ├── payment-method │ │ ├── listAll │ │ │ ├── index.ts │ │ │ ├── ListPaymentMethodsController.ts │ │ │ └── ListPaymentMethodsUseCases.ts │ │ ├── create │ │ │ ├── index.ts │ │ │ ├── CreatePaymentMethodController.ts │ │ │ └── CreatePaymentMethodUseCases.ts │ │ ├── delete │ │ │ ├── index.ts │ │ │ ├── DeletePaymentMethodController.ts │ │ │ └── DeletePaymentMethodUseCaes.ts │ │ └── listById │ │ │ ├── index.ts │ │ │ ├── ListPaymentMethodByIdController.ts │ │ │ └── ListPaymentMethodByIdUseCases.ts │ ├── purchase-order │ │ ├── delete │ │ │ ├── index.ts │ │ │ └── DeletePurchaseOrderController.ts │ │ ├── update │ │ │ ├── index.ts │ │ │ └── UpdatePurchaseOrderController.ts │ │ ├── listById │ │ │ ├── index.ts │ │ │ └── ListPurchaseOrderByIdController.ts │ │ ├── listAll │ │ │ ├── index.ts │ │ │ └── ListPurchaseOrdersController.ts │ │ ├── create │ │ │ ├── CreatePurchaseOrderController.ts │ │ │ └── index.ts │ │ └── updatePaymentMethod │ │ │ ├── index.ts │ │ │ └── UpdatePurchaseOrderPaymentMethodController.ts │ ├── support-request │ │ ├── listAll │ │ │ ├── index.ts │ │ │ ├── ListSupportRequestsController.ts │ │ │ └── ListSupportRequestsUseCase.ts │ │ ├── delete │ │ │ ├── index.ts │ │ │ ├── DeleteSupportRequestController.ts │ │ │ └── DeleteSupportRequestUseCase.ts │ │ ├── updateResolved │ │ │ ├── index.ts │ │ │ └── UpdateSupportRequestController.ts │ │ └── create │ │ │ ├── index.ts │ │ │ └── SupportRequestCreateController.ts │ ├── print-price │ │ ├── listAll │ │ │ ├── ListPrintPricesController.ts │ │ │ ├── ListPrintPricesUseCases.ts │ │ │ └── index.ts │ │ ├── delete │ │ │ ├── DeletePrintPriceController.ts │ │ │ └── index.ts │ │ ├── create │ │ │ ├── index.ts │ │ │ └── CreatePrintPriceController.ts │ │ ├── listByLength │ │ │ ├── ListPrintPriceByLengthController.ts │ │ │ ├── index.ts │ │ │ └── ListPrintPriceByLengthUseCases.ts │ │ └── updatePrice │ │ │ ├── UpdatePricePrintPriceController.ts │ │ │ └── index.ts │ ├── notification │ │ ├── listAll │ │ │ ├── ListAllNotificationsUseCases.ts │ │ │ ├── ListAllNotificationController.ts │ │ │ └── index.ts │ │ ├── delete │ │ │ ├── DeleteNotificationController.ts │ │ │ └── index.ts │ │ ├── listById │ │ │ ├── ListNotificationByIdController.ts │ │ │ ├── index.ts │ │ │ └── ListNotificationByIdUseCases.ts │ │ ├── create │ │ │ ├── CreateNotificationController.ts │ │ │ └── index.ts │ │ ├── listByUserId │ │ │ ├── ListNotificationsByUserIdController.ts │ │ │ └── index.ts │ │ └── updateRead │ │ │ ├── UpdateReadNotificationController.ts │ │ │ └── index.ts │ ├── product-category │ │ ├── delete │ │ │ ├── index.ts │ │ │ ├── DeleteProductCategoryController.ts │ │ │ └── DeleteProductCategoryUseCases.ts │ │ ├── listAll │ │ │ ├── index.ts │ │ │ ├── ListProductCategoriesController.ts │ │ │ └── ListProductCategoriesUseCases.ts │ │ ├── listById │ │ │ ├── index.ts │ │ │ ├── ListProductCategoryByIdController.ts │ │ │ └── ListProductCategoryByIdUseCases.ts │ │ └── create │ │ │ ├── CreateProductCategoryController.ts │ │ │ ├── index.ts │ │ │ └── CreateProductCategoryUseCases.ts │ └── failed-images-uploaded │ │ ├── listAll │ │ ├── index.ts │ │ ├── ListFailedImagesUploadedController.ts │ │ └── ListFailedImagesUploadedUseCases.ts │ │ ├── create │ │ ├── index.ts │ │ └── CreateFailedImageUploadedController.ts │ │ ├── deleteAll │ │ ├── index.ts │ │ └── DeleteFailedImagesUploadedController.ts │ │ ├── listByKey │ │ ├── index.ts │ │ └── ListFailedImageUploadedByKeyController.ts │ │ └── deleteByKey │ │ ├── index.ts │ │ └── DeleteFailedImageUploadedByKeyController.ts ├── database │ └── index.ts ├── errors │ ├── ConflictRequestError.ts │ ├── IDNotGivenError.ts │ ├── NotFoundError.ts │ ├── UserNotFoundError.ts │ ├── ColorNotFoundError.ts │ ├── InvalidTokenError.ts │ ├── ProductNotFoundError.ts │ ├── BadRequestError.ts │ ├── ForbiddenError.ts │ ├── APIError.ts │ ├── AlreadyAuthenticatedError.ts │ ├── NotificationNotFoundError.ts │ ├── PrintOrderNotFoundError.ts │ ├── InternalServerError.ts │ ├── InvalidCredentialsError.ts │ ├── PrintPriceNotFoundError.ts │ ├── PurchaseOrderNotFoundError.ts │ ├── ShoppingCartNotFoundError.ts │ ├── FailedImageUploadedNotFoundError.ts │ ├── PaymentMethodNotFoundError.ts │ ├── SamePasswordsError.ts │ ├── ProductCategoryNotFoundError.ts │ ├── SupportRequestNotFoundError.ts │ ├── RevokedTokenError.ts │ ├── TokenExpiredError.ts │ ├── ShoppingCartProductNotFoundError.ts │ ├── UnauthorizedError.ts │ ├── PasswordTooShortError.ts │ ├── PasswordsDoNotMatchError.ts │ ├── PartialContentError.ts │ ├── NumberValidationError.ts │ ├── DetailedError.ts │ ├── FieldsMustBeNumericError.ts │ └── RequiredFieldsError.ts ├── providers │ ├── UUID.ts │ ├── Upload.ts │ ├── Crypt.ts │ └── emails │ │ └── EmailService.ts ├── @types │ └── express.d.ts ├── utils │ └── getBeforeDate.ts ├── services │ ├── string-helper.ts │ ├── validate.ts │ ├── parse-boolean.ts │ ├── local-image-manager.ts │ └── s3.ts ├── repositories │ ├── colors │ │ └── IColorsRepository.ts │ ├── payment-methods │ │ └── IPaymentMethodsRepository.ts │ ├── revoked-tokens │ │ └── IRevokedTokensRepository.ts │ ├── product-categories │ │ └── IProductCategoriesRepository.ts │ ├── refresh-tokens │ │ └── IRefreshTokensRepository.ts │ ├── support-requests │ │ └── ISupportRequestsRepository.ts │ ├── prints │ │ └── IPrintsRepository.ts │ ├── failed-images-uploaded │ │ └── IFailedImagesUploadedRepository.ts │ ├── print-prices │ │ └── IPrintPricesRepository.ts │ ├── validator-tokens │ │ └── IValidatorTokensRepository.ts │ ├── notifications │ │ └── INotificationsRepository.ts │ ├── password-recovery-tokens │ │ └── IPasswordRecoveryTokensRepository.ts │ ├── product │ │ └── IProductsRepository.ts │ └── purchase-order │ │ └── IPurchaseOrdersRepository.ts ├── server.ts ├── middlewares │ ├── ensureAdminUser.ts │ ├── imageUploadCaptureError.ts │ └── imageDataTransform.ts ├── domain │ ├── RefreshTokenMapper.ts │ ├── RevokedTokenMapper.ts │ ├── ValidatorTokenMapper.ts │ ├── PrintPriceMapper.ts │ ├── PasswordRecoveryTokenMapper.ts │ └── PurchaseOrderProductCreationMapper.ts └── infra │ └── scheduler.ts ├── prisma └── migrations │ ├── 20230108180907_added_phone_column_in_user_table │ └── migration.sql │ ├── 20230219200840_added_deleted_at_column_to_users_table │ └── migration.sql │ ├── migration_lock.toml │ ├── 20230220045157_added_verified_column_to_users_table │ └── migration.sql │ ├── 20230204184704_alter_column_description_to_nullable_in_products_table │ └── migration.sql │ ├── 20230201171752_added_total_print_orders_in_users_table │ └── migration.sql │ ├── 20230212204213_added_total_purchase_orders_column │ └── migration.sql │ ├── 20230219191002_added_last_login_column_to_users_table │ └── migration.sql │ ├── 20230129004104_ │ └── migration.sql │ ├── 20230116141028_updated_user_table │ └── migration.sql │ ├── 20230220180308_added_defaults_value_on_support_requests_table │ └── migration.sql │ ├── 20230216012337_ │ └── migration.sql │ ├── 20230214141203_added_uploading_images_enum_to_print_order_table │ └── migration.sql │ ├── 20230220050403_droped_deleted_at_column_on_users_table │ └── migration.sql │ ├── 20230129004251_updated_colors_table │ └── migration.sql │ ├── 20230216181426_dawd │ └── migration.sql │ ├── 20230213030901_ │ └── migration.sql │ ├── 20230219050502_added_expires_in_to_refresh_tokens_table │ └── migration.sql │ ├── 20230216012546_updated_token_column_of_revoked_tokens_table │ └── migration.sql │ ├── 20230220192032_added_notify_services_by_email_column_on_users_table │ └── migration.sql │ ├── 20230204190803_changed_user_id_to_unique_in_shopping_cart_table │ └── migration.sql │ ├── 20230108174349_created_user_table │ └── migration.sql │ ├── 20230219230459_removed_inactive_users_table │ └── migration.sql │ ├── 20230127164030_created_print_prices_table │ └── migration.sql │ ├── 20230214014756_added_failed_images_uploaded_table │ └── migration.sql │ ├── 20230129134710_created_notifications_table │ └── migration.sql │ ├── 20230214025502_added_storaged_type_column_to_failed_images_uploaded_table │ └── migration.sql │ ├── 20230220041914_added_validator_tokens_table │ └── migration.sql │ ├── 20230219193205_added_inactive_users_table │ └── migration.sql │ ├── 20230213041028_added_storaged_type_image_in_products_table │ └── migration.sql │ ├── 20230129134855_added_user_id_to_notification_table │ └── migration.sql │ ├── 20230219045851_created_refresh_tokens_table │ └── migration.sql │ ├── 20230204183550_added_category_column_to_product_table │ └── migration.sql │ ├── 20230201133938_added_total_prints_and_total_purchases_in_users_table_and_added_number_in_print_orders_table │ └── migration.sql │ ├── 20230220160157_create_password_recovery_tokens_table │ └── migration.sql │ ├── 20230219211107_added_cascade_deletion_to_tables │ └── migration.sql │ ├── 20230129223710_create_print_order_table │ └── migration.sql │ ├── 20230204190028_added_delete_cascade_to_tables │ └── migration.sql │ ├── 20230212165107_created_purchase_order_product_table │ └── migration.sql │ └── 20230212192841_added_cascade_on_delete_to_purchase_order_tables │ └── migration.sql ├── .editorconfig ├── tsconfig.json └── .eslintrc.json /tmp/uploads/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | .env 4 | tmp/uploads/* 5 | -------------------------------------------------------------------------------- /src/entities/colors/IColor.ts: -------------------------------------------------------------------------------- 1 | export interface IColor { 2 | id: string; 3 | color: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/shared/filters/PurchaseOrderFilter.ts: -------------------------------------------------------------------------------- 1 | export interface PurchaseOrderFilter { 2 | when?: Date; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/colors/dtos/ColorCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ColorCreateRequest { 2 | color: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/payment-method/IPaymentMethod.ts: -------------------------------------------------------------------------------- 1 | export interface IPaymentMethod { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/user/IUserView.ts: -------------------------------------------------------------------------------- 1 | import { IUser } from './IUser'; 2 | 3 | export type IUserView = Omit; 4 | -------------------------------------------------------------------------------- /src/modules/auth/signout/SignOutDTO.ts: -------------------------------------------------------------------------------- 1 | export interface SignOutRequest { 2 | userId: string; 3 | token: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/shared/ListValidatorTokenBy.ts: -------------------------------------------------------------------------------- 1 | export interface ListValidatorTokenBy { 2 | id?: string; 3 | email?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/print-price/dtos/PrintPriceUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PrintPriceUpdateRequest { 2 | price: number; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/product-category/IProductCategory.ts: -------------------------------------------------------------------------------- 1 | export interface IProductCategory { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/modules/user/recovery-password/RecoveryPasswordDTO.ts: -------------------------------------------------------------------------------- 1 | export interface RecoveryPasswordRequest { 2 | email: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/payment-method/dtos/PaymentMethodCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PaymentMethodCreateRequest { 2 | name: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/shared/filters/RefreshTokenFilter.ts: -------------------------------------------------------------------------------- 1 | export class RefreshTokenFilter { 2 | refreshTokenId?: string; 3 | userId?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/notification/dtos/NotificationUpdateReadRequest.ts: -------------------------------------------------------------------------------- 1 | export interface NotificationUpdateReadRequest { 2 | read: boolean; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/print-price/IPrintPrice.ts: -------------------------------------------------------------------------------- 1 | export interface IPrintPrice { 2 | id: string; 3 | length: string; 4 | price: number; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/support-request/dtos/SupportRequestCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface SupportRequestCreateRequest { 2 | email: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/database/index.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | 3 | const prisma = new PrismaClient(); 4 | 5 | export { prisma }; 6 | -------------------------------------------------------------------------------- /src/entities/product-category/dtos/ProductCategoryCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ProductCategoryCreateRequest { 2 | name: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/modules/auth/refresh-token/RefreshTokenDTO.ts: -------------------------------------------------------------------------------- 1 | export interface RefreshTokenResponse { 2 | token: string; 3 | refreshToken: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/shared/filters/PasswordRecoveryTokenFilter.ts: -------------------------------------------------------------------------------- 1 | export interface PasswordRecoveryTokenFilter { 2 | id?: string; 3 | userId?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/shared/filters/PrintFilter.ts: -------------------------------------------------------------------------------- 1 | export interface PrintFilter { 2 | key?: string; 3 | colorId?: string; 4 | printOrderId?: string; 5 | } 6 | -------------------------------------------------------------------------------- /prisma/migrations/20230108180907_added_phone_column_in_user_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "phone" TEXT; 3 | -------------------------------------------------------------------------------- /src/entities/print-price/dtos/PrintPriceCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PrintPriceCreateRequest { 2 | length: string; 3 | price: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/refresh-token/IRefreshToken.ts: -------------------------------------------------------------------------------- 1 | export interface IRefreshToken { 2 | id: string; 3 | expiresIn: number; 4 | userId: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/revoked-token/IRevokedToken.ts: -------------------------------------------------------------------------------- 1 | export interface IRevokedToken { 2 | id: string; 3 | token: string; 4 | expiresIn: number; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/shopping-cart/dtos/ShoppingCartAddProductRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ShoppingCartAddOrRemoveProductRequest { 2 | productId: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/validator-token/IValidatorToken.ts: -------------------------------------------------------------------------------- 1 | export interface IValidatorToken { 2 | id: string; 3 | expiresIn: number; 4 | email: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/modules/user/delete-account/UserDeleteAccountDTO.ts: -------------------------------------------------------------------------------- 1 | export interface UserDeleteAccountRequest { 2 | userId: string; 3 | password: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/refresh-token/dtos/RefreshTokenCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface RefreshTokenCreateRequest { 2 | expiresIn: number; 3 | userId: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/shopping-cart-product/dtos/ShoppingCartProductUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ShoppingCartProductUpdateRequest { 2 | quantity?: number; 3 | } 4 | -------------------------------------------------------------------------------- /src/entities/support-request/dtos/SupportRequestUpdateResolvedRequest.ts: -------------------------------------------------------------------------------- 1 | export interface SupportRequestUpdateResolvedRequest { 2 | resolved: boolean; 3 | } 4 | -------------------------------------------------------------------------------- /prisma/migrations/20230219200840_added_deleted_at_column_to_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "deletedAt" TIMESTAMP(3); 3 | -------------------------------------------------------------------------------- /src/entities/validator-token/dtos/ValidatorTokenCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ValidatorTokenCreateRequest { 2 | expiresIn: number; 3 | email: string; 4 | } 5 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /src/entities/revoked-token/dtos/RevokedTokenCreateOrUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface RevokedTokenCreateOrUpdatedRequest { 2 | token: string; 3 | expiresIn: number; 4 | } 5 | -------------------------------------------------------------------------------- /prisma/migrations/20230220045157_added_verified_column_to_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "verified" BOOLEAN NOT NULL DEFAULT false; 3 | -------------------------------------------------------------------------------- /src/entities/notification/dtos/NotificationCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface NotificationCreateRequest { 2 | title: string; 3 | message: string; 4 | userId: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/password-recovery-token/IPasswordRecoveryToken.ts: -------------------------------------------------------------------------------- 1 | export interface IPasswordRecoveryToken { 2 | id: string; 3 | expiresIn: number; 4 | userId: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/support-request/ISupportRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ISupportRequest { 2 | id: string; 3 | resolved: boolean; 4 | createdAt: Date; 5 | email: string; 6 | } 7 | -------------------------------------------------------------------------------- /prisma/migrations/20230204184704_alter_column_description_to_nullable_in_products_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "products" ALTER COLUMN "description" DROP NOT NULL; 3 | -------------------------------------------------------------------------------- /src/entities/print-order/dtos/PrintOrderCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PrintOrderCreateRequest { 2 | number: number; 3 | totalPrintsExpected: number; 4 | userId: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/entities/shopping-cart-product/dtos/ShoppingCartProductCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface ShoppingCartProductCreateRequest { 2 | productId: string; 3 | quantity?: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/password-recovery-token/dtos/PasswordRecoveryTokenCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PasswordRecoveryTokenCreateRequest { 2 | expiresIn: number; 3 | userId: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/entities/purchase-order-product/dtos/PurchaseOrderProductCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface PurchaseOrderProductCreateRequest { 2 | productId: string; 3 | quantity?: number; 4 | } 5 | -------------------------------------------------------------------------------- /prisma/migrations/20230201171752_added_total_print_orders_in_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "totalPrintOrders" DECIMAL(65,30) NOT NULL DEFAULT 0; 3 | -------------------------------------------------------------------------------- /prisma/migrations/20230212204213_added_total_purchase_orders_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "totalPurchaseOrders" DECIMAL(65,30) NOT NULL DEFAULT 0; 3 | -------------------------------------------------------------------------------- /src/modules/user/set-password/SetPasswordDTO.ts: -------------------------------------------------------------------------------- 1 | export interface SetPasswordRequest { 2 | passwordRecoveryTokenId: string; 3 | newPassword: string; 4 | confirmNewPassword: string; 5 | } 6 | -------------------------------------------------------------------------------- /prisma/migrations/20230219191002_added_last_login_column_to_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "lastLogin" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; 3 | -------------------------------------------------------------------------------- /src/entities/notification/INotification.ts: -------------------------------------------------------------------------------- 1 | export interface INotification { 2 | id: string; 3 | title: string; 4 | message: string; 5 | read: boolean; 6 | createdAt: Date; 7 | userId: string; 8 | } 9 | -------------------------------------------------------------------------------- /prisma/migrations/20230129004104_/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "colors" ( 3 | "id" TEXT NOT NULL, 4 | "color" TEXT NOT NULL, 5 | 6 | CONSTRAINT "colors_pkey" PRIMARY KEY ("id") 7 | ); 8 | -------------------------------------------------------------------------------- /src/shared/filters/PrintOrderFilter.ts: -------------------------------------------------------------------------------- 1 | import { PrintOrderStatus } from '../../entities/print-order/IPrintOrder'; 2 | 3 | export interface PrintOrderFilter { 4 | status?: PrintOrderStatus; 5 | when?: Date; 6 | } 7 | -------------------------------------------------------------------------------- /src/modules/user/updatePassword/UpdateUserPasswordDTO.ts: -------------------------------------------------------------------------------- 1 | export interface UpdateUserPasswordRequest { 2 | userId: string; 3 | currentPassword: string; 4 | newPassword: string; 5 | confirmNewPassword: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/entities/shopping-cart-product/IShoppingCartProduct.ts: -------------------------------------------------------------------------------- 1 | import { IProduct } from '../product/IProduct'; 2 | 3 | export interface IShoppingCartProduct { 4 | id: string; 5 | product: IProduct; 6 | quantity: number; 7 | } 8 | -------------------------------------------------------------------------------- /prisma/migrations/20230116141028_updated_user_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "users" ADD COLUMN "admin" BOOLEAN NOT NULL DEFAULT false, 3 | ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; 4 | -------------------------------------------------------------------------------- /src/errors/ConflictRequestError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class ConflictRequestError extends APIError { 4 | 5 | constructor(message: string) { 6 | super(409, message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/IDNotGivenError.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestError } from './BadRequestError'; 2 | 3 | export class IDNotGivenError extends BadRequestError { 4 | 5 | constructor() { 6 | super('ID não informado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/NotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class NotFoundError extends APIError { 4 | 5 | constructor(message?: string) { 6 | super(404, message || 'Não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/UserNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class UserNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Usuário não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /prisma/migrations/20230220180308_added_defaults_value_on_support_requests_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "support_requests" ALTER COLUMN "resolved" SET DEFAULT false, 3 | ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; 4 | -------------------------------------------------------------------------------- /src/entities/failed-image-uploaded/IFailedImageUploaded.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../services/image-storaged-type'; 2 | 3 | export interface IFailedImageUploaded { 4 | id: string; 5 | key: string; 6 | storagedType: StorageType; 7 | } 8 | -------------------------------------------------------------------------------- /src/errors/ColorNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class ColorNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Cor/descrição não encontrada'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/InvalidTokenError.ts: -------------------------------------------------------------------------------- 1 | import { UnauthorizedError } from './UnauthorizedError'; 2 | 3 | export class InvalidTokenError extends UnauthorizedError { 4 | 5 | constructor() { 6 | super('Token inválido'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/ProductNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class ProductNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Produto não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/BadRequestError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class BadRequestError extends APIError { 4 | 5 | constructor(message?: string) { 6 | super(400, message || 'Requisição inválida'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/ForbiddenError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class ForbiddenError extends APIError { 4 | 5 | constructor(message?: string) { 6 | super(403, message || 'Acesso não autorizado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/entities/shopping-cart/IShoppingCart.ts: -------------------------------------------------------------------------------- 1 | import { IShoppingCartProduct } from '../shopping-cart-product/IShoppingCartProduct'; 2 | 3 | export interface IShoppingCart { 4 | id: string; 5 | userId:string; 6 | products: IShoppingCartProduct[]; 7 | } 8 | -------------------------------------------------------------------------------- /src/entities/failed-image-uploaded/dtos/FailedImageUploadedCreateRequest.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../../services/image-storaged-type'; 2 | 3 | export interface FailedImageUploadedCreateRequest { 4 | key: string; 5 | storagedType: StorageType; 6 | } 7 | -------------------------------------------------------------------------------- /src/entities/purchase-order-product/IPurchaseOrderProduct.ts: -------------------------------------------------------------------------------- 1 | import { IProduct } from '../product/IProduct'; 2 | 3 | export interface IPurchaseOrderProduct { 4 | id: string; 5 | product: IProduct; 6 | purchaseOrderId: string; 7 | quantity: number; 8 | } 9 | -------------------------------------------------------------------------------- /src/errors/APIError.ts: -------------------------------------------------------------------------------- 1 | export class APIError extends Error { 2 | 3 | readonly statusCode: number; 4 | 5 | constructor(statusCode: number, message: string) { 6 | super(message); 7 | 8 | this.statusCode = statusCode; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/errors/AlreadyAuthenticatedError.ts: -------------------------------------------------------------------------------- 1 | import { ForbiddenError } from './ForbiddenError'; 2 | 3 | export class AlreadyAuthenticatedError extends ForbiddenError { 4 | 5 | constructor() { 6 | super('Você já está autenticado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/NotificationNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class NotificationNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Notificação não encontrada'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/PrintOrderNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class PrintOrderNotFound extends NotFoundError { 4 | 5 | constructor() { 6 | super('Pedido de revelação não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/InternalServerError.ts: -------------------------------------------------------------------------------- 1 | export class InternalServerError extends Error { 2 | 3 | constructor(message?: string) { 4 | super(message || 'Desculpe, ocorreu um erro inesperado em nosso servidor. Por favor, tente novamente mais tarde'); 5 | } 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/errors/InvalidCredentialsError.ts: -------------------------------------------------------------------------------- 1 | import { UnauthorizedError } from './UnauthorizedError'; 2 | 3 | export class InvalidCredentialsError extends UnauthorizedError { 4 | 5 | constructor() { 6 | super('E-mail ou senha inválidos'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/PrintPriceNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class PrintPriceNotFound extends NotFoundError { 4 | 5 | constructor() { 6 | super('Tamanho/tipo de revelação não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/PurchaseOrderNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class PurchaseOrderNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Pedido de compras não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/ShoppingCartNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class ShoppingCartNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Carrinho de compras não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /prisma/migrations/20230216012337_/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "revoked_tokens" ( 3 | "id" TEXT NOT NULL, 4 | "token" TEXT NOT NULL, 5 | "expiresIn" DECIMAL(65,30) NOT NULL, 6 | 7 | CONSTRAINT "revoked_tokens_pkey" PRIMARY KEY ("id") 8 | ); 9 | -------------------------------------------------------------------------------- /src/errors/FailedImageUploadedNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class FailedImageUploadedNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Imagem não encontrada'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/PaymentMethodNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class PaymentMethodNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Método de pagamento não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/SamePasswordsError.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestError } from './BadRequestError'; 2 | 3 | export class SamePasswordsError extends BadRequestError { 4 | 5 | constructor() { 6 | super('A nova senha não pode ser igual à sua atual'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/print-order/create/dtos/RejectedPrintResponse.ts: -------------------------------------------------------------------------------- 1 | import { PrintCreateRequest } from '../../../../entities/print-order/print/dtos/PrintCreateRequest'; 2 | 3 | export interface RejectedPrintResponse { 4 | print: PrintCreateRequest; 5 | reason: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/entities/user/dtos/UserCreateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface UserCreateRequest { 2 | name: string; 3 | email: string; 4 | phone?: string | null; 5 | password: string; 6 | admin?: boolean; 7 | notifyServicesByEmail: boolean; 8 | verified?: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/ProductCategoryNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class ProductCategoryNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Categoria de produto não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/SupportRequestNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class SupportRequestNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Pedido para o suporte não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/RevokedTokenError.ts: -------------------------------------------------------------------------------- 1 | import { UnauthorizedError } from './UnauthorizedError'; 2 | 3 | export class RevokedTokenError extends UnauthorizedError { 4 | 5 | constructor() { 6 | super('Sessão expirada. Faça login novamente para continuar'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/TokenExpiredError.ts: -------------------------------------------------------------------------------- 1 | import { UnauthorizedError } from './UnauthorizedError'; 2 | 3 | export class TokenExpiredError extends UnauthorizedError { 4 | 5 | constructor() { 6 | super('Sessão expirada. Faça login novamente para continuar'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /prisma/migrations/20230214141203_added_uploading_images_enum_to_print_order_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterEnum 2 | ALTER TYPE "PrintOrderStatus" ADD VALUE 'UPLOADING_IMAGES'; 3 | COMMIT; 4 | 5 | -- AlterTable 6 | ALTER TABLE "print_orders" ALTER COLUMN "status" SET DEFAULT 'UPLOADING_IMAGES'; 7 | -------------------------------------------------------------------------------- /src/errors/ShoppingCartProductNotFoundError.ts: -------------------------------------------------------------------------------- 1 | import { NotFoundError } from './NotFoundError'; 2 | 3 | export class ShoppingCartProductNotFoundError extends NotFoundError { 4 | 5 | constructor() { 6 | super('Produto no carrinho de compras não encontrado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /src/entities/purchase-order/dtos/PurchaseOrderUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | import { PurchaseOrderStatus } from '../IPurchaseOrder'; 2 | 3 | export interface PurchaseOrderUpdateRequest { 4 | status?: PurchaseOrderStatus; 5 | paymentMethodId?: string; 6 | freight?: number; 7 | discount?: number; 8 | } 9 | -------------------------------------------------------------------------------- /src/errors/UnauthorizedError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class UnauthorizedError extends APIError { 4 | 5 | constructor(message?: string) { 6 | super(401, message || 'Você não está autenticado para isso, portanto, acesso não autorizado'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/auth/validate/ValidateTokenDTO.ts: -------------------------------------------------------------------------------- 1 | import { IUserPublic } from '../../../entities/user/IUserPublic'; 2 | 3 | export interface ValidateTokenRequest { 4 | token: string; 5 | } 6 | 7 | export interface ValidateTokenResponse { 8 | user: IUserPublic; 9 | token: string; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230220050403_droped_deleted_at_column_on_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `deletedAt` on the `users` table. All the data in the column will be lost. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "users" DROP COLUMN "deletedAt"; 9 | -------------------------------------------------------------------------------- /src/errors/PasswordTooShortError.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestError } from './BadRequestError'; 2 | 3 | export class PasswordTooShortError extends BadRequestError { 4 | 5 | constructor() { 6 | super('Senha muito curta. Por favor, escolha uma senha com pelo menos 3 caracteres'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/errors/PasswordsDoNotMatchError.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestError } from './BadRequestError'; 2 | 3 | export class PasswordsDoNotMatchError extends BadRequestError { 4 | 5 | constructor() { 6 | super('A confirmação de senha não corresponde à senha inserida. Por favor, tente novamente'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/providers/UUID.ts: -------------------------------------------------------------------------------- 1 | import cuid from 'cuid'; 2 | import { v4 } from 'uuid'; 3 | 4 | export class UUID { 5 | 6 | generateUUID() { 7 | return v4(); 8 | } 9 | 10 | generateCUID() { 11 | return cuid(); 12 | } 13 | 14 | } 15 | 16 | const uuidProvider = new UUID(); 17 | 18 | export { uuidProvider }; 19 | -------------------------------------------------------------------------------- /prisma/migrations/20230129004251_updated_colors_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[color]` on the table `colors` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX "colors_color_key" ON "colors"("color"); 9 | -------------------------------------------------------------------------------- /src/errors/PartialContentError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class PartialContentError extends APIError { 4 | 5 | readonly errorOcurred: Error; 6 | 7 | constructor(message: string, errorOcurred: Error) { 8 | super(206, message); 9 | this.errorOcurred = errorOcurred; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /prisma/migrations/20230216181426_dawd/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `totalPrintsExpected` to the `print_orders` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "print_orders" ADD COLUMN "totalPrintsExpected" DECIMAL(65,30) NOT NULL; 9 | -------------------------------------------------------------------------------- /src/@types/express.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Express { 2 | export interface Request { 3 | userIdOfShoppingCartRequest: string; 4 | userId: string; 5 | userIsAdmin: boolean; 6 | tokenRequesting: string; 7 | image: { 8 | imageName: string; 9 | imageUrl: string; 10 | key: string; 11 | }; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/auth/signin/SignInDTO.ts: -------------------------------------------------------------------------------- 1 | import { IUserPublic } from '../../../entities/user/IUserPublic'; 2 | 3 | export interface SignInRequest { 4 | email: string; 5 | password: string; 6 | rememberMe: boolean; 7 | } 8 | 9 | export interface SignInResponse { 10 | user: IUserPublic; 11 | token: string; 12 | refreshToken: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/entities/user/IUserPublic.ts: -------------------------------------------------------------------------------- 1 | export interface IUserPublic { 2 | id: string; 3 | name: string; 4 | email: string; 5 | phone?: string | null; 6 | createdAt: Date; 7 | admin: boolean; 8 | verified: boolean; 9 | totalPrints: number; 10 | totalPrintOrders: number; 11 | totalPurchases: number; 12 | totalPurchaseOrders: number; 13 | } 14 | -------------------------------------------------------------------------------- /src/entities/purchase-order/dtos/PurchaseOrderCreateRequest.ts: -------------------------------------------------------------------------------- 1 | import { PurchaseOrderProductCreateRequest } from '../../purchase-order-product/dtos/PurchaseOrderProductCreateRequest'; 2 | 3 | export interface PurchaseOrderCreateRequest { 4 | number: number; 5 | paymentMethodId: string; 6 | products: PurchaseOrderProductCreateRequest[]; 7 | userId: string; 8 | } 9 | -------------------------------------------------------------------------------- /src/errors/NumberValidationError.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestError } from './BadRequestError'; 2 | 3 | export class NumberValidationError extends BadRequestError { 4 | 5 | constructor(field?: string) { 6 | super(`O valor fornecido para o campo ${field || 'númerico'} é inválido. Por favor, verifique se você está enviando um número válido.`); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /prisma/migrations/20230213030901_/migration.sql: -------------------------------------------------------------------------------- 1 | -- DropForeignKey 2 | ALTER TABLE "shopping_cart_products" DROP CONSTRAINT "shopping_cart_products_productId_fkey"; 3 | 4 | -- AddForeignKey 5 | ALTER TABLE "shopping_cart_products" ADD CONSTRAINT "shopping_cart_products_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE CASCADE ON UPDATE CASCADE; 6 | -------------------------------------------------------------------------------- /prisma/migrations/20230219050502_added_expires_in_to_refresh_tokens_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `expiresIn` to the `refresh_tokens` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "refresh_tokens" ADD COLUMN "expiresIn" DECIMAL(65,30) NOT NULL; 9 | -------------------------------------------------------------------------------- /src/errors/DetailedError.ts: -------------------------------------------------------------------------------- 1 | import { APIError } from './APIError'; 2 | 3 | export class DetailedError extends APIError { 4 | 5 | readonly details: Record; 6 | 7 | constructor(statusCode: number, details: Record, message?: string) { 8 | super(statusCode, message ?? 'Erro'); 9 | this.details = details; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /prisma/migrations/20230216012546_updated_token_column_of_revoked_tokens_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[token]` on the table `revoked_tokens` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX "revoked_tokens_token_key" ON "revoked_tokens"("token"); 9 | -------------------------------------------------------------------------------- /prisma/migrations/20230220192032_added_notify_services_by_email_column_on_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `notifyServicesByEmail` to the `users` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "users" ADD COLUMN "notifyServicesByEmail" BOOLEAN NOT NULL; 9 | -------------------------------------------------------------------------------- /src/entities/product/dtos/ProductCreateRequest.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../../services/image-storaged-type'; 2 | 3 | export interface ProductCreateRequest { 4 | name: string; 5 | description?: string; 6 | price: number; 7 | imageName: string; 8 | imageUrl: string; 9 | key: string; 10 | imageStoragedType: StorageType; 11 | categoryId: string; 12 | } 13 | -------------------------------------------------------------------------------- /prisma/migrations/20230204190803_changed_user_id_to_unique_in_shopping_cart_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[userId]` on the table `shopping_carts` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX "shopping_carts_userId_key" ON "shopping_carts"("userId"); 9 | -------------------------------------------------------------------------------- /src/modules/auth/refresh-token/index.ts: -------------------------------------------------------------------------------- 1 | import { RefreshTokenController } from './RefreshTokenController'; 2 | import { RefreshTokenUseCases } from './RefreshTokenUseCases'; 3 | 4 | export function refreshTokenFactory() { 5 | const useCases = new RefreshTokenUseCases(); 6 | const controller = new RefreshTokenController(useCases); 7 | 8 | return { useCases, controller }; 9 | } 10 | -------------------------------------------------------------------------------- /prisma/migrations/20230108174349_created_user_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "users" ( 3 | "id" TEXT NOT NULL, 4 | "name" VARCHAR(32) NOT NULL, 5 | "email" TEXT NOT NULL, 6 | "password" TEXT NOT NULL, 7 | 8 | CONSTRAINT "users_pkey" PRIMARY KEY ("id") 9 | ); 10 | 11 | -- CreateIndex 12 | CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); 13 | -------------------------------------------------------------------------------- /prisma/migrations/20230219230459_removed_inactive_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the `inactive_users` table. If the table is not empty, all the data it contains will be lost. 5 | 6 | */ 7 | -- DropForeignKey 8 | ALTER TABLE "inactive_users" DROP CONSTRAINT "inactive_users_userId_fkey"; 9 | 10 | -- DropTable 11 | DROP TABLE "inactive_users"; 12 | -------------------------------------------------------------------------------- /prisma/migrations/20230127164030_created_print_prices_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "print_prices" ( 3 | "id" TEXT NOT NULL, 4 | "length" TEXT NOT NULL, 5 | "price" DECIMAL(65,30) NOT NULL, 6 | 7 | CONSTRAINT "print_prices_pkey" PRIMARY KEY ("id") 8 | ); 9 | 10 | -- CreateIndex 11 | CREATE UNIQUE INDEX "print_prices_length_key" ON "print_prices"("length"); 12 | -------------------------------------------------------------------------------- /prisma/migrations/20230214014756_added_failed_images_uploaded_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "failed_images_uploaded" ( 3 | "id" TEXT NOT NULL, 4 | "key" TEXT NOT NULL, 5 | 6 | CONSTRAINT "failed_images_uploaded_pkey" PRIMARY KEY ("id") 7 | ); 8 | 9 | -- CreateIndex 10 | CREATE UNIQUE INDEX "failed_images_uploaded_key_key" ON "failed_images_uploaded"("key"); 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230129134710_created_notifications_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "notifications" ( 3 | "id" TEXT NOT NULL, 4 | "title" TEXT NOT NULL, 5 | "message" TEXT NOT NULL, 6 | "read" BOOLEAN NOT NULL DEFAULT false, 7 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 8 | 9 | CONSTRAINT "notifications_pkey" PRIMARY KEY ("id") 10 | ); 11 | -------------------------------------------------------------------------------- /src/entities/user/dtos/UserUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | export interface UserUpdateRequest { 2 | name?: string; 3 | phone?: string | null; 4 | password?: string; 5 | admin?: boolean; 6 | verified?: boolean; 7 | lastLogin?: Date; 8 | notifyServicesByEmail?: boolean; 9 | totalPrints?: number; 10 | totalPrintOrders?: number; 11 | totalPurchases?: number; 12 | totalPurchaseOrders?: number; 13 | } 14 | -------------------------------------------------------------------------------- /src/entities/product/dtos/ProductUpdateRequest.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../../services/image-storaged-type'; 2 | 3 | export interface ProductUpdateRequest { 4 | name?: string; 5 | description?: string | null; 6 | rated?: number; 7 | price?: number; 8 | imageName?: string; 9 | imageUrl?: string; 10 | key?: string; 11 | imageStoragedType?: StorageType; 12 | categoryId?: string; 13 | } 14 | -------------------------------------------------------------------------------- /prisma/migrations/20230214025502_added_storaged_type_column_to_failed_images_uploaded_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `storagedType` to the `failed_images_uploaded` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "failed_images_uploaded" ADD COLUMN "storagedType" "ImageStoragedTypeProduct" NOT NULL; 9 | -------------------------------------------------------------------------------- /prisma/migrations/20230220041914_added_validator_tokens_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "validator_tokens" ( 3 | "id" TEXT NOT NULL, 4 | "expiresIn" DECIMAL(65,30) NOT NULL, 5 | "email" TEXT NOT NULL, 6 | 7 | CONSTRAINT "validator_tokens_pkey" PRIMARY KEY ("id") 8 | ); 9 | 10 | -- CreateIndex 11 | CREATE UNIQUE INDEX "validator_tokens_email_key" ON "validator_tokens"("email"); 12 | -------------------------------------------------------------------------------- /src/entities/print-order/print/dtos/PrintCreateRequest.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../../../services/image-storaged-type'; 2 | 3 | export interface PrintCreateRequest { 4 | imageName: string; 5 | imageUrl: string; 6 | key: string; 7 | imageStoragedType: StorageType; 8 | printPriceId: string; 9 | border: boolean; 10 | colorId: string; 11 | quantity: number; 12 | printOrderId: string; 13 | } 14 | -------------------------------------------------------------------------------- /prisma/migrations/20230219193205_added_inactive_users_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "inactive_users" ( 3 | "userId" TEXT NOT NULL, 4 | 5 | CONSTRAINT "inactive_users_pkey" PRIMARY KEY ("userId") 6 | ); 7 | 8 | -- AddForeignKey 9 | ALTER TABLE "inactive_users" ADD CONSTRAINT "inactive_users_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 10 | -------------------------------------------------------------------------------- /src/modules/auth/signin/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { SignInController } from './SignInController'; 3 | import { SignInUseCases } from './SignInUseCases'; 4 | 5 | export function signInFactory() { 6 | const useCases = new SignInUseCases(currentUsersRepository); 7 | const controller = new SignInController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/entities/user/IUser.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | id: string; 3 | name: string; 4 | email: string; 5 | phone: string | null; 6 | password: string; 7 | createdAt: Date; 8 | lastLogin: Date; 9 | admin: boolean; 10 | verified: boolean; 11 | notifyServicesByEmail: boolean; 12 | totalPrints: number; 13 | totalPrintOrders: number; 14 | totalPurchases: number; 15 | totalPurchaseOrders: number; 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "sourceMap": true, 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "target": "es6", 8 | "allowJs": true, 9 | "typeRoots": [ 10 | "./node_modules/@types" 11 | ], 12 | "types": [ 13 | "node", 14 | "jest" 15 | ], 16 | "esModuleInterop": true 17 | }, 18 | "include": [ 19 | "./src/**/*" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/modules/print/listByProperties/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintsRepository } from '../../../repositories'; 2 | import { ListPrintsController } from './ListPrintsController'; 3 | import { ListPrintsUseCases } from './ListPrintsUseCases'; 4 | 5 | export function listPrintsFactory() { 6 | const useCases = new ListPrintsUseCases(currentPrintsRepository); 7 | const controller = new ListPrintsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/set-password/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { SetPasswordController } from './SetPasswordController'; 3 | import { SetPasswordUseCase } from './SetPasswordUseCase'; 4 | 5 | export function setPasswordFactory() { 6 | const useCases = new SetPasswordUseCase(currentUsersRepository); 7 | const controller = new SetPasswordController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/shared/NotFoundHTMLTemplate.ts: -------------------------------------------------------------------------------- 1 | export class NotFoundHTMLTemplate { 2 | 3 | static getHTML(url: string, method: string) { 4 | return ` 5 | 6 | 7 | 8 | 9 | Error 10 | 11 | 12 |
Cannot ${method.toUpperCase()} ${url}
13 | 14 | 15 | `; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/providers/Upload.ts: -------------------------------------------------------------------------------- 1 | import multer from 'multer'; 2 | import multerConfig from '../config/multer.config'; 3 | 4 | class UploadProvider { 5 | 6 | uploadSingleFile(fieldName: string) { 7 | return multer(multerConfig).single(fieldName); 8 | } 9 | 10 | uploadMultiFiles(fieldName: string) { 11 | return multer(multerConfig).array(fieldName); 12 | } 13 | 14 | } 15 | 16 | const uploadProvider = new UploadProvider(); 17 | 18 | export { uploadProvider }; 19 | -------------------------------------------------------------------------------- /src/entities/product/IProduct.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../services/image-storaged-type'; 2 | import { IProductCategory } from '../product-category/IProductCategory'; 3 | 4 | export interface IProduct { 5 | id: string; 6 | name: string; 7 | description: string | null; 8 | rated: number; 9 | price: number; 10 | imageName: string; 11 | imageUrl: string; 12 | key: string; 13 | imageStoragedType: StorageType; 14 | category: IProductCategory; 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/auth/validate/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { ValidateTokenController } from './ValidateTokenController'; 3 | import { ValidateTokenUseCases } from './ValidateTokenUseCases'; 4 | 5 | export function validateTokenFactory() { 6 | const useCases = new ValidateTokenUseCases(currentUsersRepository); 7 | const controller = new ValidateTokenController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listAll/ListUsersController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListUsersUseCases } from './ListUsersUseCases'; 3 | export class ListUsersController { 4 | 5 | constructor( 6 | private listUsersUseCases: ListUsersUseCases, 7 | ) { } 8 | 9 | async handle(req: Request, res: Response): Promise { 10 | const user = await this.listUsersUseCases.execute(); 11 | 12 | return res.json(user); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/auth/signup/SignUpDTO.ts: -------------------------------------------------------------------------------- 1 | import { IUserPublic } from '../../../entities/user/IUserPublic'; 2 | 3 | export interface SignUpRequest { 4 | name: string; 5 | email: string; 6 | phone?: string; 7 | password: string; 8 | confirmPassword: string; 9 | notifyServicesByEmail: boolean; 10 | acceptedTermsAndConditions: boolean; 11 | } 12 | 13 | export interface SignUpResponse { 14 | user: IUserPublic; 15 | token: string; 16 | refreshToken: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/auth/validate-email/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { ValidateEmailController } from './ValidateEmailController'; 3 | import { ValidateEmailUseCase } from './ValidateEmailUseCase'; 4 | 5 | export function validateEmailFactory() { 6 | const useCases = new ValidateEmailUseCase(currentUsersRepository); 7 | const controller = new ValidateEmailController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230213041028_added_storaged_type_image_in_products_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `imageStoragedType` to the `products` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- CreateEnum 8 | CREATE TYPE "ImageStoragedTypeProduct" AS ENUM ('LOCAL', 'S3'); 9 | 10 | -- AlterTable 11 | ALTER TABLE "products" ADD COLUMN "imageStoragedType" "ImageStoragedTypeProduct" NOT NULL; 12 | -------------------------------------------------------------------------------- /src/errors/FieldsMustBeNumericError.ts: -------------------------------------------------------------------------------- 1 | import { StringHelperService } from '../services/string-helper'; 2 | import { BadRequestError } from './BadRequestError'; 3 | 4 | export class FieldsMustBeNumericError extends BadRequestError { 5 | 6 | constructor(...fields: string[]) { 7 | super(`O${fields.length > 1 ? 's' :''} campo${fields.length > 1 ? 's' : ''} ${StringHelperService.formatList(fields)} deve${fields.length > 1 ? 'm' : ''} ser de valor númerico`); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductsRepository } from '../../../repositories'; 2 | import { DeleteProductController } from './DeleteProductController'; 3 | import { DeleteProductUseCases } from './DeleteProductUseCases'; 4 | 5 | export function deleteProductFactory() { 6 | const useCases = new DeleteProductUseCases(currentProductsRepository); 7 | const controller = new DeleteProductController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listAll/ListUsersUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IUserView } from '../../../entities/user/IUserView'; 2 | import { IUsersRepository } from '../../../repositories/users/IUsersRepository'; 3 | 4 | export class ListUsersUseCases { 5 | 6 | constructor( 7 | private usersRepository: IUsersRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const users = await this.usersRepository.listAll(); 12 | 13 | return users; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/colors/listAll/ListColorsUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IColor } from '../../../entities/colors/IColor'; 2 | import { IColorsRepository } from '../../../repositories/colors/IColorsRepository'; 3 | 4 | export class ListColorsUseCases { 5 | 6 | constructor( 7 | private colorsRepository: IColorsRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const colors = await this.colorsRepository.listAll(); 12 | 13 | return colors; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/colors/listAll/ListColorsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListColorsUseCases } from './ListColorsUseCases'; 3 | 4 | export class ListColorsController { 5 | 6 | constructor( 7 | private listColorsUseCases: ListColorsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const colors = await this.listColorsUseCases.execute(); 12 | 13 | return res.json(colors); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/utils/getBeforeDate.ts: -------------------------------------------------------------------------------- 1 | export function getBeforeData(when: 'today' | 'lastweek' | 'lastmonth') { 2 | const times = { 3 | today: 1, 4 | lastweek: 7, 5 | lastmonth: 30, 6 | }; 7 | 8 | const time = times[when]; 9 | if(!time) { 10 | throw new Error('Valor inválido para o parâmetro "when". Valores permitidos são "today", "lastmonth" e "lastweek"'); 11 | } 12 | 13 | const before = Date.now() - time * 24 * 60 * 60 * 1000; 14 | 15 | return new Date(before); 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/auth/signout/index.ts: -------------------------------------------------------------------------------- 1 | import { currentRevokedTokensRepository, currentUsersRepository } from '../../../repositories'; 2 | import { SignOutController } from './SignOutController'; 3 | import { SignOutUseCases } from './SignOutUseCases'; 4 | 5 | export function signOutFactory() { 6 | const useCases = new SignOutUseCases(currentUsersRepository, currentRevokedTokensRepository); 7 | const controller = new SignOutController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductsRepository } from '../../../repositories'; 2 | import { ListProductByIdController } from './ListProductByIdController'; 3 | import { ListProductByIdUseCases } from './ListProductByIdUseCases'; 4 | 5 | export function listProductByIdFactory() { 6 | const useCases = new ListProductByIdUseCases(currentProductsRepository); 7 | const controller = new ListProductByIdController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/services/string-helper.ts: -------------------------------------------------------------------------------- 1 | class StringHelperService { 2 | 3 | static formatList(strings: string[]) { 4 | if(strings.length === 0) { 5 | return ''; 6 | } else if(strings.length === 1) { 7 | return strings[0]; 8 | } else if(strings.length === 2) { 9 | return strings.join(' e '); 10 | } else { 11 | const lastItem = strings.pop(); 12 | return strings.join(', ') + ' e ' + lastItem; 13 | } 14 | } 15 | 16 | } 17 | 18 | export { StringHelperService }; 19 | -------------------------------------------------------------------------------- /src/modules/user/delete-account/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { UserDeleteAccountController } from './UserDeleteAccountController'; 3 | import { UserDeleteAccountUseCase } from './UserDeleteAccountUseCase'; 4 | 5 | export function userDeleteAccountFactory() { 6 | const useCases = new UserDeleteAccountUseCase(currentUsersRepository); 7 | const controller = new UserDeleteAccountController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listInactives/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { ListInactiveUsersController } from './ListInactiveUsersController'; 3 | import { ListInactiveUsersUseCases } from './ListInactiveUsersUseCases'; 4 | 5 | export function listInactiveUsersFactory() { 6 | const useCases = new ListInactiveUsersUseCases(currentUsersRepository); 7 | const controller = new ListInactiveUsersController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { ListUsersController } from './ListUsersController'; 3 | import { ListUsersUseCases } from './ListUsersUseCases'; 4 | 5 | export function listUsersFactory() { 6 | const listUsersUseCases = new ListUsersUseCases(currentUsersRepository); 7 | const listUsersController = new ListUsersController(listUsersUseCases); 8 | 9 | return { useCases: listUsersUseCases, controller: listUsersController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listInactives/ListInactiveUsersUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IUserView } from '../../../entities/user/IUserView'; 2 | import { IUsersRepository } from '../../../repositories/users/IUsersRepository'; 3 | 4 | export class ListInactiveUsersUseCases { 5 | 6 | constructor( 7 | private usersRepository: IUsersRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const users = await this.usersRepository.listInactiveUsers(); 12 | 13 | return users; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/user/updatePassword/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { UpdateUserPasswordController } from './UpdateUserPasswordController'; 3 | import { UpdateUserPasswordUseCases } from './UpdateUserPasswordUseCases'; 4 | 5 | export function updateUserPasswordFactory() { 6 | const useCases = new UpdateUserPasswordUseCases(currentUsersRepository); 7 | const controller = new UpdateUserPasswordController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/validate-recovery-password-token/index.ts: -------------------------------------------------------------------------------- 1 | import { ValidateRecoveryPasswordTokenController } from './ValidateRecoveryPasswordTokenController'; 2 | import { ValidateRecoveryPasswordTokenUseCase } from './ValidateRecoveryPasswordTokenUseCase'; 3 | 4 | export function validateRecoveryPasswordTokenFactory() { 5 | const useCases = new ValidateRecoveryPasswordTokenUseCase(); 6 | const controller = new ValidateRecoveryPasswordTokenController(useCases); 7 | 8 | return { useCases, controller }; 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/user/delete/DeleteUserController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteUserUseCases } from './DeleteUserUseCases'; 3 | 4 | export class DeleteUserController { 5 | 6 | constructor( 7 | private deleteUserUseCases: DeleteUserUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteUserUseCases.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/user/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { DeleteUserController } from './DeleteUserController'; 3 | import { DeleteUserUseCases } from './DeleteUserUseCases'; 4 | 5 | export function deleteUserFactory() { 6 | const deleteUserUseCases = new DeleteUserUseCases(currentUsersRepository); 7 | const deleteUserController = new DeleteUserController(deleteUserUseCases); 8 | 9 | return { useCases: deleteUserUseCases, controller: deleteUserController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/update/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { UpdateUserController } from './UpdateUserController'; 3 | import { UpdateUserUseCases } from './UpdateUserUseCases'; 4 | 5 | export function updateUserFactory() { 6 | const updateUserUseCases = new UpdateUserUseCases(currentUsersRepository); 7 | const updateUserController = new UpdateUserController(updateUserUseCases); 8 | 9 | return { useCases: updateUserUseCases, controller: updateUserController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/providers/Crypt.ts: -------------------------------------------------------------------------------- 1 | import bcrypt from 'bcrypt'; 2 | import { IUser } from '../entities/user/IUser'; 3 | 4 | class Crypt { 5 | hash(value: string) { 6 | return bcrypt.hash(value, 8); 7 | } 8 | 9 | matches(plainValue: string, hashedValue: string) { 10 | return bcrypt.compare(plainValue, hashedValue); 11 | } 12 | 13 | matchesPassword(password: string, user: IUser) { 14 | return this.matches(password, user.password); 15 | } 16 | } 17 | 18 | const crypt = new Crypt(); 19 | 20 | export { crypt }; 21 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentShoppingCartsRepository } from '../../../repositories'; 2 | import { ListShoppingCartsController } from './ListShoppingCartsController'; 3 | import { ListShoppingCartsUseCases } from './ListShoppingCartsUseCases'; 4 | 5 | export function listShoppingCartsFactory() { 6 | const useCases = new ListShoppingCartsUseCases(currentShoppingCartsRepository); 7 | const controller = new ListShoppingCartsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/colors/delete/DeleteColorController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteColorUseCases } from './DeleteColorUseCases'; 3 | 4 | export class DeleteColorController { 5 | 6 | constructor( 7 | private deleteColorUseCases: DeleteColorUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteColorUseCases.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/colors/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentColorsRepository } from '../../../repositories'; 2 | import { ListColorsController } from './ListColorsController'; 3 | import { ListColorsUseCases } from './ListColorsUseCases'; 4 | 5 | export function listColorsFactory() { 6 | const listColorsUseCases = new ListColorsUseCases(currentColorsRepository); 7 | const listColorsControlller = new ListColorsController(listColorsUseCases); 8 | 9 | return { useCases: listColorsUseCases, controller: listColorsControlller }; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230129134855_added_user_id_to_notification_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `userId` to the `notifications` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "notifications" ADD COLUMN "userId" TEXT NOT NULL; 9 | 10 | -- AddForeignKey 11 | ALTER TABLE "notifications" ADD CONSTRAINT "notifications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 12 | -------------------------------------------------------------------------------- /src/modules/colors/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentColorsRepository } from '../../../repositories'; 2 | import { CreateColorController } from './CreateColorController'; 3 | import { CreateColorUseCases } from './CreateColorUseCases'; 4 | 5 | export function createColorFactory() { 6 | const createColorUseCases = new CreateColorUseCases(currentColorsRepository); 7 | const createColorController = new CreateColorController(createColorUseCases); 8 | 9 | return { useCases: createColorUseCases, controller: createColorController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/payment-method/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository } from '../../../repositories'; 2 | import { ListPaymentMethodsController } from './ListPaymentMethodsController'; 3 | import { ListPaymentMethodsUseCases } from './ListPaymentMethodsUseCases'; 4 | 5 | export function listPaymentMethodsFactory() { 6 | const useCases = new ListPaymentMethodsUseCases(currentPaymentMethodsRepository); 7 | const controller = new ListPaymentMethodsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/colors/listByColor/index.ts: -------------------------------------------------------------------------------- 1 | import { currentColorsRepository } from '../../../repositories'; 2 | import { ListByColorController } from './ListByColorController'; 3 | import { ListByColorUseCases } from './ListByColorUseCases'; 4 | 5 | export function listByColorFactory() { 6 | const listByColorUseCases = new ListByColorUseCases(currentColorsRepository); 7 | const listByColorController = new ListByColorController(listByColorUseCases); 8 | 9 | return { useCases: listByColorUseCases, controller: listByColorController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/payment-method/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository } from '../../../repositories'; 2 | import { CreatePaymentMethodController } from './CreatePaymentMethodController'; 3 | import { CreatePaymentMethodUseCases } from './CreatePaymentMethodUseCases'; 4 | 5 | export function createPaymentMethodFactory() { 6 | const useCases = new CreatePaymentMethodUseCases(currentPaymentMethodsRepository); 7 | const controller = new CreatePaymentMethodController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/payment-method/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository } from '../../../repositories'; 2 | import { DeletePaymentMethodController } from './DeletePaymentMethodController'; 3 | import { DeletePaymentMethodUseCases } from './DeletePaymentMethodUseCaes'; 4 | 5 | export function deletePaymentMethodFactory() { 6 | const useCases = new DeletePaymentMethodUseCases(currentPaymentMethodsRepository); 7 | const controller = new DeletePaymentMethodController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/purchase-order/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPurchaseOrdersRepository } from '../../../repositories'; 2 | import { DeletePurchaseOrderController } from './DeletePurchaseOrderController'; 3 | import { DeletePurchaseOrderUseCases } from './DeletePurchaseOrderUseCases'; 4 | 5 | export function deletePurchaseOrderFactory() { 6 | const useCases = new DeletePurchaseOrderUseCases(currentPurchaseOrdersRepository); 7 | const controller = new DeletePurchaseOrderController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/purchase-order/update/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPurchaseOrdersRepository } from '../../../repositories'; 2 | import { UpdatePurchaseOrderController } from './UpdatePurchaseOrderController'; 3 | import { UpdatePurchaseOrderUseCases } from './UpdatePurchaseOrderUseCases'; 4 | 5 | export function updatePurchaseOrderFactory() { 6 | const useCases = new UpdatePurchaseOrderUseCases(currentPurchaseOrdersRepository); 7 | const controller = new UpdatePurchaseOrderController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/support-request/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentSupportRequestsRepository } from '../../../repositories'; 2 | import { ListSupportRequestsController } from './ListSupportRequestsController'; 3 | import { ListSupportRequestsUseCase } from './ListSupportRequestsUseCase'; 4 | 5 | export function listSupportRequestsFactory() { 6 | const useCases = new ListSupportRequestsUseCase(currentSupportRequestsRepository); 7 | const controller = new ListSupportRequestsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listInactives/ListInactiveUsersController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListInactiveUsersUseCases } from './ListInactiveUsersUseCases'; 3 | 4 | export class ListInactiveUsersController { 5 | 6 | constructor( 7 | private listInactiveUsersUseCases: ListInactiveUsersUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const users = await this.listInactiveUsersUseCases.execute(); 12 | 13 | return res.json(users); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/repositories/colors/IColorsRepository.ts: -------------------------------------------------------------------------------- 1 | import { ColorCreateRequest } from '../../entities/colors/dtos/ColorCreateRequest'; 2 | import { IColor } from '../../entities/colors/IColor'; 3 | 4 | export interface IColorsRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | listByColor(color: string): Promise; 11 | 12 | create({ color }: ColorCreateRequest): Promise; 13 | 14 | delete(id: string): Promise; 15 | 16 | cleanRepository(): void; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/auth/signout/SignOutController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SignOutUseCases } from './SignOutUseCases'; 3 | 4 | export class SignOutController { 5 | 6 | constructor( 7 | private signOutUseCases: SignOutUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userId, tokenRequesting } = req; 12 | 13 | await this.signOutUseCases.execute({ userId, token: tokenRequesting }); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print-price/listAll/ListPrintPricesController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | 3 | import { ListPrintPricesUseCases } from './ListPrintPricesUseCases'; 4 | 5 | export class ListPrintPricesController { 6 | 7 | constructor( 8 | private listPrintPricesUseCases: ListPrintPricesUseCases, 9 | ) { } 10 | 11 | async handle(req: Request, res: Response): Promise { 12 | const printPrices = await this.listPrintPricesUseCases.execute(); 13 | 14 | return res.json(printPrices); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/product/delete/DeleteProductController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteProductUseCases } from './DeleteProductUseCases'; 3 | 4 | export class DeleteProductController { 5 | 6 | constructor( 7 | private deleteProductUseCases: DeleteProductUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteProductUseCases.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository, currentProductsRepository } from '../../../repositories'; 2 | import { ListProductsController } from './ListProductsController'; 3 | import { ListProductsUseCases } from './ListProductsUseCases'; 4 | 5 | export function listProductsFactory() { 6 | const useCases = new ListProductsUseCases(currentProductsRepository, currentProductCategoriesRepository); 7 | const controller = new ListProductsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/support-request/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentSupportRequestsRepository } from '../../../repositories'; 2 | import { DeleteSupportRequestController } from './DeleteSupportRequestController'; 3 | import { DeleteSupportRequestUseCase } from './DeleteSupportRequestUseCase'; 4 | 5 | export function deleteSupportRequestFactory() { 6 | const useCases = new DeleteSupportRequestUseCase(currentSupportRequestsRepository); 7 | const controller = new DeleteSupportRequestController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { ListUserByIdController } from './ListUserByIdController'; 2 | import { currentUsersRepository } from '../../../repositories'; 3 | import { ListUserByIdUseCases } from './ListUserByIdUseCases'; 4 | 5 | export function listUserByIdFactory() { 6 | const listUserByIdUseCases = new ListUserByIdUseCases(currentUsersRepository); 7 | const listUserByIdController = new ListUserByIdController(listUserByIdUseCases); 8 | 9 | return { useCases: listUserByIdUseCases, controller: listUserByIdController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | import { app } from './app'; 2 | import { prisma } from './database'; 3 | import { EnvProvider } from './services/env-provider'; 4 | 5 | async function main() { 6 | try { 7 | await prisma.$connect(); 8 | console.info('🔌 Database connected'); 9 | 10 | app.listen(EnvProvider.port, () => console.log(`✅ Server started at port ${EnvProvider.port}`)); 11 | } catch (err) { 12 | console.error('⚠️ Failed to connect to the database', err); 13 | console.warn('⚠️ Aborting the server'); 14 | } 15 | } 16 | 17 | main(); 18 | -------------------------------------------------------------------------------- /prisma/migrations/20230219045851_created_refresh_tokens_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "refresh_tokens" ( 3 | "id" TEXT NOT NULL, 4 | "userId" TEXT NOT NULL, 5 | 6 | CONSTRAINT "refresh_tokens_pkey" PRIMARY KEY ("id") 7 | ); 8 | 9 | -- CreateIndex 10 | CREATE UNIQUE INDEX "refresh_tokens_userId_key" ON "refresh_tokens"("userId"); 11 | 12 | -- AddForeignKey 13 | ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 14 | -------------------------------------------------------------------------------- /src/modules/auth/signin/SignInController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SignInUseCases } from './SignInUseCases'; 3 | 4 | export class SignInController { 5 | 6 | constructor( 7 | private signInUseCases: SignInUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { email, password, rememberMe } = req.body; 12 | 13 | const user = await this.signInUseCases.execute({ email, password, rememberMe }); 14 | 15 | return res.json(user); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/auth/validate-email/ValidateEmailController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ValidateEmailUseCase } from './ValidateEmailUseCase'; 3 | 4 | export class ValidateEmailController { 5 | 6 | constructor( 7 | private validateEmailUseCase: ValidateEmailUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { token } = req.params; 12 | 13 | await this.validateEmailUseCase.execute(token); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/notification/listAll/ListAllNotificationsUseCases.ts: -------------------------------------------------------------------------------- 1 | import { INotification } from '../../../entities/notification/INotification'; 2 | import { NotificationsService } from '../../../services/notifications'; 3 | 4 | export class ListAllNotificationsUseCases { 5 | 6 | constructor( 7 | private notificationsService: NotificationsService, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const notifications = await this.notificationsService.getAll(); 12 | 13 | return notifications; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/product/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository, currentProductsRepository } from '../../../repositories'; 2 | import { CreateProductController } from './CreateProductController'; 3 | import { CreateProductUseCases } from './CreateProductUseCases'; 4 | 5 | export function createProductFactory() { 6 | const useCases = new CreateProductUseCases(currentProductsRepository, currentProductCategoriesRepository); 7 | const controller = new CreateProductController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product/update/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository, currentProductsRepository } from '../../../repositories'; 2 | import { UpdateProductController } from './UpdateProductController'; 3 | import { UpdateProductUseCases } from './UpdateProductUseCases'; 4 | 5 | export function updateProductFactory() { 6 | const useCases = new UpdateProductUseCases(currentProductsRepository, currentProductCategoriesRepository); 7 | const controller = new UpdateProductController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/colors/listByColor/ListByColorController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListByColorUseCases } from './ListByColorUseCases'; 3 | 4 | export class ListByColorController { 5 | 6 | constructor( 7 | private listByColorUseCases: ListByColorUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { color } = req.params; 12 | 13 | const colorObj = await this.listByColorUseCases.execute(color); 14 | 15 | return res.json(colorObj); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/colors/listById/ListColorByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListColorByIdUseCases } from './ListColorByIdUseCases'; 3 | 4 | export class ListColorByIdController { 5 | 6 | constructor( 7 | private listColorByIdUseCases: ListColorByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const color = await this.listColorByIdUseCases.execute(id); 14 | 15 | return res.json(color); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/payment-method/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository } from '../../../repositories'; 2 | import { ListPaymentMethodByIdController } from './ListPaymentMethodByIdController'; 3 | import { ListPaymentMethodByIdUseCases } from './ListPaymentMethodByIdUseCases'; 4 | 5 | export function listPaymentMethodByIdFactory() { 6 | const useCases = new ListPaymentMethodByIdUseCases(currentPaymentMethodsRepository); 7 | const controller = new ListPaymentMethodByIdController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/purchase-order/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPurchaseOrdersRepository } from '../../../repositories'; 2 | import { ListPurchaseOrderByIdController } from './ListPurchaseOrderByIdController'; 3 | import { ListPurchaseOrderByIdUseCases } from './ListPurchaseOrderByIdUseCases'; 4 | 5 | export function listPurchaseOrderByIdFactory() { 6 | const useCases = new ListPurchaseOrderByIdUseCases(currentPurchaseOrdersRepository); 7 | const controller = new ListPurchaseOrderByIdController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-price/listAll/ListPrintPricesUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPrintPrice } from '../../../entities/print-price/IPrintPrice'; 2 | import { IPrintPricesRepository } from '../../../repositories/print-prices/IPrintPricesRepository'; 3 | 4 | export class ListPrintPricesUseCases { 5 | 6 | constructor( 7 | private printPricesRepository: IPrintPricesRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const printPrices = await this.printPricesRepository.listAll(); 12 | 13 | return printPrices; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/product-category/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository } from '../../../repositories'; 2 | import { DeleteProductCategoryController } from './DeleteProductCategoryController'; 3 | import { DeleteProductCategoryUseCases } from './DeleteProductCategoryUseCases'; 4 | 5 | export function deleteProductCategoryFactory() { 6 | const useCases = new DeleteProductCategoryUseCases(currentProductCategoriesRepository); 7 | const controller = new DeleteProductCategoryController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listAll/ListShoppingCartsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListShoppingCartsUseCases } from './ListShoppingCartsUseCases'; 3 | 4 | export class ListShoppingCartsController { 5 | 6 | constructor( 7 | private listShoppingCartsUseCases: ListShoppingCartsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const shoppingCarts = await this.listShoppingCartsUseCases.execute(); 12 | 13 | return res.json(shoppingCarts); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/user/listById/ListUserByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListUserByIdUseCases } from './ListUserByIdUseCases'; 3 | 4 | export class ListUserByIdController { 5 | 6 | constructor( 7 | private listUserByIdUseCases: ListUserByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const user = await this.listUserByIdUseCases.execute(id, req.userIsAdmin); 14 | 15 | return res.json(user); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/colors/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { ListColorByIdController } from './ListColorByIdController'; 2 | import { currentColorsRepository } from '../../../repositories'; 3 | import { ListColorByIdUseCases } from './ListColorByIdUseCases'; 4 | 5 | export function listColorByIdFactory() { 6 | const listColorByIdUseCases = new ListColorByIdUseCases(currentColorsRepository); 7 | const listColorByIdController = new ListColorByIdController(listColorByIdUseCases); 8 | 9 | return { useCases: listColorByIdUseCases, controller: listColorByIdController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product-category/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository } from '../../../repositories'; 2 | import { ListProductCategoriesController } from './ListProductCategoriesController'; 3 | import { ListProductCategoriesUseCases } from './ListProductCategoriesUseCases'; 4 | 5 | export function listProductCategoriesFactory() { 6 | const useCases = new ListProductCategoriesUseCases(currentProductCategoriesRepository); 7 | const controller = new ListProductCategoriesController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/entities/print-order/print/IPrint.ts: -------------------------------------------------------------------------------- 1 | import { StorageType } from '../../../services/image-storaged-type'; 2 | import { IColor } from '../../colors/IColor'; 3 | import { IPrintPrice } from '../../print-price/IPrintPrice'; 4 | 5 | export interface IPrint { 6 | id: string; 7 | imageName: string; 8 | imageUrl: string; 9 | key: string; 10 | imageStoragedType: StorageType; 11 | printPrice: IPrintPrice; 12 | printPriceId: string; 13 | border: boolean; 14 | color: IColor; 15 | colorId: string; 16 | quantity: number; 17 | printOrderId: string; 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/auth/validate/ValidateTokenController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ValidateTokenUseCases } from './ValidateTokenUseCases'; 3 | 4 | export class ValidateTokenController { 5 | 6 | constructor( 7 | private validateTokenUseCases: ValidateTokenUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { token } = req.params; 12 | 13 | const response = await this.validateTokenUseCases.execute({ token }); 14 | 15 | return res.json(response); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/colors/create/CreateColorController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreateColorUseCases } from './CreateColorUseCases'; 3 | 4 | export class CreateColorController { 5 | 6 | constructor( 7 | private createColorUseCases: CreateColorUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { color } = req.body; 12 | 13 | const colorCreated = await this.createColorUseCases.execute({ color }); 14 | 15 | return res.status(201).json(colorCreated); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/payment-method/listAll/ListPaymentMethodsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPaymentMethodsUseCases } from './ListPaymentMethodsUseCases'; 3 | 4 | export class ListPaymentMethodsController { 5 | 6 | constructor( 7 | private listPaymentMethodsUseCases: ListPaymentMethodsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const paymentMethods = await this.listPaymentMethodsUseCases.execute(); 12 | 13 | return res.json(paymentMethods); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/support-request/updateResolved/index.ts: -------------------------------------------------------------------------------- 1 | import { currentSupportRequestsRepository } from '../../../repositories'; 2 | import { UpdateSupportRequestController } from './UpdateSupportRequestController'; 3 | import { UpdateSupportRequestResolvedUseCase } from './UpdateSupportRequestUseCase'; 4 | 5 | export function updateSupportRequestFactory() { 6 | const useCases = new UpdateSupportRequestResolvedUseCase(currentSupportRequestsRepository); 7 | const controller = new UpdateSupportRequestController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230204183550_added_category_column_to_product_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `productCategoryId` to the `products` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "products" ADD COLUMN "productCategoryId" TEXT NOT NULL; 9 | 10 | -- AddForeignKey 11 | ALTER TABLE "products" ADD CONSTRAINT "products_productCategoryId_fkey" FOREIGN KEY ("productCategoryId") REFERENCES "product_categories"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 12 | -------------------------------------------------------------------------------- /src/modules/print-price/delete/DeletePrintPriceController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | 3 | import { DeletePrintPriceUseCases } from './DeletePrintPriceUseCases'; 4 | 5 | export class DeletePrintPriceController { 6 | 7 | constructor( 8 | private deletePrintPriceUseCases: DeletePrintPriceUseCases, 9 | ) { } 10 | 11 | async handle(req: Request, res: Response): Promise { 12 | const { id } = req.params; 13 | 14 | await this.deletePrintPriceUseCases.execute(id); 15 | 16 | return res.sendStatus(204); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/product/listById/ListProductByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListProductByIdUseCases } from './ListProductByIdUseCases'; 3 | 4 | export class ListProductByIdController { 5 | 6 | constructor( 7 | private listProductByIdUseCases: ListProductByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const product = await this.listProductByIdUseCases.execute(id); 14 | 15 | return res.json(product); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/support-request/listAll/ListSupportRequestsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListSupportRequestsUseCase } from './ListSupportRequestsUseCase'; 3 | 4 | export class ListSupportRequestsController { 5 | 6 | constructor( 7 | private listSupportRequestsUseCase: ListSupportRequestsUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const supportRequests = await this.listSupportRequestsUseCase.execute(); 12 | 13 | return res.json(supportRequests); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/user/recovery-password/RecoveryPasswordController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { RecoveryPasswordUseCase } from './RecoveryPasswordUseCase'; 3 | 4 | export class RecoveryPasswordController { 5 | 6 | constructor( 7 | private recoveryPasswordUseCase: RecoveryPasswordUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { email } = req.body; 12 | 13 | await this.recoveryPasswordUseCase.execute({ email }); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/notification/listAll/ListAllNotificationController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListAllNotificationsUseCases } from './ListAllNotificationsUseCases'; 3 | 4 | export class ListAllNotificationsController { 5 | 6 | constructor( 7 | private listAllNotificationsUseCases: ListAllNotificationsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const notifications = await this.listAllNotificationsUseCases.execute(); 12 | 13 | return res.json(notifications); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/print-order/delete/DeletePrintOrderController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeletePrintOrderUseCases } from './DeletePrintOrderUseCases'; 3 | 4 | export class DeletePrintOrderController { 5 | 6 | constructor( 7 | private deletePrintOrderUseCases: DeletePrintOrderUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deletePrintOrderUseCases.execute(id, req.userId); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product-category/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository } from '../../../repositories'; 2 | import { ListProductCategoryByIdController } from './ListProductCategoryByIdController'; 3 | import { ListProductCategoryByIdUseCases } from './ListProductCategoryByIdUseCases'; 4 | 5 | export function listProductCategoryByIdFactory() { 6 | const useCases = new ListProductCategoryByIdUseCases(currentProductCategoriesRepository); 7 | const controller = new ListProductCategoryByIdController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/purchase-order/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPurchaseOrdersRepository, currentUsersRepository } from '../../../repositories'; 2 | import { ListPurchaseOrdersController } from './ListPurchaseOrdersController'; 3 | import { ListPurchaseOrdersUseCases } from './ListPurchaseOrdersUseCases'; 4 | 5 | export function listPurchaseOrdersFactory() { 6 | const useCases = new ListPurchaseOrdersUseCases(currentPurchaseOrdersRepository, currentUsersRepository); 7 | const controller = new ListPurchaseOrdersController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listShoppingCartProduct/index.ts: -------------------------------------------------------------------------------- 1 | import { currentShoppingCartsRepository } from '../../../repositories'; 2 | import { ListShoppingCartProductController } from './ListShoppingCartProductController'; 3 | import { ListShoppingCartProductUseCases } from './ListShoppingCartProductUseCases'; 4 | 5 | export function listShoppingCartProductFactory() { 6 | const useCases = new ListShoppingCartProductUseCases(currentShoppingCartsRepository); 7 | const controller = new ListShoppingCartProductController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/colors/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentColorsRepository, currentPrintsRepository } from '../../../repositories'; 2 | import { DeleteColorController } from './DeleteColorController'; 3 | import { DeleteColorUseCases } from './DeleteColorUseCases'; 4 | 5 | export function deleteColorFactory() { 6 | const deleteColorUseCases = new DeleteColorUseCases(currentColorsRepository, currentPrintsRepository); 7 | const deleteColorController = new DeleteColorController(deleteColorUseCases); 8 | 9 | return { useCases: deleteColorUseCases, controller: deleteColorController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentShoppingCartsRepository, currentUsersRepository } from '../../../repositories'; 2 | import { CreateUserController } from './CreateUserController'; 3 | import { CreateUserUseCases } from './CreateUserUseCases'; 4 | 5 | export function createUserFactory() { 6 | const createUserUseCases = new CreateUserUseCases(currentUsersRepository, currentShoppingCartsRepository); 7 | const createUserController = new CreateUserController(createUserUseCases); 8 | 9 | return { useCases: createUserUseCases, controller: createUserController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/listByEmail/index.ts: -------------------------------------------------------------------------------- 1 | import { currentUsersRepository } from '../../../repositories'; 2 | import { ListUserByEmailController } from './ListUserByEmailController'; 3 | import { ListUserByEmailUseCases } from './ListUserByEmailUseCases'; 4 | 5 | export function listUserByEmailFactory() { 6 | const listUserByEmailUseCases = new ListUserByEmailUseCases(currentUsersRepository); 7 | const listUserByEmailController = new ListUserByEmailController(listUserByEmailUseCases); 8 | 9 | return { useCases: listUserByEmailUseCases, controller: listUserByEmailController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/payment-method/delete/DeletePaymentMethodController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeletePaymentMethodUseCases } from './DeletePaymentMethodUseCaes'; 3 | 4 | export class DeletePaymentMethodController { 5 | 6 | constructor( 7 | private deletePaymentMethodUseCases: DeletePaymentMethodUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deletePaymentMethodUseCases.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listAll/ListShoppingCartsUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IShoppingCart } from '../../../entities/shopping-cart/IShoppingCart'; 2 | import { IShoppingCartsRepository } from '../../../repositories/shopping-carts/IShoppingCartsRepository'; 3 | 4 | export class ListShoppingCartsUseCases { 5 | 6 | constructor( 7 | private shoppingCartsRepository: IShoppingCartsRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const shoppingCarts = await this.shoppingCartsRepository.listAll(); 12 | 13 | return shoppingCarts; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /prisma/migrations/20230201133938_added_total_prints_and_total_purchases_in_users_table_and_added_number_in_print_orders_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `number` to the `print_orders` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "print_orders" ADD COLUMN "number" DECIMAL(65,30) NOT NULL; 9 | 10 | -- AlterTable 11 | ALTER TABLE "users" ADD COLUMN "totalPrints" DECIMAL(65,30) NOT NULL DEFAULT 0, 12 | ADD COLUMN "totalPurchases" DECIMAL(65,30) NOT NULL DEFAULT 0; 13 | -------------------------------------------------------------------------------- /src/modules/auth/refresh-token/RefreshTokenController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { RefreshTokenUseCases } from './RefreshTokenUseCases'; 3 | 4 | export class RefreshTokenController { 5 | 6 | constructor( 7 | private refreshTokenUseCases: RefreshTokenUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { refreshToken } = req.body; 12 | 13 | const tokenResponse = await this.refreshTokenUseCases.execute(refreshToken); 14 | 15 | return res.status(201).json(tokenResponse); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentFailedImagesUploadedRepository } from '../../../repositories'; 2 | import { ListFailedImagesUploadedController } from './ListFailedImagesUploadedController'; 3 | import { ListFailedImagesUploadedUseCases } from './ListFailedImagesUploadedUseCases'; 4 | 5 | export function listFailedImagesUploadedFactory() { 6 | const useCases = new ListFailedImagesUploadedUseCases(currentFailedImagesUploadedRepository); 7 | const controller = new ListFailedImagesUploadedController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/notification/delete/DeleteNotificationController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteNotificationUseCases } from './DeleteNotificationUseCases'; 3 | 4 | export class DeleteNotificationController { 5 | 6 | constructor( 7 | private deleteNotificationUseCases: DeleteNotificationUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteNotificationUseCases.execute(id, req.userId); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product/listAll/ListProductsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListProductsUseCases } from './ListProductsUseCases'; 3 | 4 | export class ListProductsController { 5 | 6 | constructor( 7 | private listProductsUseCases: ListProductsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const categoryId = req.query.categoryId as string | undefined; 12 | 13 | const products = await this.listProductsUseCases.execute(categoryId); 14 | 15 | return res.json(products); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/support-request/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentSupportRequestsRepository, currentUsersRepository } from '../../../repositories'; 2 | import { SupportRequestCreateController } from './SupportRequestCreateController'; 3 | import { SupportRequestCreateUseCase } from './SupportRequestCreateUseCase'; 4 | 5 | export function supportRequestCreateFactory() { 6 | const useCases = new SupportRequestCreateUseCase(currentSupportRequestsRepository, currentUsersRepository); 7 | const controller = new SupportRequestCreateController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/support-request/delete/DeleteSupportRequestController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteSupportRequestUseCase } from './DeleteSupportRequestUseCase'; 3 | 4 | export class DeleteSupportRequestController { 5 | 6 | constructor( 7 | private deleteSupportRequestUseCase: DeleteSupportRequestUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteSupportRequestUseCase.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/repositories/payment-methods/IPaymentMethodsRepository.ts: -------------------------------------------------------------------------------- 1 | import { IPaymentMethod } from '../../entities/payment-method/IPaymentMethod'; 2 | import { PaymentMethodCreateRequest } from '../../entities/payment-method/dtos/PaymentMethodCreateRequest'; 3 | 4 | export interface IPaymentMethodsRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | create({ name }: PaymentMethodCreateRequest): Promise; 11 | 12 | delete(id: string): Promise; 13 | 14 | cleanRepository(): void; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/repositories/revoked-tokens/IRevokedTokensRepository.ts: -------------------------------------------------------------------------------- 1 | import { IRevokedToken } from '../../entities/revoked-token/IRevokedToken'; 2 | import { RevokedTokenCreateOrUpdatedRequest } from '../../entities/revoked-token/dtos/RevokedTokenCreateOrUpdateRequest'; 3 | 4 | export interface IRevokedTokensRepository { 5 | 6 | listByToken(token: string): Promise; 7 | 8 | createOrUpdate({ token, expiresIn }: RevokedTokenCreateOrUpdatedRequest): Promise; 9 | 10 | delete(token: string): Promise; 11 | 12 | deleteExpiredTokens(): Promise; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentFailedImagesUploadedRepository } from '../../../repositories'; 2 | import { CreateFailedImageUploadedController } from './CreateFailedImageUploadedController'; 3 | import { CreateFailedImageUploadedUseCases } from './CreateFailedImageUploadedUseCases'; 4 | 5 | export function createFailedImageUploadedFactory() { 6 | const useCases = new CreateFailedImageUploadedUseCases(currentFailedImagesUploadedRepository); 7 | const controller = new CreateFailedImageUploadedController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-order/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintOrdersRepository } from '../../../repositories'; 2 | import { ListPrintOrdersController } from './ListPrintOrdersController'; 3 | import { ListPrintOrdersUseCases } from './ListPrintOrdersUseCases'; 4 | 5 | export function listPrintOrdersFactory() { 6 | const listPrintOrdersUseCases = new ListPrintOrdersUseCases(currentPrintOrdersRepository); 7 | const listPrintOrdersController = new ListPrintOrdersController(listPrintOrdersUseCases); 8 | 9 | return { useCases: listPrintOrdersUseCases, controller: listPrintOrdersController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-price/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintPricesRepository } from '../../../repositories'; 2 | import { ListPrintPricesController } from './ListPrintPricesController'; 3 | import { ListPrintPricesUseCases } from './ListPrintPricesUseCases'; 4 | 5 | export function listPrintPricesFactory() { 6 | const listPrintPricesUseCases = new ListPrintPricesUseCases(currentPrintPricesRepository); 7 | const listPrintPricesController = new ListPrintPricesController(listPrintPricesUseCases); 8 | 9 | return { useCases: listPrintPricesUseCases, controller: listPrintPricesController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product-category/listAll/ListProductCategoriesController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListProductCategoriesUseCases } from './ListProductCategoriesUseCases'; 3 | 4 | export class ListProductCategoriesController { 5 | 6 | constructor( 7 | private listProductCategoriesUseCases: ListProductCategoriesUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const productCategories = await this.listProductCategoriesUseCases.execute(); 12 | 13 | return res.json(productCategories); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/user/listByEmail/ListUserByEmailController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListUserByEmailUseCases } from './ListUserByEmailUseCases'; 3 | 4 | export class ListUserByEmailController { 5 | 6 | constructor( 7 | private listUserByEmailUseCases: ListUserByEmailUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { email } = req.params; 12 | 13 | const user = await this.listUserByEmailUseCases.execute(email, req.userId, req.userIsAdmin); 14 | 15 | return res.json(user); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/payment-method/listAll/ListPaymentMethodsUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPaymentMethod } from '../../../entities/payment-method/IPaymentMethod'; 2 | import { IPaymentMethodsRepository } from '../../../repositories/payment-methods/IPaymentMethodsRepository'; 3 | 4 | export class ListPaymentMethodsUseCases { 5 | 6 | constructor( 7 | private paymentMethodsRepository: IPaymentMethodsRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const paymentMethods = await this.paymentMethodsRepository.listAll(); 12 | 13 | return paymentMethods; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/print-order/listById/ListPrintOrderByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPrintOrderByIdUseCases } from './ListPrintOrderByIdUseCases'; 3 | 4 | export class ListPrintOrderByIdController { 5 | 6 | constructor( 7 | private listPrintOrderByIdUseCases: ListPrintOrderByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const printOrder = await this.listPrintOrderByIdUseCases.execute(id); 14 | 15 | return res.json(printOrder); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/purchase-order/delete/DeletePurchaseOrderController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeletePurchaseOrderUseCases } from './DeletePurchaseOrderUseCases'; 3 | 4 | export class DeletePurchaseOrderController { 5 | 6 | constructor( 7 | private deletePurchaseOrderUseCases: DeletePurchaseOrderUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deletePurchaseOrderUseCases.execute(id, req.userId); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/deleteShoppingCartProducts/index.ts: -------------------------------------------------------------------------------- 1 | import { currentShoppingCartsRepository } from '../../../repositories'; 2 | import { DeleteShoppingCartProductsController } from './DeleteShoppingCartProductsController'; 3 | import { DeleteShoppingCartProductsUseCases } from './DeleteShoppingCartProductsUseCases'; 4 | 5 | export function deleteShoppingCartProductsFactory() { 6 | const useCases = new DeleteShoppingCartProductsUseCases(currentShoppingCartsRepository); 7 | const controller = new DeleteShoppingCartProductsController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/validate-recovery-password-token/ValidateRecoveryPasswordTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 2 | import { passwordRecoveryTokenProvider } from '../../../providers/PasswordRecoveryToken'; 3 | 4 | export class ValidateRecoveryPasswordTokenUseCase { 5 | 6 | async execute(recoveryPasswordToken: string): Promise { 7 | 8 | if(!recoveryPasswordToken) { 9 | throw new RequiredFieldsError('Token'); 10 | } 11 | 12 | await passwordRecoveryTokenProvider.verifyToken({ id: recoveryPasswordToken }); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/middlewares/ensureAdminUser.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { NotFoundHTMLTemplate } from '../shared/NotFoundHTMLTemplate'; 3 | import { verifyUserAuth } from '../services/verify-user-auth'; 4 | 5 | export async function ensureAdminUser(req: Request, res: Response, next: NextFunction) { 6 | const { userId } = req; 7 | 8 | const html = NotFoundHTMLTemplate.getHTML(req.originalUrl, req.method); 9 | 10 | try { 11 | await verifyUserAuth.ensureAdminUser(userId); 12 | } catch { 13 | return res.status(404).send(html); 14 | } 15 | 16 | next(); 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/deleteAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentFailedImagesUploadedRepository } from '../../../repositories'; 2 | import { DeleteFailedImagesUploadedController } from './DeleteFailedImagesUploadedController'; 3 | import { DeleteFailedImagesUploadedUseCases } from './DeleteFailedImagesUploadedUseCases'; 4 | 5 | export function deleteFailedImagesUploadedFactory() { 6 | const useCases = new DeleteFailedImagesUploadedUseCases(currentFailedImagesUploadedRepository); 7 | const controller = new DeleteFailedImagesUploadedController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-price/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintPricesRepository } from '../../../repositories'; 2 | import { CreatePrintPriceController } from './CreatePrintPriceController'; 3 | import { CreatePrintPriceUseCases } from './CreatePrintPriceUseCases'; 4 | 5 | export function createPrintPriceFactory() { 6 | const createPrintPriceUseCases = new CreatePrintPriceUseCases(currentPrintPricesRepository); 7 | const createPrintPriceController = new CreatePrintPriceController(createPrintPriceUseCases); 8 | 9 | return { useCases: createPrintPriceUseCases, controller: createPrintPriceController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product-category/delete/DeleteProductCategoryController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteProductCategoryUseCases } from './DeleteProductCategoryUseCases'; 3 | 4 | export class DeleteProductCategoryController { 5 | 6 | constructor( 7 | private deleteProductCategoryUseCases: DeleteProductCategoryUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | await this.deleteProductCategoryUseCases.execute(id); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/auth/send-new-validate-email/SendNewValidateEmailController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SendNewValidateEmailUseCase } from './SendNewValidateEmailuseCase'; 3 | 4 | export class SendNewValidateEmailController { 5 | 6 | constructor( 7 | private sendNewValdiateEmailUseCase: SendNewValidateEmailUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { email } = req.body; 12 | 13 | await this.sendNewValdiateEmailUseCase.execute(email, req.userId); 14 | 15 | return res.sendStatus(200); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/deleteAll/DeleteFailedImagesUploadedController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteFailedImagesUploadedUseCases } from './DeleteFailedImagesUploadedUseCases'; 3 | 4 | export class DeleteFailedImagesUploadedController { 5 | 6 | constructor( 7 | private deleteFailedImagesUploadedUseCases: DeleteFailedImagesUploadedUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | 12 | await this.deleteFailedImagesUploadedUseCases.execute(); 13 | 14 | return res.sendStatus(204); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/support-request/create/SupportRequestCreateController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SupportRequestCreateUseCase } from './SupportRequestCreateUseCase'; 3 | 4 | export class SupportRequestCreateController { 5 | 6 | constructor( 7 | private supportRequestCreateUseCase: SupportRequestCreateUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { email } = req.body; 12 | 13 | await this.supportRequestCreateUseCase.execute({ email }, req.userId); 14 | 15 | return res.sendStatus(201); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/support-request/listAll/ListSupportRequestsUseCase.ts: -------------------------------------------------------------------------------- 1 | import { ISupportRequest } from '../../../entities/support-request/ISupportRequest'; 2 | import { ISupportRequestsRepository } from '../../../repositories/support-requests/ISupportRequestsRepository'; 3 | 4 | export class ListSupportRequestsUseCase { 5 | 6 | constructor( 7 | private supportRequestsRepository: ISupportRequestsRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const supportRequests = await this.supportRequestsRepository.listAll(); 12 | 13 | return supportRequests; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/listByKey/index.ts: -------------------------------------------------------------------------------- 1 | import { currentFailedImagesUploadedRepository } from '../../../repositories'; 2 | import { ListFailedImageUploadedByKeyController } from './ListFailedImageUploadedByKeyController'; 3 | import { ListFailedImageUploadedByKeyUseCases } from './ListFailedImageUploadedByKeyUseCases'; 4 | 5 | export function listFailedImageUploadedByKeyFactory() { 6 | const useCases = new ListFailedImageUploadedByKeyUseCases(currentFailedImagesUploadedRepository); 7 | const controller = new ListFailedImageUploadedByKeyController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/notification/listById/ListNotificationByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListNotificationByIdUseCases } from './ListNotificationByIdUseCases'; 3 | 4 | export class ListNotificationByIdController { 5 | 6 | constructor( 7 | private listNotificationByIdUseCases: ListNotificationByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const notification = await this.listNotificationByIdUseCases.execute(id); 14 | 15 | return res.json(notification); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print-price/create/CreatePrintPriceController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreatePrintPriceUseCases } from './CreatePrintPriceUseCases'; 3 | 4 | export class CreatePrintPriceController { 5 | 6 | constructor( 7 | private createPrintPriceUseCases: CreatePrintPriceUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { length, price } = req.body; 12 | 13 | const printPrice = await this.createPrintPriceUseCases.execute({ length, price }); 14 | 15 | return res.status(201).json(printPrice); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listByUserId/index.ts: -------------------------------------------------------------------------------- 1 | import { currentShoppingCartsRepository, currentUsersRepository } from '../../../repositories'; 2 | import { ListShoppingCartByUserIdController } from './ListShoppingCartByUserIdController'; 3 | import { ListShoppingCartByUserIdUseCases } from './ListShoppingCartByUserIdUseCases'; 4 | 5 | export function listShoppingCartByUserIdFactory() { 6 | const useCases = new ListShoppingCartByUserIdUseCases(currentShoppingCartsRepository, currentUsersRepository); 7 | const controller = new ListShoppingCartByUserIdController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/recovery-password/index.ts: -------------------------------------------------------------------------------- 1 | import { NodemailerEmailService } from '../../../providers/emails/NodemailerEmailService'; 2 | import { currentUsersRepository } from '../../../repositories'; 3 | import { RecoveryPasswordController } from './RecoveryPasswordController'; 4 | import { RecoveryPasswordUseCase } from './RecoveryPasswordUseCase'; 5 | 6 | export function recoveryPasswordFactory() { 7 | const useCases = new RecoveryPasswordUseCase(currentUsersRepository, new NodemailerEmailService()); 8 | const controller = new RecoveryPasswordController(useCases); 9 | 10 | return { useCases, controller }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/user/set-password/SetPasswordController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SetPasswordUseCase } from './SetPasswordUseCase'; 3 | 4 | export class SetPasswordController { 5 | 6 | constructor( 7 | private setPasswordUseCase: SetPasswordUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { token, newPassword, confirmNewPassword } = req.body; 12 | 13 | await this.setPasswordUseCase.execute({ passwordRecoveryTokenId: token, newPassword, confirmNewPassword }); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/repositories/product-categories/IProductCategoriesRepository.ts: -------------------------------------------------------------------------------- 1 | import { IProductCategory } from '../../entities/product-category/IProductCategory'; 2 | import { ProductCategoryCreateRequest } from '../../entities/product-category/dtos/ProductCategoryCreateRequest'; 3 | 4 | export interface IProductCategoriesRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | create({ name }: ProductCategoryCreateRequest): Promise; 11 | 12 | delete(id: string): Promise; 13 | 14 | cleanRepository(): void; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/listAll/ListFailedImagesUploadedController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListFailedImagesUploadedUseCases } from './ListFailedImagesUploadedUseCases'; 3 | 4 | export class ListFailedImagesUploadedController { 5 | 6 | constructor( 7 | private listFailedImagesUploadedUseCases: ListFailedImagesUploadedUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const failedImagesUploaded = await this.listFailedImagesUploadedUseCases.execute(); 12 | 13 | return res.json(failedImagesUploaded); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/print/listByProperties/ListPrintsUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPrint } from '../../../entities/print-order/print/IPrint'; 2 | import { IPrintsRepository } from '../../../repositories/prints/IPrintsRepository'; 3 | import { PrintFilter } from '../../../shared/filters/PrintFilter'; 4 | 5 | export class ListPrintsUseCases { 6 | 7 | constructor( 8 | private printsRepository: IPrintsRepository, 9 | ) { } 10 | 11 | async execute(filterProperties: PrintFilter): Promise { 12 | const prints = await this.printsRepository.listManyByProperties(filterProperties); 13 | 14 | return prints; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/addShoppingCartProduct/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductsRepository, currentShoppingCartsRepository } from '../../../repositories'; 2 | import { AddShoppingCartProductController } from './AddShoppingCartProductController'; 3 | import { AddShoppingCartProductUseCases } from './AddShoppingCartProductUseCases'; 4 | 5 | export function addShoppingCartProductFactory() { 6 | const useCases = new AddShoppingCartProductUseCases(currentShoppingCartsRepository, currentProductsRepository); 7 | const controller = new AddShoppingCartProductController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/services/validate.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | class ValidateService { 3 | 4 | static someIsNullOrUndefined(...values: any[]) { 5 | const nullOrUndefined: any[] = [null, undefined]; 6 | 7 | if(nullOrUndefined.includes(values)) { 8 | return true; 9 | } 10 | 11 | return values.some(value => nullOrUndefined.includes(value)); 12 | } 13 | 14 | static someIsNull(...values: any[]) { 15 | if(values === null) { 16 | return true; 17 | } 18 | 19 | return values.some(value => value === null); 20 | } 21 | 22 | } 23 | 24 | export { ValidateService }; 25 | -------------------------------------------------------------------------------- /src/modules/payment-method/create/CreatePaymentMethodController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreatePaymentMethodUseCases } from './CreatePaymentMethodUseCases'; 3 | 4 | export class CreatePaymentMethodController { 5 | 6 | constructor( 7 | private createPaymentMethodUseCases: CreatePaymentMethodUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { name } = req.body; 12 | 13 | const paymentMethod = await this.createPaymentMethodUseCases.execute({ name }); 14 | 15 | return res.status(201).json(paymentMethod); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/payment-method/listById/ListPaymentMethodByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPaymentMethodByIdUseCases } from './ListPaymentMethodByIdUseCases'; 3 | 4 | export class ListPaymentMethodByIdController { 5 | 6 | constructor( 7 | private listPaymentMethodbyIdUseCases: ListPaymentMethodByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const paymentMethod = await this.listPaymentMethodbyIdUseCases.execute(id); 14 | 15 | return res.json(paymentMethod); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print/listByProperties/ListPrintsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPrintsUseCases } from './ListPrintsUseCases'; 3 | 4 | export class ListPrintsController { 5 | 6 | constructor( 7 | private listPrintsUseCases: ListPrintsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { key, printOrderId } = req.query as { 12 | key: string, printOrderId: string, 13 | }; 14 | 15 | const prints = await this.listPrintsUseCases.execute({ key, printOrderId }); 16 | 17 | return res.json(prints); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/user/delete-account/UserDeleteAccountController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UserDeleteAccountUseCase } from './UserDeleteAccountUseCase'; 3 | 4 | export class UserDeleteAccountController { 5 | 6 | constructor( 7 | private userDeleteAccountUseCase: UserDeleteAccountUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id: userId } = req.params; 12 | const { password } = req.body; 13 | 14 | await this.userDeleteAccountUseCase.execute({ userId, password }); 15 | 16 | return res.sendStatus(204); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/repositories/refresh-tokens/IRefreshTokensRepository.ts: -------------------------------------------------------------------------------- 1 | import { IRefreshToken } from '../../entities/refresh-token/IRefreshToken'; 2 | import { RefreshTokenCreateRequest } from '../../entities/refresh-token/dtos/RefreshTokenCreateRequest'; 3 | import { RefreshTokenFilter } from '../../shared/filters/RefreshTokenFilter'; 4 | 5 | export interface IRefreshTokensRepository { 6 | 7 | listByProperties({ refreshTokenId, userId }: RefreshTokenFilter): Promise; 8 | 9 | create({ expiresIn, userId }: RefreshTokenCreateRequest): Promise; 10 | 11 | delete(refreshToken: string): Promise; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/deleteByKey/index.ts: -------------------------------------------------------------------------------- 1 | import { currentFailedImagesUploadedRepository } from '../../../repositories'; 2 | import { DeleteFailedImageUploadedByKeyController } from './DeleteFailedImageUploadedByKeyController'; 3 | import { DeleteFailedImageUploadedByKeyUseCases } from './DeleteFailedImageUploadedByKeyUseCases'; 4 | 5 | export function deleteFailedImageUploadedByKeyFactory() { 6 | const useCases = new DeleteFailedImageUploadedByKeyUseCases(currentFailedImagesUploadedRepository); 7 | const controller = new DeleteFailedImageUploadedByKeyController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-order/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintOrdersRepository } from '../../../repositories'; 2 | import { ListPrintOrderByIdController } from './ListPrintOrderByIdController'; 3 | import { ListPrintOrderByIdUseCases } from './ListPrintOrderByIdUseCases'; 4 | 5 | export function listPrintOrderByIdFactory() { 6 | const listPrintOrderByIdUseCases = new ListPrintOrderByIdUseCases(currentPrintOrdersRepository); 7 | const listPrintOrderByIdController = new ListPrintOrderByIdController(listPrintOrderByIdUseCases); 8 | 9 | return { useCases: listPrintOrderByIdUseCases, controller: listPrintOrderByIdController }; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230220160157_create_password_recovery_tokens_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "PasswordRecoveryToken" ( 3 | "id" TEXT NOT NULL, 4 | "expiresIn" DECIMAL(65,30) NOT NULL, 5 | "userId" TEXT NOT NULL, 6 | 7 | CONSTRAINT "PasswordRecoveryToken_pkey" PRIMARY KEY ("id") 8 | ); 9 | 10 | -- CreateIndex 11 | CREATE UNIQUE INDEX "PasswordRecoveryToken_userId_key" ON "PasswordRecoveryToken"("userId"); 12 | 13 | -- AddForeignKey 14 | ALTER TABLE "PasswordRecoveryToken" ADD CONSTRAINT "PasswordRecoveryToken_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; 15 | -------------------------------------------------------------------------------- /src/modules/print-price/listByLength/ListPrintPriceByLengthController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPrintPriceByLengthUseCases } from './ListPrintPriceByLengthUseCases'; 3 | 4 | export class ListPrintPriceByLengthController { 5 | 6 | constructor( 7 | private listPrintPriceByLengthUseCases: ListPrintPriceByLengthUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { length } = req.params; 12 | 13 | const printPrice = await this.listPrintPriceByLengthUseCases.execute(length); 14 | 15 | return res.json(printPrice); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product-category/listAll/ListProductCategoriesUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IProductCategory } from '../../../entities/product-category/IProductCategory'; 2 | import { IProductCategoriesRepository } from '../../../repositories/product-categories/IProductCategoriesRepository'; 3 | 4 | export class ListProductCategoriesUseCases { 5 | 6 | constructor( 7 | private productCategoriesRepository: IProductCategoriesRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const productCategories = await this.productCategoriesRepository.listAll(); 12 | 13 | return productCategories; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/purchase-order/listById/ListPurchaseOrderByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPurchaseOrderByIdUseCases } from './ListPurchaseOrderByIdUseCases'; 3 | 4 | export class ListPurchaseOrderByIdController { 5 | 6 | constructor( 7 | private listPurchaseOrderByIdUseCases: ListPurchaseOrderByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const purchaseOrder = await this.listPurchaseOrderByIdUseCases.execute(id, req.userId); 14 | 15 | return res.json(purchaseOrder); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/services/parse-boolean.ts: -------------------------------------------------------------------------------- 1 | class ParseBoolean { 2 | 3 | static parse(value: any): boolean { 4 | if(typeof value === 'string') { 5 | return value.toLowerCase() === 'true'; 6 | } 7 | 8 | if(typeof value === 'boolean') { 9 | return value; 10 | } 11 | 12 | return value === 'true'; 13 | } 14 | 15 | static literallyParse(value: 'true' | 'false'): boolean { 16 | if(value === 'true') { 17 | return true; 18 | } 19 | 20 | if(value === 'false') { 21 | return false; 22 | } 23 | 24 | throw new Error('Invalid boolean value'); 25 | } 26 | 27 | } 28 | 29 | export { ParseBoolean }; 30 | -------------------------------------------------------------------------------- /src/modules/print-order/create/CreatePrintOrderController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreatePrintOrderUseCases } from './CreatePrintOrderUseCases'; 3 | 4 | export class CreatePrintOrderController { 5 | 6 | constructor( 7 | private createPrintOrderUseCases: CreatePrintOrderUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { totalPrintsExpected, userId } = req.body; 12 | 13 | const printOrder = await this.createPrintOrderUseCases.execute({ totalPrintsExpected, userId }); 14 | 15 | return res.status(201).json(printOrder); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/repositories/support-requests/ISupportRequestsRepository.ts: -------------------------------------------------------------------------------- 1 | import { ISupportRequest } from '../../entities/support-request/ISupportRequest'; 2 | import { SupportRequestCreateRequest } from '../../entities/support-request/dtos/SupportRequestCreateRequest'; 3 | 4 | export interface ISupportRequestsRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | create(request: SupportRequestCreateRequest): Promise; 11 | 12 | updateResolved(id: string, resolved: boolean): Promise; 13 | 14 | delete(id: string): Promise; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /prisma/migrations/20230219211107_added_cascade_deletion_to_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- DropForeignKey 2 | ALTER TABLE "inactive_users" DROP CONSTRAINT "inactive_users_userId_fkey"; 3 | 4 | -- DropForeignKey 5 | ALTER TABLE "refresh_tokens" DROP CONSTRAINT "refresh_tokens_userId_fkey"; 6 | 7 | -- AddForeignKey 8 | ALTER TABLE "inactive_users" ADD CONSTRAINT "inactive_users_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; 9 | 10 | -- AddForeignKey 11 | ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; 12 | -------------------------------------------------------------------------------- /src/modules/auth/send-new-validate-email/index.ts: -------------------------------------------------------------------------------- 1 | import { NodemailerEmailService } from '../../../providers/emails/NodemailerEmailService'; 2 | import { currentUsersRepository } from '../../../repositories'; 3 | import { SendNewValidateEmailController } from './SendNewValidateEmailController'; 4 | import { SendNewValidateEmailUseCase } from './SendNewValidateEmailuseCase'; 5 | 6 | export function sendNewValidateEmailFactory() { 7 | const useCase = new SendNewValidateEmailUseCase(currentUsersRepository, new NodemailerEmailService()); 8 | const controller = new SendNewValidateEmailController(useCase); 9 | 10 | return { useCase, controller }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/print-order/listByUserId/ListPrintOrdersByUserIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPrintOrdersByUserIdUseCases } from './ListPrintOrdersByUserIdUseCases'; 3 | 4 | export class ListPrintOrdersByUserIdController { 5 | 6 | constructor( 7 | private listPrintOrdersByUserIdUseCases: ListPrintOrdersByUserIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userId } = req.params; 12 | 13 | const printOrders = await this.listPrintOrdersByUserIdUseCases.execute(userId); 14 | 15 | return res.json(printOrders); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product-category/create/CreateProductCategoryController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreateProductCategoryUseCases } from './CreateProductCategoryUseCases'; 3 | 4 | export class CreateProductCategoryController { 5 | 6 | constructor( 7 | private createProductCategoryUseCases: CreateProductCategoryUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { name } = req.body; 12 | 13 | const productCategory = await this.createProductCategoryUseCases.execute({ name }); 14 | 15 | return res.status(201).json(productCategory); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/product-category/listById/ListProductCategoryByIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListProductCategoryByIdUseCases } from './ListProductCategoryByIdUseCases'; 3 | 4 | export class ListProductCategoryByIdController { 5 | 6 | constructor( 7 | private listProductCategoryByIdUseCases: ListProductCategoryByIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | 13 | const productCategory = await this.listProductCategoryByIdUseCases.execute(id); 14 | 15 | return res.json(productCategory); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/notification/create/CreateNotificationController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreateNotificationUseCases } from './CreateNotificationUseCases'; 3 | 4 | export class CreateNotificationController { 5 | 6 | constructor( 7 | private createNotificationUseCases: CreateNotificationUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { title, message, userId } = req.body; 12 | 13 | const notification = await this.createNotificationUseCases.execute({ title, message, userId }); 14 | 15 | return res.status(201).json(notification); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print-order/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintOrdersRepository, currentPrintsRepository } from '../../../repositories'; 2 | import { DeletePrintOrderController } from './DeletePrintOrderController'; 3 | import { DeletePrintOrderUseCases } from './DeletePrintOrderUseCases'; 4 | 5 | export function deletePrintOrderFactory() { 6 | const deletePrintOrderUseCases = new DeletePrintOrderUseCases(currentPrintOrdersRepository, currentPrintsRepository); 7 | const deletePrintOrderController = new DeletePrintOrderController(deletePrintOrderUseCases); 8 | 9 | return { useCases: deletePrintOrderUseCases, controller: deletePrintOrderController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/print-price/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintPricesRepository, currentPrintsRepository } from '../../../repositories'; 2 | import { DeletePrintPriceController } from './DeletePrintPriceController'; 3 | import { DeletePrintPriceUseCases } from './DeletePrintPriceUseCases'; 4 | 5 | export function deletePrintPriceFactory() { 6 | const deletePrintPriceUseCases = new DeletePrintPriceUseCases(currentPrintPricesRepository, currentPrintsRepository); 7 | const deletePrintPriceController = new DeletePrintPriceController(deletePrintPriceUseCases); 8 | 9 | return { useCases: deletePrintPriceUseCases, controller: deletePrintPriceController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/create/CreateUserController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | 3 | import { CreateUserUseCases } from './CreateUserUseCases'; 4 | 5 | export class CreateUserController { 6 | 7 | constructor( 8 | private createUserUseCases: CreateUserUseCases, 9 | ) { } 10 | 11 | async handle(req: Request, res: Response): Promise { 12 | const { name, email, phone, password, admin, notifyServicesByEmail } = req.body; 13 | 14 | const user = await this.createUserUseCases.execute({ name, email, phone, password, notifyServicesByEmail, admin }); 15 | 16 | return res.status(201).json(user); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /prisma/migrations/20230129223710_create_print_order_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateEnum 2 | CREATE TYPE "PrintOrderStatus" AS ENUM ('WAITING', 'IN_PRODUCTION', 'DONE'); 3 | 4 | -- CreateTable 5 | CREATE TABLE "print_orders" ( 6 | "id" TEXT NOT NULL, 7 | "status" "PrintOrderStatus" NOT NULL DEFAULT 'WAITING', 8 | "userId" TEXT NOT NULL, 9 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 10 | 11 | CONSTRAINT "print_orders_pkey" PRIMARY KEY ("id") 12 | ); 13 | 14 | -- AddForeignKey 15 | ALTER TABLE "print_orders" ADD CONSTRAINT "print_orders_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 16 | -------------------------------------------------------------------------------- /src/modules/notification/listByUserId/ListNotificationsByUserIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListNotificationsByUserIdUseCases } from './ListNotificationsByUserIdUseCases'; 3 | 4 | export class ListNotificationsByUserIdController { 5 | 6 | constructor( 7 | private listNotificationsByUserIdUseCases: ListNotificationsByUserIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userId } = req.params; 12 | 13 | const notifications = await this.listNotificationsByUserIdUseCases.execute(userId); 14 | 15 | return res.json(notifications); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print-price/updatePrice/UpdatePricePrintPriceController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdatePricePrintPriceUseCases } from './UpdatePricePrintPriceUseCases'; 3 | 4 | export class UpdatePricePrintPriceController { 5 | 6 | constructor( 7 | private updatePricePrintPriceUseCases: UpdatePricePrintPriceUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { price } = req.body; 13 | 14 | const printPrice = await this.updatePricePrintPriceUseCases.execute(id, { price }); 15 | 16 | return res.json(printPrice); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/print-price/updatePrice/index.ts: -------------------------------------------------------------------------------- 1 | import { UpdatePricePrintPriceController } from './UpdatePricePrintPriceController'; 2 | import { currentPrintPricesRepository } from '../../../repositories'; 3 | import { UpdatePricePrintPriceUseCases } from './UpdatePricePrintPriceUseCases'; 4 | 5 | export function updatePricePrintPriceFactory() { 6 | const updatePricePrintPriceUseCases = new UpdatePricePrintPriceUseCases(currentPrintPricesRepository); 7 | const updatePricePrintPriceController = new UpdatePricePrintPriceController(updatePricePrintPriceUseCases); 8 | 9 | return { useCases: updatePricePrintPriceUseCases, controller: updatePricePrintPriceController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/user/validate-recovery-password-token/ValidateRecoveryPasswordTokenController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ValidateRecoveryPasswordTokenUseCase } from './ValidateRecoveryPasswordTokenUseCase'; 3 | 4 | export class ValidateRecoveryPasswordTokenController { 5 | 6 | constructor( 7 | private validateRecoveryPasswordTokenUseCase: ValidateRecoveryPasswordTokenUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { token } = req.params; 12 | 13 | await this.validateRecoveryPasswordTokenUseCase.execute(token); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/repositories/prints/IPrintsRepository.ts: -------------------------------------------------------------------------------- 1 | import { PrintCreateRequest } from '../../entities/print-order/print/dtos/PrintCreateRequest'; 2 | import { IPrint } from '../../entities/print-order/print/IPrint'; 3 | import { PrintFilter } from '../../shared/filters/PrintFilter'; 4 | export interface IPrintsRepository { 5 | 6 | listManyByProperties({ printOrderId, colorId, key }: PrintFilter): Promise; 7 | 8 | listFirstByProperties({ printOrderId, colorId, key }: PrintFilter): Promise; 9 | 10 | create({ imageName, imageUrl, key, imageStoragedType, border, colorId, printPriceId, quantity, printOrderId }: PrintCreateRequest): Promise; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/deleteByKey/DeleteFailedImageUploadedByKeyController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteFailedImageUploadedByKeyUseCases } from './DeleteFailedImageUploadedByKeyUseCases'; 3 | 4 | export class DeleteFailedImageUploadedByKeyController { 5 | 6 | constructor( 7 | private deleteFailedImageUplaodedByKeyUseCases: DeleteFailedImageUploadedByKeyUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { key } = req.params; 12 | 13 | await this.deleteFailedImageUplaodedByKeyUseCases.execute(key); 14 | 15 | return res.sendStatus(204); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/print-price/listByLength/index.ts: -------------------------------------------------------------------------------- 1 | import { ListPrintPriceByLengthController } from './ListPrintPriceByLengthController'; 2 | import { currentPrintPricesRepository } from '../../../repositories'; 3 | import { ListPrintPriceByLengthUseCases } from './ListPrintPriceByLengthUseCases'; 4 | 5 | export function listPrintPriceByLengthFactory() { 6 | const listPrintPriceByLengthUseCases = new ListPrintPriceByLengthUseCases(currentPrintPricesRepository); 7 | const listPrintPriceByLengthController = new ListPrintPriceByLengthController(listPrintPriceByLengthUseCases); 8 | 9 | return { useCases: listPrintPriceByLengthUseCases, controller: listPrintPriceByLengthController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/product-category/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentProductCategoriesRepository } from '../../../repositories'; 2 | import { CreateProductCategoryController } from './CreateProductCategoryController'; 3 | import { CreateProductCategoryUseCases } from './CreateProductCategoryUseCases'; 4 | 5 | export function createProductCategoryFactory() { 6 | const createProductCategoryUseCases = new CreateProductCategoryUseCases(currentProductCategoriesRepository); 7 | const createProductCategoryController = new CreateProductCategoryController(createProductCategoryUseCases); 8 | 9 | return { useCases: createProductCategoryUseCases, controller: createProductCategoryController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/repositories/failed-images-uploaded/IFailedImagesUploadedRepository.ts: -------------------------------------------------------------------------------- 1 | import { IFailedImageUploaded } from '../../entities/failed-image-uploaded/IFailedImageUploaded'; 2 | import { FailedImageUploadedCreateRequest } from '../../entities/failed-image-uploaded/dtos/FailedImageUploadedCreateRequest'; 3 | 4 | export interface IFailedImageUploadedRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listByKey(key: string): Promise; 9 | 10 | create({ key, storagedType }: FailedImageUploadedCreateRequest): Promise; 11 | 12 | deleteByKey(key: string): Promise; 13 | 14 | deleteAll(): Promise; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/domain/RefreshTokenMapper.ts: -------------------------------------------------------------------------------- 1 | import { RefreshToken } from '@prisma/client'; 2 | import { IRefreshToken } from '../entities/refresh-token/IRefreshToken'; 3 | 4 | type RefreshTokenDomain = IRefreshToken; 5 | type RefreshTokenPersistence = RefreshToken; 6 | 7 | class RefreshTokenMapper { 8 | 9 | toDomain(refreshTokenPersistence: RefreshTokenPersistence): RefreshTokenDomain { 10 | return { 11 | id: refreshTokenPersistence.id, 12 | expiresIn: Number(refreshTokenPersistence.expiresIn), 13 | userId: refreshTokenPersistence.userId, 14 | }; 15 | } 16 | 17 | } 18 | 19 | const refreshTokenMapper = new RefreshTokenMapper(); 20 | 21 | export { refreshTokenMapper }; 22 | -------------------------------------------------------------------------------- /src/domain/RevokedTokenMapper.ts: -------------------------------------------------------------------------------- 1 | import { RevokedTokens } from '@prisma/client'; 2 | import { IRevokedToken } from '../entities/revoked-token/IRevokedToken'; 3 | 4 | type RevokedTokenDomain = IRevokedToken; 5 | type RevokedTokenPersistence = RevokedTokens; 6 | 7 | class RevokedTokenMapper { 8 | 9 | toDomain(revokedTokenPersistence: RevokedTokenPersistence): RevokedTokenDomain { 10 | return { 11 | id: revokedTokenPersistence.id, 12 | token: revokedTokenPersistence.token, 13 | expiresIn: Number(revokedTokenPersistence.expiresIn), 14 | }; 15 | } 16 | 17 | } 18 | 19 | const revokedTokenMapper = new RevokedTokenMapper(); 20 | 21 | export { revokedTokenMapper }; 22 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/listAll/ListFailedImagesUploadedUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IFailedImageUploaded } from '../../../entities/failed-image-uploaded/IFailedImageUploaded'; 2 | import { IFailedImageUploadedRepository } from '../../../repositories/failed-images-uploaded/IFailedImagesUploadedRepository'; 3 | 4 | export class ListFailedImagesUploadedUseCases { 5 | 6 | constructor( 7 | private failedImagesUploadedRepository: IFailedImageUploadedRepository, 8 | ) { } 9 | 10 | async execute(): Promise { 11 | const failedImagesUploaded = await this.failedImagesUploadedRepository.listAll(); 12 | 13 | return failedImagesUploaded; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/notification/updateRead/UpdateReadNotificationController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdateReadNotificationUseCases } from './UpdateReadNotificationUseCases'; 3 | 4 | export class UpdateReadNotificationController { 5 | 6 | constructor( 7 | private updateReadNotificationUseCases: UpdateReadNotificationUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { read } = req.body; 13 | 14 | const notification = await this.updateReadNotificationUseCases.execute(id, { read }, req.userId); 15 | 16 | return res.json(notification); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/print-order/updateStatus/UpdatePrintOrderStatusController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdatePrintOrderStatusUseCases } from './UpdatePrintOrderStatusUseCases'; 3 | 4 | export class UpdatePrintOrderStatusController { 5 | 6 | constructor( 7 | private updatePrintOrderStatusUseCases: UpdatePrintOrderStatusUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { status } = req.body; 13 | 14 | const printOrderUpdated = await this.updatePrintOrderStatusUseCases.execute(id, status); 15 | 16 | return res.json(printOrderUpdated); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/purchase-order/create/CreatePurchaseOrderController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreatePurchaseOrderUseCases } from './CreatePurchaseOrderUseCases'; 3 | 4 | export class CreatePurchaseOrderController { 5 | 6 | constructor( 7 | private createPurchaseOrderUseCases: CreatePurchaseOrderUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { paymentMethodId, products, userId } = req.body; 12 | 13 | const purchaseOrder = await this.createPurchaseOrderUseCases.execute({ paymentMethodId, products, userId }); 14 | 15 | return res.status(201).json(purchaseOrder); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/support-request/updateResolved/UpdateSupportRequestController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdateSupportRequestResolvedUseCase } from './UpdateSupportRequestUseCase'; 3 | 4 | export class UpdateSupportRequestController { 5 | 6 | constructor( 7 | private updateSupportRequestUseCase: UpdateSupportRequestResolvedUseCase, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { resolved } = req.body; 13 | 14 | const supportRequest = await this.updateSupportRequestUseCase.execute(id, { resolved }); 15 | 16 | return res.json(supportRequest); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/repositories/print-prices/IPrintPricesRepository.ts: -------------------------------------------------------------------------------- 1 | import { PrintPriceCreateRequest } from '../../entities/print-price/dtos/PrintPriceCreateRequest'; 2 | import { IPrintPrice } from '../../entities/print-price/IPrintPrice'; 3 | 4 | export interface IPrintPricesRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | listByLength(length: string): Promise; 11 | 12 | create({ length, price }: PrintPriceCreateRequest): Promise; 13 | 14 | updatePrice(id: string, newPrice: number): Promise; 15 | 16 | delete(id: string): Promise; 17 | 18 | cleanRepository(): void; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/listByKey/ListFailedImageUploadedByKeyController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListFailedImageUploadedByKeyUseCases } from './ListFailedImageUploadedByKeyUseCases'; 3 | 4 | export class ListFailedImageUploadedByKeyController { 5 | 6 | constructor( 7 | private listFailedImageUploadedByKeyUseCases: ListFailedImageUploadedByKeyUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { key } = req.params; 12 | 13 | const failedImageUploaded = await this.listFailedImageUploadedByKeyUseCases.execute(key); 14 | 15 | return res.json(failedImageUploaded); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/purchase-order/update/UpdatePurchaseOrderController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdatePurchaseOrderUseCases } from './UpdatePurchaseOrderUseCases'; 3 | 4 | export class UpdatePurchaseOrderController { 5 | 6 | constructor( 7 | private updatePurchaseOrderUseCases: UpdatePurchaseOrderUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { status, freight, discount } = req.body; 13 | 14 | const purchaseOrder = await this.updatePurchaseOrderUseCases.execute(id, { status, freight, discount }); 15 | 16 | return res.json(purchaseOrder); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/auth/signup/SignUpController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { SignUpUseCases } from './SignUpUseCases'; 3 | 4 | export class SignUpController { 5 | 6 | constructor( 7 | private signUpUseCases: SignUpUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { name, email, phone, password, confirmPassword, notifyServicesByEmail, acceptedTermsAndConditions } = req.body; 12 | 13 | const response = await this.signUpUseCases.execute({ name, email, phone, password, confirmPassword, notifyServicesByEmail, acceptedTermsAndConditions }); 14 | 15 | return res.status(201).json(response); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/purchase-order/updatePaymentMethod/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository, currentPurchaseOrdersRepository } from '../../../repositories'; 2 | import { UpdatePurchaseOrderPaymentMethodController } from './UpdatePurchaseOrderPaymentMethodController'; 3 | import { UpdatePurchaseOrderPaymentMethodUseCases } from './UpdatePurchaseOrderPaymentMethodUseCases'; 4 | 5 | export function updatePurchaseOrderPaymentMethodFactory() { 6 | const useCases = new UpdatePurchaseOrderPaymentMethodUseCases(currentPurchaseOrdersRepository, currentPaymentMethodsRepository); 7 | const controller = new UpdatePurchaseOrderPaymentMethodController(useCases); 8 | 9 | return { useCases, controller }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listByUserId/ListShoppingCartByUserIdController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListShoppingCartByUserIdUseCases } from './ListShoppingCartByUserIdUseCases'; 3 | 4 | export class ListShoppingCartByUserIdController { 5 | 6 | constructor( 7 | private listShoppingCartByUserIdUseCases: ListShoppingCartByUserIdUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userIdOfShoppingCartRequest } = req; 12 | 13 | const shoppingCart = await this.listShoppingCartByUserIdUseCases.execute(userIdOfShoppingCartRequest, req.userId); 14 | 15 | return res.json(shoppingCart); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /prisma/migrations/20230204190028_added_delete_cascade_to_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- DropForeignKey 2 | ALTER TABLE "shopping_cart_products" DROP CONSTRAINT "shopping_cart_products_shoppingCartId_fkey"; 3 | 4 | -- DropForeignKey 5 | ALTER TABLE "shopping_carts" DROP CONSTRAINT "shopping_carts_userId_fkey"; 6 | 7 | -- AddForeignKey 8 | ALTER TABLE "shopping_cart_products" ADD CONSTRAINT "shopping_cart_products_shoppingCartId_fkey" FOREIGN KEY ("shoppingCartId") REFERENCES "shopping_carts"("id") ON DELETE CASCADE ON UPDATE CASCADE; 9 | 10 | -- AddForeignKey 11 | ALTER TABLE "shopping_carts" ADD CONSTRAINT "shopping_carts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; 12 | -------------------------------------------------------------------------------- /src/modules/product/create/CreateProductController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreateProductUseCases } from './CreateProductUseCases'; 3 | 4 | export class CreateProductController { 5 | 6 | constructor( 7 | private createProductUseCases: CreateProductUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { name, description, price, categoryId } = req.body; 12 | const { imageName, imageUrl, key } = req.image; 13 | 14 | const product = await this.createProductUseCases.execute({ name, description, price, imageName, imageUrl, key, categoryId }); 15 | 16 | return res.status(201).json(product); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/failed-images-uploaded/create/CreateFailedImageUploadedController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreateFailedImageUploadedUseCases } from './CreateFailedImageUploadedUseCases'; 3 | 4 | export class CreateFailedImageUploadedController { 5 | 6 | constructor( 7 | private createFailedImageUploadedUseCases: CreateFailedImageUploadedUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { key, storagedType } = req.body; 12 | 13 | const failedImageUploaded = await this.createFailedImageUploadedUseCases.execute({ key, storagedType }); 14 | 15 | return res.status(201).json(failedImageUploaded); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/domain/ValidatorTokenMapper.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorToken } from '@prisma/client'; 2 | import { IValidatorToken } from '../entities/validator-token/IValidatorToken'; 3 | 4 | type ValidatorTokenDomain = IValidatorToken; 5 | type ValidatorTokenPersistence = ValidatorToken; 6 | 7 | class ValidatorTokenMapper { 8 | 9 | toDomain(validatorTokenPersistence: ValidatorTokenPersistence): ValidatorTokenDomain { 10 | return { 11 | id: validatorTokenPersistence.id, 12 | expiresIn: Number(validatorTokenPersistence.expiresIn), 13 | email: validatorTokenPersistence.email, 14 | }; 15 | } 16 | 17 | } 18 | 19 | const validatorTokenMapper = new ValidatorTokenMapper(); 20 | 21 | export { validatorTokenMapper }; 22 | -------------------------------------------------------------------------------- /src/modules/notification/delete/index.ts: -------------------------------------------------------------------------------- 1 | import { DeleteNotificationController } from './DeleteNotificationController'; 2 | import { currentNotificationsRepository } from '../../../repositories'; 3 | import { DeleteNotificationUseCases } from './DeleteNotificationUseCases'; 4 | import { NotificationsService } from '../../../services/notifications'; 5 | 6 | export function deleteNotificationFactory() { 7 | const deleteNotificationUseCases = new DeleteNotificationUseCases(new NotificationsService(currentNotificationsRepository)); 8 | const deleteNotificationController = new DeleteNotificationController(deleteNotificationUseCases); 9 | 10 | return { useCases: deleteNotificationUseCases, controller: deleteNotificationController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/repositories/validator-tokens/IValidatorTokensRepository.ts: -------------------------------------------------------------------------------- 1 | import { IValidatorToken } from '../../entities/validator-token/IValidatorToken'; 2 | import { ValidatorTokenCreateRequest } from '../../entities/validator-token/dtos/ValidatorTokenCreateRequest'; 3 | import { ListValidatorTokenBy } from '../../shared/ListValidatorTokenBy'; 4 | 5 | export interface IValidatorTokensRepository { 6 | 7 | listById(id: string): Promise; 8 | 9 | listByEmail(email: string): Promise; 10 | 11 | create({ expiresIn, email }: ValidatorTokenCreateRequest): Promise; 12 | 13 | delete({ id, email }: ListValidatorTokenBy): Promise; 14 | 15 | deleteExpiredTokens(): Promise; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/print-order/listByUserId/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintOrdersRepository, currentUsersRepository } from '../../../repositories'; 2 | import { ListPrintOrdersByUserIdController } from './ListPrintOrdersByUserIdController'; 3 | import { ListPrintOrdersByUserIdUseCases } from './ListPrintOrdersByUserIdUseCases'; 4 | 5 | export function listPrintOrdersByUserIdFactory() { 6 | const listPrintOrdersByUserIdUseCases = new ListPrintOrdersByUserIdUseCases(currentPrintOrdersRepository, currentUsersRepository); 7 | const listPrintOrdersByUserIdController = new ListPrintOrdersByUserIdController(listPrintOrdersByUserIdUseCases); 8 | 9 | return { useCases: listPrintOrdersByUserIdUseCases, controller: listPrintOrdersByUserIdController }; 10 | } 11 | -------------------------------------------------------------------------------- /src/modules/purchase-order/listAll/ListPurchaseOrdersController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPurchaseOrdersUseCases } from './ListPurchaseOrdersUseCases'; 3 | 4 | export class ListPurchaseOrdersController { 5 | 6 | constructor( 7 | private listPurchaseOrdersUseCases: ListPurchaseOrdersUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const userId = req.query.userId as string | undefined; 12 | const when = req.query.when as 'today' | 'lastweek' | 'lastmonth' | undefined; 13 | 14 | const purchaseOrders = await this.listPurchaseOrdersUseCases.execute(req.userId, userId, when); 15 | 16 | return res.json(purchaseOrders); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/purchase-order/create/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPaymentMethodsRepository, currentProductsRepository, currentPurchaseOrdersRepository, currentUsersRepository } from '../../../repositories'; 2 | import { CreatePurchaseOrderController } from './CreatePurchaseOrderController'; 3 | import { CreatePurchaseOrderUseCases } from './CreatePurchaseOrderUseCases'; 4 | 5 | export function createPurchaseOrderFactory() { 6 | const useCases = new CreatePurchaseOrderUseCases( 7 | currentPurchaseOrdersRepository, 8 | currentPaymentMethodsRepository, 9 | currentUsersRepository, 10 | currentProductsRepository, 11 | ); 12 | const controller = new CreatePurchaseOrderController(useCases); 13 | 14 | return { useCases, controller }; 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/user/updatePassword/UpdateUserPasswordController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdateUserPasswordUseCases } from './UpdateUserPasswordUseCases'; 3 | 4 | export class UpdateUserPasswordController { 5 | 6 | constructor( 7 | private updateUserPasswordUseCases: UpdateUserPasswordUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id: userId } = req.params; 12 | const { currentPassword, newPassword, confirmNewPassword } = req.body; 13 | 14 | const user = await this.updateUserPasswordUseCases.execute({ userId, currentPassword, newPassword, confirmNewPassword }, req.userIsAdmin); 15 | 16 | return res.json(user); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/notification/listAll/index.ts: -------------------------------------------------------------------------------- 1 | import { currentNotificationsRepository } from '../../../repositories'; 2 | import { NotificationsService } from '../../../services/notifications'; 3 | import { ListAllNotificationsController } from './ListAllNotificationController'; 4 | import { ListAllNotificationsUseCases } from './ListAllNotificationsUseCases'; 5 | 6 | export function listAllNotificationsFactory() { 7 | const listAllNotificationsUseCases = new ListAllNotificationsUseCases(new NotificationsService(currentNotificationsRepository)); 8 | const listAllNotificationsController = new ListAllNotificationsController(listAllNotificationsUseCases); 9 | 10 | return { useCases: listAllNotificationsUseCases, controller: listAllNotificationsController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/notification/listById/index.ts: -------------------------------------------------------------------------------- 1 | import { currentNotificationsRepository } from '../../../repositories'; 2 | import { NotificationsService } from '../../../services/notifications'; 3 | import { ListNotificationByIdController } from './ListNotificationByIdController'; 4 | import { ListNotificationByIdUseCases } from './ListNotificationByIdUseCases'; 5 | 6 | export function listNotificationByIdFactory() { 7 | const listNotificationByIdUseCases = new ListNotificationByIdUseCases(new NotificationsService(currentNotificationsRepository)); 8 | const listNotificationByIdController = new ListNotificationByIdController(listNotificationByIdUseCases); 9 | 10 | return { useCases: listNotificationByIdUseCases, controller: listNotificationByIdController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/print/create/CreatePrintController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { CreatePrintUseCases } from './CreatePrintUseCases'; 3 | 4 | export class CreatePrintController { 5 | 6 | constructor( 7 | private createPrintUseCases: CreatePrintUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { border, colorId, printPriceId, quantity, printOrderId } = req.body; 12 | const { imageName, imageUrl, key } = req.image; 13 | 14 | const print = await this.createPrintUseCases.execute({ 15 | imageName, imageUrl, key, border, colorId, printPriceId, quantity, printOrderId, 16 | }, req.userId); 17 | 18 | return res.status(201).json(print); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/deleteShoppingCartProducts/DeleteShoppingCartProductsController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { DeleteShoppingCartProductsUseCases } from './DeleteShoppingCartProductsUseCases'; 3 | 4 | export class DeleteShoppingCartProductsController { 5 | 6 | constructor( 7 | private deleteShoppingCartProductsUseCases: DeleteShoppingCartProductsUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userIdOfShoppingCartRequest } = req; 12 | const { productsId } = req.body; 13 | 14 | await this.deleteShoppingCartProductsUseCases.execute(userIdOfShoppingCartRequest, req.userId, productsId); 15 | 16 | return res.sendStatus(204); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/auth/signup/index.ts: -------------------------------------------------------------------------------- 1 | import { NodemailerEmailService } from '../../../providers/emails/NodemailerEmailService'; 2 | import { currentNotificationsRepository, currentShoppingCartsRepository, currentUsersRepository } from '../../../repositories'; 3 | import { NotificationsService } from '../../../services/notifications'; 4 | import { SignUpController } from './SignUpController'; 5 | import { SignUpUseCases } from './SignUpUseCases'; 6 | 7 | export function signUpFactory() { 8 | const useCases = new SignUpUseCases(currentUsersRepository, currentShoppingCartsRepository, new NotificationsService(currentNotificationsRepository), new NodemailerEmailService()); 9 | const controller = new SignUpController(useCases); 10 | 11 | return { useCases, controller }; 12 | } 13 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/addShoppingCartProduct/AddShoppingCartProductController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { AddShoppingCartProductUseCases } from './AddShoppingCartProductUseCases'; 3 | 4 | export class AddShoppingCartProductController { 5 | 6 | constructor( 7 | private addShoppingCartProductUseCases: AddShoppingCartProductUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { userIdOfShoppingCartRequest } = req; 12 | const { productId, quantity } = req.body; 13 | 14 | const product = await this.addShoppingCartProductUseCases.execute(userIdOfShoppingCartRequest, { productId, quantity }, req.userId); 15 | 16 | return res.status(201).json(product); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/errors/RequiredFieldsError.ts: -------------------------------------------------------------------------------- 1 | import { StringHelperService } from '../services/string-helper'; 2 | import { BadRequestError } from './BadRequestError'; 3 | 4 | export class RequiredFieldsError extends BadRequestError { 5 | 6 | constructor(...fields: string[]) { 7 | super(RequiredFieldsError.buildStringMessage(fields)); 8 | } 9 | 10 | static buildStringMessage(fields?: string[]) { 11 | if(typeof fields === 'object' && fields instanceof Array && fields.length > 0) { 12 | return `O${fields.length > 1 ? 's' : ''} campo${fields.length > 1 ? 's' : ''} ${StringHelperService.formatList(fields)} ${fields.length > 1 ? 'são' : 'é'} obrigatório${fields.length > 1 ? 's' : ''}`; 13 | } 14 | 15 | return 'Preencha todos os campos obrigatórios'; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/notification/create/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateNotificationUseCases } from './CreateNotificationUseCases'; 2 | import { currentNotificationsRepository, currentUsersRepository } from '../../../repositories'; 3 | import { CreateNotificationController } from './CreateNotificationController'; 4 | import { NotificationsService } from '../../../services/notifications'; 5 | 6 | export function createNotificationFactory() { 7 | const createNotificationUseCases = new CreateNotificationUseCases(new NotificationsService(currentNotificationsRepository), currentUsersRepository); 8 | const createNotificationController = new CreateNotificationController(createNotificationUseCases); 9 | 10 | return { useCases: createNotificationUseCases, controller: createNotificationController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/notification/updateRead/index.ts: -------------------------------------------------------------------------------- 1 | import { currentNotificationsRepository } from '../../../repositories'; 2 | import { NotificationsService } from '../../../services/notifications'; 3 | import { UpdateReadNotificationController } from './UpdateReadNotificationController'; 4 | import { UpdateReadNotificationUseCases } from './UpdateReadNotificationUseCases'; 5 | 6 | export function updateReadNotificationFactory() { 7 | const updateReadNotificationUseCases = new UpdateReadNotificationUseCases(new NotificationsService(currentNotificationsRepository)); 8 | const updateReadNotificationController = new UpdateReadNotificationController(updateReadNotificationUseCases); 9 | 10 | return { useCases: updateReadNotificationUseCases, controller: updateReadNotificationController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/purchase-order/updatePaymentMethod/UpdatePurchaseOrderPaymentMethodController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdatePurchaseOrderPaymentMethodUseCases } from './UpdatePurchaseOrderPaymentMethodUseCases'; 3 | 4 | export class UpdatePurchaseOrderPaymentMethodController { 5 | 6 | constructor( 7 | private updatePurchaseOrderPaymentMethodUseCases: UpdatePurchaseOrderPaymentMethodUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { paymentMethod } = req.body; 13 | 14 | const purchaseOrder = await this.updatePurchaseOrderPaymentMethodUseCases.execute(id, paymentMethod, req.userId); 15 | 16 | return res.json(purchaseOrder); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/repositories/notifications/INotificationsRepository.ts: -------------------------------------------------------------------------------- 1 | import { NotificationCreateRequest } from '../../entities/notification/dtos/NotificationCreateRequest'; 2 | import { INotification } from '../../entities/notification/INotification'; 3 | 4 | export interface INotificationsRepository { 5 | 6 | listAll(): Promise; 7 | 8 | listById(id: string): Promise; 9 | 10 | listByUserId(userId: string): Promise; 11 | 12 | create({ title, message, userId }: NotificationCreateRequest): Promise; 13 | 14 | updateRead(id: string, isRead: boolean): Promise; 15 | 16 | delete(id: string): Promise; 17 | 18 | deleteByUserId(userId: string): Promise; 19 | 20 | cleanRepository(): void; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/modules/colors/listById/ListColorByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IColor } from '../../../entities/colors/IColor'; 2 | import { ColorNotFoundError } from '../../../errors/ColorNotFoundError'; 3 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 4 | import { IColorsRepository } from '../../../repositories/colors/IColorsRepository'; 5 | 6 | export class ListColorByIdUseCases { 7 | 8 | constructor( 9 | private colorsRepository: IColorsRepository, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const color = await this.colorsRepository.listById(id); 18 | if(!color) { 19 | throw new ColorNotFoundError(); 20 | } 21 | 22 | return color; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/repositories/password-recovery-tokens/IPasswordRecoveryTokensRepository.ts: -------------------------------------------------------------------------------- 1 | import { IPasswordRecoveryToken } from '../../entities/password-recovery-token/IPasswordRecoveryToken'; 2 | import { PasswordRecoveryTokenCreateRequest } from '../../entities/password-recovery-token/dtos/PasswordRecoveryTokenCreateRequest'; 3 | import { PasswordRecoveryTokenFilter } from '../../shared/filters/PasswordRecoveryTokenFilter'; 4 | 5 | export interface IPasswordRecoveryTokensRepository { 6 | 7 | listBy(filter: PasswordRecoveryTokenFilter): Promise; 8 | 9 | create(createDTO: PasswordRecoveryTokenCreateRequest): Promise; 10 | 11 | delete(filter: PasswordRecoveryTokenFilter): Promise; 12 | 13 | deleteExpiredTokens(): Promise; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/print-order/listAll/ListPrintOrdersController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListPrintOrdersUseCases } from './ListPrintOrdersUseCases'; 3 | import { PrintOrderStatus } from '../../../entities/print-order/IPrintOrder'; 4 | 5 | export class ListPrintOrdersController { 6 | 7 | constructor( 8 | private listPrintOrdersUseCases: ListPrintOrdersUseCases, 9 | ) { } 10 | 11 | async handle(req: Request, res: Response): Promise { 12 | const status = req.query.status as PrintOrderStatus | undefined; 13 | const when = req.query.when as 'today' | 'lastweek' | 'lastmonth' | undefined; 14 | 15 | const printOrders = await this.listPrintOrdersUseCases.execute(status, when); 16 | 17 | return res.json(printOrders); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/print-order/listByUserIdStatus/index.ts: -------------------------------------------------------------------------------- 1 | import { currentPrintOrdersRepository, currentUsersRepository } from '../../../repositories'; 2 | import { ListPrintOrdersByUserIdStatusController } from './ListPrintOrdersByUserIdController'; 3 | import { ListPrintOrdersByUserIdStatusUseCases } from './ListPrintOrdersByUserIdUseCases'; 4 | 5 | export function listPrintOrdersByUserIdStatusFactory() { 6 | const listPrintOrdersByUserIdStatusUseCases = new ListPrintOrdersByUserIdStatusUseCases(currentPrintOrdersRepository, currentUsersRepository); 7 | const listPrintOrdersByUserIdStatusController = new ListPrintOrdersByUserIdStatusController(listPrintOrdersByUserIdStatusUseCases); 8 | 9 | return { useCases: listPrintOrdersByUserIdStatusUseCases, controller: listPrintOrdersByUserIdStatusController }; 10 | } 11 | -------------------------------------------------------------------------------- /prisma/migrations/20230212165107_created_purchase_order_product_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "purchase_order_product" ( 3 | "id" TEXT NOT NULL, 4 | "quantity" DECIMAL(65,30) NOT NULL DEFAULT 1, 5 | "productId" TEXT NOT NULL, 6 | "purchaseOrderId" TEXT NOT NULL, 7 | 8 | CONSTRAINT "purchase_order_product_pkey" PRIMARY KEY ("id") 9 | ); 10 | 11 | -- AddForeignKey 12 | ALTER TABLE "purchase_order_product" ADD CONSTRAINT "purchase_order_product_productId_fkey" FOREIGN KEY ("productId") REFERENCES "products"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 13 | 14 | -- AddForeignKey 15 | ALTER TABLE "purchase_order_product" ADD CONSTRAINT "purchase_order_product_purchaseOrderId_fkey" FOREIGN KEY ("purchaseOrderId") REFERENCES "purchase_orders"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 16 | -------------------------------------------------------------------------------- /src/domain/PrintPriceMapper.ts: -------------------------------------------------------------------------------- 1 | import { IPrintPrice } from './../entities/print-price/IPrintPrice'; 2 | import { PrintPrice, Prisma } from '.prisma/client'; 3 | 4 | type PrintPriceDomain = IPrintPrice; 5 | type PrintPricePersistence = PrintPrice; 6 | 7 | class PrintPriceMapper { 8 | 9 | toDomain(persistencePrintPrice: PrintPricePersistence): PrintPriceDomain { 10 | return { 11 | ...persistencePrintPrice, 12 | price: Number(persistencePrintPrice.price), 13 | }; 14 | } 15 | 16 | toPersistence(domainPrintPrice: PrintPriceDomain): PrintPricePersistence { 17 | return { 18 | ...domainPrintPrice, 19 | price: new Prisma.Decimal(domainPrintPrice.price), 20 | }; 21 | } 22 | 23 | } 24 | 25 | const printPriceMapper = new PrintPriceMapper(); 26 | 27 | export { printPriceMapper }; 28 | -------------------------------------------------------------------------------- /src/providers/emails/EmailService.ts: -------------------------------------------------------------------------------- 1 | export interface EmailService { 2 | 3 | sendEmail(to: string, subject: string, body: string): Promise; 4 | 5 | sendConfirmEmail(to: string, userName: string, validatorToken: string): Promise; 6 | 7 | sendRecoveryPasswordEmail(to: string, userName: string, passwordRecoveryToken: string): Promise; 8 | 9 | sendSupportEmail(to: string, userName: string): Promise; 10 | 11 | sendPrintOrderReleasedEmail(to: string, userName: string): Promise; 12 | 13 | sendPrintOrderInProductionEmail(to: string, userName: string): Promise; 14 | 15 | sendPrintOrderFinishedEmail(to: string, userName: string, date: string, time: string): Promise; 16 | 17 | sendPurchaseOrderReleasedEmail(to: string, userName: string): Promise; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/modules/product/listById/ListProductByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IProduct } from '../../../entities/product/IProduct'; 2 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 3 | import { ProductNotFoundError } from '../../../errors/ProductNotFoundError'; 4 | import { IProductsRepository } from '../../../repositories/product/IProductsRepository'; 5 | 6 | export class ListProductByIdUseCases { 7 | 8 | constructor( 9 | private productsRepository: IProductsRepository, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const product = await this.productsRepository.listById(id); 18 | if(!product) { 19 | throw new ProductNotFoundError(); 20 | } 21 | 22 | return product; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/middlewares/imageUploadCaptureError.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { createFailedImageUploadedFactory } from '../modules/failed-images-uploaded/create'; 3 | import { ImageStoragedService } from '../services/image-storaged-type'; 4 | 5 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 6 | export function imageUploadCaptureError(error: any, req: Request, res: Response, next: NextFunction) { 7 | if(req.file) { 8 | const { filename: keyLocal } = req.file; 9 | const { key: keyS3 } = req.file as unknown as { key: string }; 10 | 11 | const key = keyS3 || keyLocal; 12 | 13 | if(key) { 14 | createFailedImageUploadedFactory().useCases.execute({ key, storagedType: ImageStoragedService.getCurrentStorageType() }); 15 | } 16 | } 17 | 18 | throw error; 19 | } 20 | -------------------------------------------------------------------------------- /src/infra/scheduler.ts: -------------------------------------------------------------------------------- 1 | import cron from 'node-cron'; 2 | import { currentPasswordRecoveryTokensRepository, currentRevokedTokensRepository, currentValidatorTokensRepository } from '../repositories'; 3 | 4 | const task = cron.schedule('*/30 * * * *', async () => { 5 | try { 6 | await currentRevokedTokensRepository.deleteExpiredTokens(); 7 | } catch (err: any) { 8 | console.warn('Fail to delete revoked tokens:', err); 9 | } 10 | 11 | try { 12 | await currentValidatorTokensRepository.deleteExpiredTokens(); 13 | } catch (err: any) { 14 | console.warn('Fail to delete revoked tokens:', err); 15 | } 16 | 17 | try { 18 | await currentPasswordRecoveryTokensRepository.deleteExpiredTokens(); 19 | } catch (err: any) { 20 | console.warn('Fail to delete revoked tokens:', err); 21 | } 22 | }); 23 | 24 | task.start(); 25 | -------------------------------------------------------------------------------- /src/modules/colors/listByColor/ListByColorUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IColor } from '../../../entities/colors/IColor'; 2 | import { ColorNotFoundError } from '../../../errors/ColorNotFoundError'; 3 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 4 | import { IColorsRepository } from '../../../repositories/colors/IColorsRepository'; 5 | 6 | export class ListByColorUseCases { 7 | 8 | constructor( 9 | private colorsRepository: IColorsRepository, 10 | ) { } 11 | 12 | async execute(color: string): Promise { 13 | if(!color) { 14 | throw new RequiredFieldsError('Cor/descrição'); 15 | } 16 | 17 | const colorObj = await this.colorsRepository.listByColor(color); 18 | if(!colorObj) { 19 | throw new ColorNotFoundError(); 20 | } 21 | 22 | return colorObj; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/domain/PasswordRecoveryTokenMapper.ts: -------------------------------------------------------------------------------- 1 | import { PasswordRecoveryToken } from '@prisma/client'; 2 | import { IPasswordRecoveryToken } from '../entities/password-recovery-token/IPasswordRecoveryToken'; 3 | 4 | type PasswordRecoveryTokenDomain = IPasswordRecoveryToken; 5 | type PasswordRecoveryTokenPersistence = PasswordRecoveryToken; 6 | 7 | class PasswordRecoveryTokenMapper { 8 | 9 | toDomain(passwordRecoveryTokenPersistence: PasswordRecoveryTokenPersistence): PasswordRecoveryTokenDomain { 10 | return { 11 | id: passwordRecoveryTokenPersistence.id, 12 | expiresIn: Number(passwordRecoveryTokenPersistence.expiresIn), 13 | userId: passwordRecoveryTokenPersistence.userId, 14 | }; 15 | } 16 | 17 | } 18 | 19 | const passwordRecoveryTokenMapper = new PasswordRecoveryTokenMapper(); 20 | 21 | export { passwordRecoveryTokenMapper }; 22 | -------------------------------------------------------------------------------- /src/modules/notification/listByUserId/index.ts: -------------------------------------------------------------------------------- 1 | import { currentNotificationsRepository, currentUsersRepository } from '../../../repositories'; 2 | import { NotificationsService } from '../../../services/notifications'; 3 | import { ListNotificationsByUserIdController } from './ListNotificationsByUserIdController'; 4 | import { ListNotificationsByUserIdUseCases } from './ListNotificationsByUserIdUseCases'; 5 | 6 | export function listNotificationsByUserIdFactory() { 7 | const listNotificationsByUserIdUseCases = new ListNotificationsByUserIdUseCases(new NotificationsService(currentNotificationsRepository), currentUsersRepository); 8 | const listNotificationsByUserIdController = new ListNotificationsByUserIdController(listNotificationsByUserIdUseCases); 9 | 10 | return { useCases: listNotificationsByUserIdUseCases, controller: listNotificationsByUserIdController }; 11 | } 12 | -------------------------------------------------------------------------------- /src/modules/print-order/listById/ListPrintOrderByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPrintOrder } from '../../../entities/print-order/IPrintOrder'; 2 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 3 | import { PrintOrderNotFound } from '../../../errors/PrintOrderNotFoundError'; 4 | import { IPrintOrdersRepository } from '../../../repositories/print-orders/IPrintOrdersRepository'; 5 | 6 | export class ListPrintOrderByIdUseCases { 7 | 8 | constructor( 9 | private printOrdersRepository: IPrintOrdersRepository, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const printOrder = await this.printOrdersRepository.listById(id); 18 | if(!printOrder) { 19 | throw new PrintOrderNotFound(); 20 | } 21 | 22 | return printOrder; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/payment-method/delete/DeletePaymentMethodUseCaes.ts: -------------------------------------------------------------------------------- 1 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 2 | import { PaymentMethodNotFoundError } from '../../../errors/PaymentMethodNotFoundError'; 3 | import { IPaymentMethodsRepository } from '../../../repositories/payment-methods/IPaymentMethodsRepository'; 4 | 5 | export class DeletePaymentMethodUseCases { 6 | 7 | constructor( 8 | private paymentMethodsRepository: IPaymentMethodsRepository, 9 | ) { } 10 | 11 | async execute(id: string): Promise { 12 | if(!id) { 13 | throw new IDNotGivenError(); 14 | } 15 | 16 | const paymentMethodExists = await this.paymentMethodsRepository.listById(id); 17 | if(!paymentMethodExists) { 18 | throw new PaymentMethodNotFoundError(); 19 | } 20 | 21 | await this.paymentMethodsRepository.delete(id); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/notification/listById/ListNotificationByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 2 | import { INotification } from '../../../entities/notification/INotification'; 3 | import { NotificationNotFoundError } from '../../../errors/NotificationNotFoundError'; 4 | import { NotificationsService } from '../../../services/notifications'; 5 | 6 | export class ListNotificationByIdUseCases { 7 | 8 | constructor( 9 | private notificationsService: NotificationsService, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const notification = await this.notificationsService.getNotification(id); 18 | if(!notification) { 19 | throw new NotificationNotFoundError(); 20 | } 21 | 22 | return notification; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/support-request/delete/DeleteSupportRequestUseCase.ts: -------------------------------------------------------------------------------- 1 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 2 | import { SupportRequestNotFoundError } from '../../../errors/SupportRequestNotFoundError'; 3 | import { ISupportRequestsRepository } from '../../../repositories/support-requests/ISupportRequestsRepository'; 4 | 5 | export class DeleteSupportRequestUseCase { 6 | 7 | constructor( 8 | private supportRequestsRepository: ISupportRequestsRepository, 9 | ) { } 10 | 11 | async execute(id: string): Promise { 12 | if(!id) { 13 | throw new IDNotGivenError(); 14 | } 15 | 16 | const supportRequestExists = await this.supportRequestsRepository.listById(id); 17 | if(!supportRequestExists) { 18 | throw new SupportRequestNotFoundError(); 19 | } 20 | 21 | await this.supportRequestsRepository.delete(id); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es2021": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended" 9 | ], 10 | "overrides": [ 11 | ], 12 | "parser": "@typescript-eslint/parser", 13 | "parserOptions": { 14 | "ecmaVersion": "latest", 15 | "sourceType": "module" 16 | }, 17 | "plugins": [ 18 | "@typescript-eslint" 19 | ], 20 | "rules": { 21 | "indent": [ 22 | "error", 23 | 2 24 | ], 25 | "linebreak-style": [ 26 | "error", 27 | "unix" 28 | ], 29 | "quotes": [ 30 | "error", 31 | "single" 32 | ], 33 | "semi": [ 34 | "error", 35 | "always" 36 | ], 37 | "@typescript-eslint/no-empty-function": "off", 38 | "@typescript-eslint/ban-ts-comment": "off", 39 | "@typescript-eslint/no-explicit-any": "off" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/entities/print-order/IPrintOrder.ts: -------------------------------------------------------------------------------- 1 | import { PrintOrderStatus as PrismaPrintOrderStatus } from '@prisma/client'; 2 | import { IPrint } from './print/IPrint'; 3 | 4 | export type PrintOrderStatus = 'UPLOADING_IMAGES' | 'WAITING' | 'IN_PRODUCTION' | 'DONE'; 5 | 6 | export function isPrintOrderStatus(value: string) { 7 | return value.toUpperCase() in PrismaPrintOrderStatus; 8 | } 9 | 10 | export function convertPrintOrderStatus(status: string): PrintOrderStatus { 11 | if(!isPrintOrderStatus(status)) { 12 | throw new TypeError(); 13 | } 14 | 15 | const newStatus = status.toUpperCase().replace(' ', '_'); 16 | 17 | // @ts-ignore 18 | return newStatus; 19 | } 20 | 21 | export interface IPrintOrder { 22 | id: string; 23 | number: number; 24 | status: PrintOrderStatus; 25 | totalPrintsExpected: number; 26 | userId: string; 27 | prints: IPrint[]; 28 | createdAt: Date; 29 | } 30 | -------------------------------------------------------------------------------- /prisma/migrations/20230212192841_added_cascade_on_delete_to_purchase_order_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- DropForeignKey 2 | ALTER TABLE "purchase_order_products" DROP CONSTRAINT "purchase_order_products_purchaseOrderId_fkey"; 3 | 4 | -- DropForeignKey 5 | ALTER TABLE "purchase_orders" DROP CONSTRAINT "purchase_orders_userId_fkey"; 6 | 7 | -- AlterTable 8 | ALTER TABLE "purchase_orders" ALTER COLUMN "status" SET DEFAULT 'WAITING_PAYMENT', 9 | ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; 10 | 11 | -- AddForeignKey 12 | ALTER TABLE "purchase_orders" ADD CONSTRAINT "purchase_orders_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; 13 | 14 | -- AddForeignKey 15 | ALTER TABLE "purchase_order_products" ADD CONSTRAINT "purchase_order_products_purchaseOrderId_fkey" FOREIGN KEY ("purchaseOrderId") REFERENCES "purchase_orders"("id") ON DELETE CASCADE ON UPDATE CASCADE; 16 | -------------------------------------------------------------------------------- /src/modules/product-category/delete/DeleteProductCategoryUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 2 | import { ProductCategoryNotFoundError } from '../../../errors/ProductCategoryNotFoundError'; 3 | import { IProductCategoriesRepository } from '../../../repositories/product-categories/IProductCategoriesRepository'; 4 | 5 | export class DeleteProductCategoryUseCases { 6 | 7 | constructor( 8 | private productCategoriesRepository: IProductCategoriesRepository, 9 | ) { } 10 | 11 | async execute(id: string): Promise { 12 | if(!id) { 13 | throw new IDNotGivenError(); 14 | } 15 | 16 | const productCategoryExists = await this.productCategoriesRepository.listById(id); 17 | if(!productCategoryExists) { 18 | throw new ProductCategoryNotFoundError(); 19 | } 20 | 21 | await this.productCategoriesRepository.delete(id); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/payment-method/create/CreatePaymentMethodUseCases.ts: -------------------------------------------------------------------------------- 1 | import { PaymentMethodCreateRequest } from '../../../entities/payment-method/dtos/PaymentMethodCreateRequest'; 2 | import { IPaymentMethod } from '../../../entities/payment-method/IPaymentMethod'; 3 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 4 | import { IPaymentMethodsRepository } from '../../../repositories/payment-methods/IPaymentMethodsRepository'; 5 | 6 | export class CreatePaymentMethodUseCases { 7 | 8 | constructor( 9 | private paymentMethodsRepository: IPaymentMethodsRepository, 10 | ) { } 11 | 12 | async execute({ name }: PaymentMethodCreateRequest): Promise { 13 | if(!name) { 14 | throw new RequiredFieldsError('Nome'); 15 | } 16 | 17 | const paymentMethod = await this.paymentMethodsRepository.create({ name }); 18 | 19 | return paymentMethod; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/services/local-image-manager.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import { promisify } from 'util'; 4 | 5 | class LocalFileManagerService { 6 | 7 | static async deleteImage(imageKey: string) { 8 | const image = path.resolve(__dirname, '..', '..', 'tmp', 'uploads', imageKey); 9 | 10 | if(!fs.existsSync(image)) { 11 | throw new Error(`Image ${imageKey} not found to delete`); 12 | } 13 | 14 | const unlink = promisify(fs.unlink); 15 | await unlink(image); 16 | } 17 | 18 | static async deleteImages(imagesKey: string[]) { 19 | const unlink = promisify(fs.unlink); 20 | 21 | for(const imageKey of imagesKey) { 22 | const image = path.resolve(__dirname, '..', '..', 'tmp', 'uploads', imageKey); 23 | 24 | if(fs.existsSync(image)) { 25 | await unlink(image); 26 | } 27 | } 28 | } 29 | 30 | } 31 | 32 | export { LocalFileManagerService }; 33 | -------------------------------------------------------------------------------- /src/modules/user/update/UpdateUserController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { UpdateUserUseCases } from './UpdateUserUseCases'; 3 | 4 | export class UpdateUserController { 5 | 6 | constructor( 7 | private updateUserUseCases: UpdateUserUseCases, 8 | ) { } 9 | 10 | async handle(req: Request, res: Response): Promise { 11 | const { id } = req.params; 12 | const { name, password, phone, admin, notifyServicesByEmail, totalPrints, totalPrintOrders, totalPurchases, totalPurchaseOrders } = req.body; 13 | 14 | const user = await this.updateUserUseCases.execute(id, { 15 | name, 16 | password, 17 | phone, 18 | admin, 19 | notifyServicesByEmail, 20 | totalPrints, 21 | totalPrintOrders, 22 | totalPurchases, 23 | totalPurchaseOrders 24 | }, false, req.userIsAdmin); 25 | 26 | return res.json(user); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/modules/print-price/listByLength/ListPrintPriceByLengthUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPrintPrice } from '../../../entities/print-price/IPrintPrice'; 2 | import { PrintPriceNotFound } from '../../../errors/PrintPriceNotFoundError'; 3 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 4 | import { IPrintPricesRepository } from '../../../repositories/print-prices/IPrintPricesRepository'; 5 | 6 | export class ListPrintPriceByLengthUseCases { 7 | 8 | constructor( 9 | private printPricesRepository: IPrintPricesRepository, 10 | ) { } 11 | 12 | async execute(length: string): Promise { 13 | if(!length) { 14 | throw new RequiredFieldsError('Tamanho/tipo'); 15 | } 16 | 17 | const printPrice = await this.printPricesRepository.listByLength(length); 18 | if(!printPrice) { 19 | throw new PrintPriceNotFound(); 20 | } 21 | 22 | return printPrice; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/payment-method/listById/ListPaymentMethodByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IPaymentMethod } from '../../../entities/payment-method/IPaymentMethod'; 2 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 3 | import { PaymentMethodNotFoundError } from '../../../errors/PaymentMethodNotFoundError'; 4 | import { IPaymentMethodsRepository } from '../../../repositories/payment-methods/IPaymentMethodsRepository'; 5 | 6 | export class ListPaymentMethodByIdUseCases { 7 | 8 | constructor( 9 | private paymentMethodsRepository: IPaymentMethodsRepository, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const paymentMethod = await this.paymentMethodsRepository.listById(id); 18 | if(!paymentMethod) { 19 | throw new PaymentMethodNotFoundError(); 20 | } 21 | 22 | return paymentMethod; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/shopping-cart/listShoppingCartProduct/ListShoppingCartProductController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | import { ListShoppingCartProductUseCases } from './ListShoppingCartProductUseCases'; 3 | import { ShoppingCartProductNotFoundError } from '../../../errors/ShoppingCartProductNotFoundError'; 4 | 5 | export class ListShoppingCartProductController { 6 | 7 | constructor( 8 | private listShoppingCartProductUseCases: ListShoppingCartProductUseCases, 9 | ) { } 10 | 11 | async handle(req: Request, res: Response): Promise { 12 | const { userIdOfShoppingCartRequest } = req; 13 | const { productId } = req.params; 14 | 15 | const product = await this.listShoppingCartProductUseCases.execute(userIdOfShoppingCartRequest, productId, req.userId); 16 | if(!product) { 17 | throw new ShoppingCartProductNotFoundError(); 18 | } 19 | 20 | return res.json(product); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/services/s3.ts: -------------------------------------------------------------------------------- 1 | import { DeleteObjectCommand, DeleteObjectsCommand, S3Client } from '@aws-sdk/client-s3'; 2 | 3 | class S3ClientService { 4 | 5 | readonly client: S3Client; 6 | 7 | constructor(region: string, accessKeyId: string, secretAccessKey: string) { 8 | this.client = new S3Client({ 9 | region, 10 | credentials: { 11 | accessKeyId, 12 | secretAccessKey, 13 | }, 14 | }); 15 | } 16 | 17 | async deleteFile(bucketName: string, imageKey: string) { 18 | await this.client.send(new DeleteObjectCommand({ 19 | Bucket: bucketName, 20 | Key: imageKey, 21 | })); 22 | } 23 | 24 | async deleteFiles(bucketName: string, imagesKey: string[]) { 25 | await this.client.send(new DeleteObjectsCommand({ 26 | Bucket: bucketName, 27 | Delete: { 28 | Objects: imagesKey.map(key => ({ Key: key })), 29 | } 30 | })); 31 | } 32 | 33 | } 34 | 35 | export { S3ClientService }; 36 | -------------------------------------------------------------------------------- /src/domain/PurchaseOrderProductCreationMapper.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PurchaseOrderProduct } from '@prisma/client'; 2 | import { PurchaseOrderProductCreateRequest } from '../entities/purchase-order-product/dtos/PurchaseOrderProductCreateRequest'; 3 | 4 | type PurchaseOrderProductCreationDomain = PurchaseOrderProductCreateRequest; 5 | type PurchaseOrderProductCreationPersistence = Omit; 6 | 7 | class PurchaseOrderProductCreationMapper { 8 | 9 | toPersistence(purchaseOrderProductCreationDomain: PurchaseOrderProductCreationDomain): PurchaseOrderProductCreationPersistence { 10 | return { 11 | productId: purchaseOrderProductCreationDomain.productId, 12 | quantity: new Prisma.Decimal(purchaseOrderProductCreationDomain.quantity), 13 | }; 14 | } 15 | 16 | } 17 | 18 | const purchaseOrderProductCreationMapper = new PurchaseOrderProductCreationMapper(); 19 | 20 | export { purchaseOrderProductCreationMapper }; 21 | -------------------------------------------------------------------------------- /src/modules/product-category/create/CreateProductCategoryUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IProductCategory } from '../../../entities/product-category/IProductCategory'; 2 | import { ProductCategoryCreateRequest } from '../../../entities/product-category/dtos/ProductCategoryCreateRequest'; 3 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 4 | import { IProductCategoriesRepository } from '../../../repositories/product-categories/IProductCategoriesRepository'; 5 | 6 | export class CreateProductCategoryUseCases { 7 | 8 | constructor( 9 | private productCategoriesRepository: IProductCategoriesRepository, 10 | ) { } 11 | 12 | async execute({ name }: ProductCategoryCreateRequest): Promise { 13 | if(!name) { 14 | throw new RequiredFieldsError('Nome da categoria'); 15 | } 16 | 17 | const productCategory = await this.productCategoriesRepository.create({ name }); 18 | 19 | return productCategory; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/repositories/product/IProductsRepository.ts: -------------------------------------------------------------------------------- 1 | import { IProduct } from '../../entities/product/IProduct'; 2 | import { ProductCreateRequest } from '../../entities/product/dtos/ProductCreateRequest'; 3 | import { ProductUpdateRequest } from '../../entities/product/dtos/ProductUpdateRequest'; 4 | 5 | export interface IProductsRepository { 6 | 7 | listAll(): Promise; 8 | 9 | listByIds(ids: string[]): Promise; 10 | 11 | listById(id: string): Promise; 12 | 13 | listByCategoryId(categoryId: string): Promise; 14 | 15 | create({ name, description, price, imageName, imageUrl, key, categoryId, imageStoragedType }: ProductCreateRequest): Promise; 16 | 17 | update(id: string, { name, description, rated, price, imageName, imageUrl, key, categoryId, imageStoragedType }: ProductUpdateRequest): Promise; 18 | 19 | delete(id: string): Promise; 20 | 21 | cleanRepository(): void; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/modules/print-order/create/index.ts: -------------------------------------------------------------------------------- 1 | import { NodemailerEmailService } from '../../../providers/emails/NodemailerEmailService'; 2 | import { currentNotificationsRepository, currentPrintOrdersRepository, currentUsersRepository } from '../../../repositories'; 3 | import { NotificationsService } from '../../../services/notifications'; 4 | import { CreatePrintOrderController } from './CreatePrintOrderController'; 5 | import { CreatePrintOrderUseCases } from './CreatePrintOrderUseCases'; 6 | 7 | export function createPrintOrderFactory() { 8 | const createPrintOrderUseCases = new CreatePrintOrderUseCases( 9 | currentPrintOrdersRepository, 10 | currentUsersRepository, 11 | new NotificationsService(currentNotificationsRepository), 12 | new NodemailerEmailService(), 13 | ); 14 | const createPrintOrderController = new CreatePrintOrderController(createPrintOrderUseCases); 15 | 16 | return { useCases: createPrintOrderUseCases, controller: createPrintOrderController }; 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/product-category/listById/ListProductCategoryByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { IProductCategory } from '../../../entities/product-category/IProductCategory'; 2 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 3 | import { ProductCategoryNotFoundError } from '../../../errors/ProductCategoryNotFoundError'; 4 | import { IProductCategoriesRepository } from '../../../repositories/product-categories/IProductCategoriesRepository'; 5 | 6 | export class ListProductCategoryByIdUseCases { 7 | 8 | constructor( 9 | private productCategoriesRepository: IProductCategoriesRepository, 10 | ) { } 11 | 12 | async execute(id: string): Promise { 13 | if(!id) { 14 | throw new IDNotGivenError(); 15 | } 16 | 17 | const productCategory = await this.productCategoriesRepository.listById(id); 18 | 19 | if(!productCategory) { 20 | throw new ProductCategoryNotFoundError(); 21 | } 22 | 23 | return productCategory; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/user/listById/ListUserByIdUseCases.ts: -------------------------------------------------------------------------------- 1 | import { userViewMapper } from '../../../domain/UserViewMapper'; 2 | import { IUserPublic } from '../../../entities/user/IUserPublic'; 3 | import { IUserView } from '../../../entities/user/IUserView'; 4 | import { IDNotGivenError } from '../../../errors/IDNotGivenError'; 5 | import { UserNotFoundError } from '../../../errors/UserNotFoundError'; 6 | import { IUsersRepository } from '../../../repositories/users/IUsersRepository'; 7 | 8 | export class ListUserByIdUseCases { 9 | 10 | constructor( 11 | private usersRepository: IUsersRepository, 12 | ) { } 13 | 14 | async execute(id: string, isAdmin = false): Promise { 15 | if(!id) { 16 | throw new IDNotGivenError(); 17 | } 18 | 19 | const user = await this.usersRepository.listById(id); 20 | if(!user) { 21 | throw new UserNotFoundError(); 22 | } 23 | 24 | return isAdmin ? user : userViewMapper.toPublic(user); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/middlewares/imageDataTransform.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { BadRequestError } from '../errors/BadRequestError'; 3 | import { EnvProvider } from '../services/env-provider'; 4 | 5 | type MulterFullFile = Express.Multer.File & Express.MulterS3.File; 6 | 7 | interface RequestWithFullFile { 8 | file: MulterFullFile; 9 | } 10 | 11 | export function imageDataTransform(req: Request & RequestWithFullFile, res: Response, next: NextFunction) { 12 | 13 | if(!req.file) { 14 | throw new BadRequestError('A imagem é obrigatória'); 15 | } 16 | 17 | const { originalname: imageName, filename: keyLocal } = req.file; 18 | const { key: keyS3, location: imageUrlS3 } = req.file as unknown as { key: string, location: string }; 19 | 20 | const key = keyS3 || keyLocal; 21 | const imageUrl = imageUrlS3 || `${EnvProvider.host}/images/${key}`; 22 | 23 | req.image = { 24 | imageName, 25 | imageUrl, 26 | key, 27 | }; 28 | 29 | next(); 30 | } 31 | -------------------------------------------------------------------------------- /src/modules/auth/validate-email/ValidateEmailUseCase.ts: -------------------------------------------------------------------------------- 1 | import { RequiredFieldsError } from '../../../errors/RequiredFieldsError'; 2 | import { validatorTokenProvider } from '../../../providers/ValidatorToken'; 3 | import { IUsersRepository } from '../../../repositories/users/IUsersRepository'; 4 | 5 | export class ValidateEmailUseCase { 6 | 7 | constructor( 8 | private usersRepository: IUsersRepository, 9 | ) { } 10 | 11 | async execute(validatorToken: string): Promise { 12 | if(!validatorToken) { 13 | throw new RequiredFieldsError('Token'); 14 | } 15 | 16 | await validatorTokenProvider.verify(validatorToken); 17 | const { email } = await validatorTokenProvider.getValidatorToken({ id: validatorToken }); 18 | 19 | const { id: userId } = await this.usersRepository.listByEmail(email); 20 | await this.usersRepository.update(userId, { verified: true }, false); 21 | 22 | await validatorTokenProvider.delete({ id: validatorToken }); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/repositories/purchase-order/IPurchaseOrdersRepository.ts: -------------------------------------------------------------------------------- 1 | import { IPurchaseOrder } from '../../entities/purchase-order/IPurchaseOrder'; 2 | import { PurchaseOrderCreateRequest } from '../../entities/purchase-order/dtos/PurchaseOrderCreateRequest'; 3 | import { PurchaseOrderUpdateRequest } from '../../entities/purchase-order/dtos/PurchaseOrderUpdateRequest'; 4 | import { PurchaseOrderFilter } from '../../shared/filters/PurchaseOrderFilter'; 5 | 6 | export interface IPurchaseOrdersRepository { 7 | 8 | listAll(filter?: PurchaseOrderFilter): Promise; 9 | 10 | listByUserId(userId: string): Promise; 11 | 12 | listById(id: string): Promise; 13 | 14 | create({ number, paymentMethodId, products, userId }: PurchaseOrderCreateRequest): Promise; 15 | 16 | update(id: string, { status, paymentMethodId, freight, discount }: PurchaseOrderUpdateRequest): Promise; 17 | 18 | delete(id: string): Promise; 19 | 20 | } 21 | --------------------------------------------------------------------------------