import Fluent import Foundation import Vapor func routes(_ app: Application) throws { app.get { req in let output = try await req.view.render("login") return output } app.get("loggedIn") { req -> View in guard let user = try await req.currentUser(withProsAndCons: true) else { throw Abort(.badRequest) } return try await req.view.render( "loggedIn", LoggedInContext(name: user.displayName, prosAndCons: user.prosAndCons) ) } app.get("submitProOrCon") { req in let params = try req.query.decode(SubmitProOrCon.self) guard let userId = req.userId else { throw Abort(.unauthorized) } try checkForBadWords(in: params.description) let proOrCon = ProCon(type: params.type, description: params.description, userId: userId) try await proOrCon.save(on: req.db) return req.redirect(to: "loggedIn") } app.get("login") { req in let params = try req.query.decode(LoginParams.self) req.logger.info("params: \(params)") try checkForBadWords(in: params.displayName) let user = User(displayName: params.displayName) try await user.save(on: req.db) req.session.data["userId"] = user.id?.uuidString return req.redirect(to: "loggedIn") } } private extension Request { var userId: UUID? { guard let userIdString = session.data["userId"], let userId = UUID(uuidString: userIdString) else { return nil } return userId } func currentUser(withProsAndCons: Bool) async throws -> User? { guard let userId = userId else { return nil } var query = User.query(on: db).filter(\.$id == userId) if withProsAndCons { query = query.with(\.$prosAndCons) } return try await query.first() } } struct DisplayNameError: Error {} struct LoginParams: Content { let displayName: String } struct SubmitProOrCon: Content { let type: ProCon.ProConType let description: String } struct LoggedInContext: Encodable { let name: String let pros: [ProCon] let cons: [ProCon] init(name: String, prosAndCons: [ProCon]) { self.name = name self.cons = prosAndCons.filter { $0.type == .con } self.pros = prosAndCons.filter { $0.type == .pro } } }