swift-개인프로젝트
swift - vapor로 DB를 활용한 로그인 구현하기 (1)
Coding_happyytw
2023. 7. 7. 23:25
우선 모델을 만든다.
import Fluent
import Vapor
final class User: Model, Validatable {
static let schema = "users"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
@Field(key: "password")
var password: String
init() { }
init(id: UUID? = nil, name: String, password: String) {
self.id = id
self.name = name
self.password = password
}
// validation이란 확인이라는 뜻이다.
static func validations(_ validations: inout Validations) {
validations.add("username", as: String.self, is: !.empty, customFailureDescription: "Useranme cannot be empty") // username은 비면 안된다.
validations.add("password", as: String.self, is: !.empty, customFailureDescription: "Password cannot be empty")
// between 6 and 10 characters
validations.add("password", as: String.self, is: .count(6...10), customFailureDescription: "비밀번호는 6자리에서 10자리 사이다")
}
}
validation이란?
https://happyytw.tistory.com/18
swift - vapor Validation이란
Vapor는 Validation API를 제공하여 클라이언트로부터 받는 request를 Content API를 사용하여 decode하기전에 확인한다. middleware하고 비슷한 느낌인거같기도.. middleware는 클라이언트로 받는 request를 중간에
happyytw.tistory.com
이후 Migration을 만든다.
import Fluent
struct CreateUsersTableMigration: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("users")
.id()
.field("username", .string, .required).unique(on: "username") // 중복을 불가능하게한다.
.field("password", .string, .required)
.create()
}
func revert(on database: Database) async throws {
try await database.schema("users").delete()
}
}
다음으로 migraion을 잊으면 안된다.
app.migraions.add(CreateUsersTableMigration.Migration())
다음으로 Controller를 만든다.
import Fluent
import Vapor
struct UserController: RouteCollection {
func boot(routes: Vapor.RoutesBuilder) throws {
let api = routes.grouped("api")
api.post("register", use: register)
}
func register(req: Request) async throws -> RegisterResponseDTO {
// validate the user // validations
try User.validate(content: req) // req에 대해 검사한다.
let user = try req.content.decode(User.self) // 검사에 문제가 없으면 decode한다.
// find if the user already exists using the username
if let _ = try await User.query(on: req.db)
.filter(\.$username == user.username) // 만약 db에 이미있는 username이라면
.first() {
throw Abort(.conflict, reason: "Username is aleeady taken.") // error발생
}
// hash the password // 비밀번호를 그냥 넣지 않고 hash로 함호화하여 저장한다.
user.password = try await req.password.async.hash(user.password)
// db에 저장하기
try await user.save(on: req.db)
// 여기까지 문제없이 실행되었다면 false를 Return하여 문제가 없음을 알려준다
return RegisterResponseDTO(error: false)
}
}
그리고 만든 controller를 configure에 추가한다.
try app.register(collection: UserController())
다음으로 이제 서버를 실행하고 해당 주소에 User 클래스의 필드 형식에 맞게 username, password를 입력하고 서버에 전송하면
id하고 해시로 암호화된 password를 확인할 수 있다.
그리고 같은 이름으로 다시 요청을 하게된다면 에러가 발생한다.