gpt4 book ai didi

swift - Vapor 3 - 如何在保存对象之前检查类似的电子邮件

转载 作者:行者123 更新时间:2023-12-04 01:38:43 25 4
gpt4 key购买 nike

我想创建一个路由让用户更新他们的数据(例如更改他们的电子邮件或用户名)。为了确保一个用户不能使用与另一个用户相同的用户名,我想检查数据库中是否已经存在具有相同用户名的用户。

我已经使用户名在迁移中是唯一的。

我有一个如下所示的用户模型:

struct User: Content, SQLiteModel, Migration {
var id: Int?
var username: String
var name: String
var email: String
var password: String

var creationDate: Date?

// Permissions
var staff: Bool = false
var superuser: Bool = false

init(username: String, name: String, email: String, password: String) {
self.username = username
self.name = name
self.email = email
self.password = password
self.creationDate = Date()
}
}

这是我要使用它的代码片段:

func create(_ req: Request) throws -> EventLoopFuture<User> {
return try req.content.decode(UserCreationRequest.self).flatMap { userRequest in

// Check if `userRequest.email` already exists
// If if does -> throw Abort(.badRequest, reason: "Email already in use")
// Else -> Go on with creation

let digest = try req.make(BCryptDigest.self)
let hashedPassword = try digest.hash(userRequest.password)
let persistedUser = User(name: userRequest.name, email: userRequest.email, password: hashedPassword)

return persistedUser.save(on: req)
}
}

我可以这样做(见下一个片段)但这似乎是一个奇怪的选择,因为当更多检查例如必须执行唯一性(例如在更新用户的情况下)。

func create(_ req: Request) throws -> EventLoopFuture<User> {
return try req.content.decode(UserCreationRequest.self).flatMap { userRequest in
let userID = userRequest.email
return User.query(on: req).filter(\.userID == userID).first().flatMap { existingUser in
guard existingUser == nil else {
throw Abort(.badRequest, reason: "A user with this email already exists")
}

let digest = try req.make(BCryptDigest.self)
let hashedPassword = try digest.hash(userRequest.password)
let persistedUser = User(name: userRequest.name, email: userRequest.email, password: hashedPassword)

return persistedUser.save(on: req)
}
}
}

正如其中一个答案所建议的那样,我尝试添加错误中间件(请参阅下一个片段),但这并没有正确捕获错误(也许我在代码中做错了什么 - 刚开始使用 Vapor)。

import Vapor
import FluentSQLite

enum InternalError: Error {
case emailDuplicate
}

struct EmailDuplicateErrorMiddleware: Middleware {
func respond(to request: Request, chainingTo next: Responder) throws -> EventLoopFuture<Response> {
let response: Future<Response>

do {
response = try next.respond(to: request)
} catch is SQLiteError {
response = request.eventLoop.newFailedFuture(error: InternalError.emailDuplicate)
}

return response.catchFlatMap { error in
if let response = error as? ResponseEncodable {
do {
return try response.encode(for: request)
} catch {
return request.eventLoop.newFailedFuture(error: InternalError.emailDuplicate)
}
} else {
return request.eventLoop.newFailedFuture(error: error)
}
}
}
}

最佳答案

快速的方法是执行类似 User.query(on: req).filter(\.email == email).count() 的操作,并在尝试之前检查是否等于 0保存。

然而,虽然这对几乎每个人都适用,但您仍然会冒着边缘情况的风险,即两个用户同时尝试使用相同的用户名注册 - 处理此问题的唯一方法是捕获保存失败,检查是否这是因为电子邮件的唯一约束并将错误返回给用户。然而,即使对于大型应用程序,您真正达到目标的机会也非常少。

关于swift - Vapor 3 - 如何在保存对象之前检查类似的电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58466181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com