diff --git a/Sources/App/Controllers/Favorites/FavoritesController.swift b/Sources/App/Controllers/Favorites/FavoritesController.swift index afb103d..3c0f37a 100644 --- a/Sources/App/Controllers/Favorites/FavoritesController.swift +++ b/Sources/App/Controllers/Favorites/FavoritesController.swift @@ -38,7 +38,9 @@ struct FavoritesController: RouteCollection { guard let user = request.auth.get(User.self) else { throw ErrorFactory.unauthorized() } let productsIDs = try request.content.decode([UUID].self) - try await favoritesRepository.update(productsIDs: productsIDs, for: user) + if let error = try await favoritesRepository.update(productsIDs: productsIDs, for: user) { + throw error + } return DummyResponse() } diff --git a/Sources/App/Controllers/Favorites/FavoritesRepository.swift b/Sources/App/Controllers/Favorites/FavoritesRepository.swift index 0391250..b0d17a1 100644 --- a/Sources/App/Controllers/Favorites/FavoritesRepository.swift +++ b/Sources/App/Controllers/Favorites/FavoritesRepository.swift @@ -14,7 +14,7 @@ protocol FavoritesRepositoryProtocol: Sendable { func get(for user: User, with page: PageRequest) async throws -> PaginationResponse func get(for user: User) async throws -> [UUID]? func getCount(for user: User) async throws -> FavoritesCountDTO - func update(productsIDs: [Product.IDValue], for user: User) async throws + func update(productsIDs: [Product.IDValue], for user: User) async throws -> CustomError? func delete(productsIDs: [Product.IDValue], for user: User) async throws } @@ -47,21 +47,23 @@ final class FavoritesRepository: FavoritesRepositoryProtocol { DTOFactory.makeFavoritesCount(from: try await buildQuery(for: user.requireID()).aggregate(.count, \.$id)) } - func update(productsIDs: [Product.IDValue], for user: User) async throws { + func update(productsIDs: [Product.IDValue], for user: User) async throws -> CustomError? { try await database.transaction { transaction in let products = try await Product.query(on: transaction) .filter(\.$id ~~ productsIDs.reversed()) .all() let favorites = try await user.$favorites.get(on: transaction) - + var productAlreadyStarred = false try await products.asyncForEach { product in if try await favorites?.$products.isAttached(to: product, on: transaction) == true { - throw ErrorFactory.badRequest(.productAlreadyStarred) + productAlreadyStarred = true } else { try await favorites?.$products.attach(product, on: transaction) } } + + return productAlreadyStarred ? ErrorFactory.successWarning(.productAlreadyStarred) : nil } } diff --git a/Sources/App/Helpers/ErrorFactory/ErrorFactory+BadRequest.swift b/Sources/App/Helpers/ErrorFactory/ErrorFactory+BadRequest.swift index 9207ea5..7fcaa90 100644 --- a/Sources/App/Helpers/ErrorFactory/ErrorFactory+BadRequest.swift +++ b/Sources/App/Helpers/ErrorFactory/ErrorFactory+BadRequest.swift @@ -13,7 +13,6 @@ enum BadRequest: String { case oneProductUnavailable = "oneProductUnavailable" case categoryIDRequired = "categoryIDRequired" case categoryIDOrProductsIDsRequired = "categoryIDOrProductsIDsRequired" - case productAlreadyStarred = "productAlreadyStarred" case xCityIdParameterRequired = "xCityIdParameterRequired" case orderNumberRequired = "orderNumberRequired" case orderIdRequired = "orderIdRequired" @@ -57,9 +56,6 @@ extension BadRequest { case .categoryIDOrProductsIDsRequired: return "Category ID or products IDs is required." - case .productAlreadyStarred: - return "Attempting to add a product to favorites that has already been added." - case .xCityIdParameterRequired: return "X-City-Id parameter is required." diff --git a/Sources/App/Helpers/ErrorFactory/ErrorFactory+SuccessWarning.swift b/Sources/App/Helpers/ErrorFactory/ErrorFactory+SuccessWarning.swift new file mode 100644 index 0000000..38758a1 --- /dev/null +++ b/Sources/App/Helpers/ErrorFactory/ErrorFactory+SuccessWarning.swift @@ -0,0 +1,22 @@ +// +// ErrorFactory+SuccessWarning.swift +// MEOWLSServer +// +// Created by Artem Mayer on 29.10.2024. +// + +import Foundation + +enum SuccessWarning: String { + + case productAlreadyStarred = "productAlreadyStarred" + + var description: String { + switch self { + case .productAlreadyStarred: + return "Attempting to add a product to favorites that has already been added." + + } + } + +} diff --git a/Sources/App/Helpers/ErrorFactory/ErrorFactory.swift b/Sources/App/Helpers/ErrorFactory/ErrorFactory.swift index 1050003..149b299 100644 --- a/Sources/App/Helpers/ErrorFactory/ErrorFactory.swift +++ b/Sources/App/Helpers/ErrorFactory/ErrorFactory.swift @@ -20,6 +20,10 @@ struct ErrorFactory { CustomError(.unauthorized, reason: "Access is denied. Please authenticate and try again.") } + static func successWarning(_ type: SuccessWarning) -> CustomError { + CustomError(.alreadyReported, code: type.rawValue, reason: type.description) + } + static func internalError(_ type: InternalServerError, failures: [ValidationFailureType]? = nil) -> CustomError { CustomError(.internalServerError, code: type.rawValue, reason: type.description, failures: failures?.toFailures) } diff --git a/Sources/App/Vapor/ExtendedError/CustomErrorMiddleware.swift b/Sources/App/Vapor/ExtendedError/CustomErrorMiddleware.swift index 20f155c..d694f0d 100644 --- a/Sources/App/Vapor/ExtendedError/CustomErrorMiddleware.swift +++ b/Sources/App/Vapor/ExtendedError/CustomErrorMiddleware.swift @@ -113,7 +113,7 @@ final class CustomErrorMiddleware: Middleware { let code: String let reason: String - if error.status == .unauthorized, url.path.pathComponents.last == "login" { + if url.path.pathComponents.contains("login") { code = "authError" reason = "Invalid phone or password"