// // cntrlAddociate.swift // // // Created by Michiel Carman on 4/11/2024. // import Fluent import Vapor import Crypto struct cntrlAssociate: RouteCollection { func boot(routes: RoutesBuilder) throws { let rts = routes.grouped("associates") rts.get(use: index) rts.get(":x", use: read) rts.post(use: create) rts.delete(":x", use: delete) rts.post("create", use: createUser) let passwordProtected = rts.grouped(mdlAssociate.authenticator(), mdlAssociate.guardMiddleware()) passwordProtected.post("login", use: login) passwordProtected.post("tlogin", use: jwtauth) let tokenProtected = rts.grouped(mdlToken.authenticator()) tokenProtected.get("tauth", use: auth) //Additional routs added here } @Sendable func jwtauth(req: Request) async throws -> ClientTokenResponse{ let user = try req.auth.require(mdlAssociate.self) let payload = SessionToken(user: user) return ClientTokenResponse(token: try req.jwt.sign(payload)) } @Sendable func auth(req: Request) async throws -> Response{ let result = try req.auth.require(mdlAssociate.self) let assoc = mdlAssociate.Output(id: result.id, firstname: result.firstname, lastname: result.lastname) guard let response = try? await assoc.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Associate could not be shown.") } return response } @Sendable func login(req: Request) async throws -> Response{ guard let result = try? req.auth.require(mdlAssociate.self) else{ throw Abort(.unauthorized) } let token = try await result.generateToken() try await token.save(on: req.db) guard let response = try? await token.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Token could not be shown.") } return response } @Sendable func createUser(req: Request) async throws -> Response{ try mdlAssociate.CreateUser.validate(content: req) let create = try req.content.decode(mdlAssociate.CreateUser.self) guard create.password == create.confirmpassword else{ throw Abort(.badRequest, reason: "Passwords did not match") } let user = try mdlAssociate( firstname: create.firstname, lastname: create.lastname, username: create.username, password: Bcrypt.hash(create.password) ) try await user.save(on: req.db) let assoc = mdlAssociate.Output(id: user.id, firstname: user.firstname, lastname: user.lastname) guard let response = try? await assoc.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Associate could not be shown.") } return response } @Sendable func index(req: Request) async throws -> Response { let obj = try await mdlAssociate.ObjQuery(req: req).all() // guard let obj = try? await mdlAssociate.ObjQuery(req: req).all() else { // throw Abort(.badGateway, reason: "Something went wrong with this api.") // } guard let response = try? await obj.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Array could not be shown.") } return response } @Sendable func read(req:Request) async throws -> Response{ guard let obj = try? await mdlAssociate.ObjQuery(req: req).first() else{ throw Abort(.notFound, reason: "Associate was not found.") } guard let response = try? await obj.encodeResponse(status: .ok, for: req) else { throw Abort(.noContent, reason: "Something went wrong decoding object.") } return response } @Sendable func create(req: Request) async throws -> Response { guard let obj = try? req.content.decode(mdlAssociate.self) else { throw Abort(.notAcceptable, reason: "Associate json not formatted correctly or is missing parents.") } var exists = false if(obj.id != nil){ obj._$idExists = true exists = true } guard let _ = try? await obj.save(on: req.db) else{ throw Abort(.conflict, reason: "Something conflicts in the database. Associate cannot be saved.") } guard let response = try? await obj.encodeResponse(status: exists ? .accepted : .created, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Associate has been saved.") } return response } @Sendable func delete(req: Request) async throws -> Response { guard let obj = try? await mdlAssociate.ObjQuery(req: req).first() else { throw Abort(.notFound, reason: "Associate's ID was not supplied. Associate will not be deleted") } guard let _ = try? await obj.delete(on: req.db) else{ throw Abort(.conflict, reason: "There was a conflict deleting Associate. Make sure it has not children.") } guard let response = try? await obj.encodeResponse(status: .ok, for: req) else{ throw Abort(.noContent, reason: "Something went wrong decoding data. Associate has been deleted.") } return response } }