From f202dff47890bc6e93de557674992d94c23b61d3 Mon Sep 17 00:00:00 2001 From: rpm-mcarman <65228808+rpm-mcarman@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:00:45 -0400 Subject: [PATCH] Pushing edits --- .../UserInterfaceState.xcuserstate | Bin 47911 -> 125302 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 ++ .../Controllers/FuelEntryV2Controller.swift | 85 ++++++++++++++++++ Sources/App/Controllers/UserController.swift | 76 +++++++++++++++- Sources/App/Errors/UserErrors.swift | 23 +++++ Sources/App/Migrations/CreateFuelEntry.swift | 14 +++ Sources/App/Migrations/CreateToken.swift | 23 +++++ Sources/App/Migrations/CreateUser.swift | 19 ++++ Sources/App/Models/FuelEntry.swift | 76 +++++++++++++++- Sources/App/Models/Token.swift | 54 ++++++++++- Sources/App/Models/User.swift | 66 ++++++++++++-- Sources/App/configure.swift | 4 + Sources/App/routes.swift | 51 ++++++----- 13 files changed, 468 insertions(+), 29 deletions(-) create mode 100644 .swiftpm/xcode/xcuserdata/michielcarman.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/michielcarman.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/michielcarman.xcuserdatad/UserInterfaceState.xcuserstate index 406ac5fe40a81c66330e672815b249d31963f722..27743b9a94121b55dd08e2006043bf143b3faf53 100644 GIT binary patch literal 125302 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 V|B3nD|NDRcjP(EiPpC`x{{xJlwcP*! literal 47911 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 + + diff --git a/Sources/App/Controllers/FuelEntryV2Controller.swift b/Sources/App/Controllers/FuelEntryV2Controller.swift index 7dbaaa7..6802b6f 100644 --- a/Sources/App/Controllers/FuelEntryV2Controller.swift +++ b/Sources/App/Controllers/FuelEntryV2Controller.swift @@ -12,6 +12,7 @@ struct FuelEntryV2Controller: RouteCollection { func boot(routes: RoutesBuilder) throws { let fuelEntries = routes.grouped("fuel_entries") fuelEntries.get(use: index) + fuelEntries.get("test", use: filtered) // fuelEntries.get("with-images", use: getAllEntriesWithImages) fuelEntries.post(use: create) // fuelEntries.post("upload-image", use: uploadImage) @@ -24,6 +25,90 @@ struct FuelEntryV2Controller: RouteCollection { return try await FuelEntry.query(on: req.db).all() } + struct filteredreturn: Content{ + var fuelentries: [FuelEntry] + var pages: Int + } + + @Sendable + func filtered(req: Request) async throws -> Response { + + var image: Bool + var serial: String + var tank: String + let qstring = req.query + if let qimage = try? qstring.get(Bool.self, at: "image"){ + image = qimage + } else { + image = false + } + if let qserial = try? qstring.get(String.self, at: "serial"){ + serial = qserial + } else { + serial = "" + } + if let qtank = try? qstring.get(String.self, at: "tank"){ + tank = qtank + } else { + tank = "" + } + + var query = FuelEntry.query(on: req.db) + if(image){ + query = query + .field(\.$id) + .field(\.$timestamp) + .field(\.$userID) + .field(\.$product) + .field(\.$make) + .field(\.$model) + .field(\.$serialNumber) + .field(\.$tankID) + .field(\.$fuelAmount) + .field(\.$fuelType) + .field(\.$isOverride) + .field(\.$latitude) + .field(\.$longitude) + .field(\.$image) + } else { + query = query + .field(\.$id) + .field(\.$timestamp) + .field(\.$userID) + .field(\.$product) + .field(\.$make) + .field(\.$model) + .field(\.$serialNumber) + .field(\.$tankID) + .field(\.$fuelAmount) + .field(\.$fuelType) + .field(\.$isOverride) + .field(\.$latitude) + .field(\.$longitude) + } + if(serial.count > 0){ + query = query + .filter(\.$serialNumber == serial) + } + if(tank.count > 0){ + query = query + .filter(\.$tankID == tank) + } + if(image){ + let wimage = try await query.paginate(for: req).map{ + img in FuelEntry.wimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride, image: img.image!) + } + return try await wimage.encodeResponse(for: req) + } else { + let woimage = try await query.paginate(for: req).map{ + img in FuelEntry.woimage(id: img.id, timestamp: img.timestamp, userID: img.userID, latitude: img.latitude, longitutde: img.longitude, product: img.product, make: img.make, model: img.model, serialNumber: img.serialNumber, tankID: img.tankID, fuelAmount: img.fuelAmount, fuelType: img.fuelType, isOverride: img.isOverride) + } + return try await woimage.encodeResponse(for: req) + } +// let result = try await query.paginate(for: req) +// return try await result.encodeResponse(for: req) + } + // func getAllEntriesWithImages(req: Request) async throws -> [FuelEntry] { // let fuelEntries = try await FuelEntry.query(on: req.db).all() // diff --git a/Sources/App/Controllers/UserController.swift b/Sources/App/Controllers/UserController.swift index cc4702c..1ede7b2 100644 --- a/Sources/App/Controllers/UserController.swift +++ b/Sources/App/Controllers/UserController.swift @@ -5,4 +5,78 @@ // Created by Michiel Carman on 9/26/24. // -import Foundation +import Vapor +import Fluent + +struct UserSignup: Content { + let username: String + let password: String +} + +struct NewSession: Content { + let token: String + let user: User.Public +} + +extension UserSignup: Validatable { + static func validations(_ validations: inout Validations) { + validations.add("username", as: String.self, is: !.empty) + validations.add("password", as: String.self, is: .count(6...)) + } +} + +struct UserController: RouteCollection { + func boot(routes: RoutesBuilder) throws { + let usersRoute = routes.grouped("users") + usersRoute.post("signup", use: create) + + let tokenProtected = usersRoute.grouped(Token.authenticator()) + tokenProtected.get("me", use: getMyOwnUser) + + let passwordProtected = usersRoute.grouped(User.authenticator()) + passwordProtected.post("login", use: login) + } + + fileprivate func create(req: Request) throws -> EventLoopFuture { + try UserSignup.validate(content: req) + let userSignup = try req.content.decode(UserSignup.self) + let user = try User.create(from: userSignup) + var token: Token! + + return checkIfUserExists(userSignup.username, req: req).flatMap { exists in + guard !exists else { + return req.eventLoop.future(error: UserError.usernameTaken) + } + + return user.save(on: req.db) + }.flatMap { + guard let newToken = try? user.createToken(source: .signup) else { + return req.eventLoop.future(error: Abort(.internalServerError)) + } + token = newToken + return token.save(on: req.db) + }.flatMapThrowing { + NewSession(token: token.value, user: try user.asPublic()) + } + } + + fileprivate func login(req: Request) throws -> EventLoopFuture { + let user = try req.auth.require(User.self) + let token = try user.createToken(source: .login) + + return token.save(on: req.db).flatMapThrowing { + NewSession(token: token.value, user: try user.asPublic()) + } + } + + func getMyOwnUser(req: Request) throws -> User.Public { + try req.auth.require(User.self).asPublic() + } + + private func checkIfUserExists(_ username: String, req: Request) -> EventLoopFuture { + User.query(on: req.db) + .filter(\.$username == username) + .first() + .map { $0 != nil } + } +} diff --git a/Sources/App/Errors/UserErrors.swift b/Sources/App/Errors/UserErrors.swift index cc4702c..a3e4ee4 100644 --- a/Sources/App/Errors/UserErrors.swift +++ b/Sources/App/Errors/UserErrors.swift @@ -6,3 +6,26 @@ // import Foundation +import Vapor + +enum UserError { + case usernameTaken +} + +extension UserError: AbortError { + var description: String { + reason + } + + var status: HTTPResponseStatus { + switch self { + case .usernameTaken: return .conflict + } + } + + var reason: String { + switch self { + case .usernameTaken: return "Username already taken" + } + } +} diff --git a/Sources/App/Migrations/CreateFuelEntry.swift b/Sources/App/Migrations/CreateFuelEntry.swift index ad0151d..197121d 100755 --- a/Sources/App/Migrations/CreateFuelEntry.swift +++ b/Sources/App/Migrations/CreateFuelEntry.swift @@ -82,3 +82,17 @@ struct StoreImageDataInDatabase: AsyncMigration { } } +struct AddDownloadedBool: AsyncMigration { + func prepare(on database: Database) async throws { + try await database.schema("fuel_entries") + .field("downloaded", .bool) + .update() + } + + func revert(on database: Database) async throws { + try await database.schema("fuel_entries") + .deleteField("downloaded") + .update() + } +} + diff --git a/Sources/App/Migrations/CreateToken.swift b/Sources/App/Migrations/CreateToken.swift index cc4702c..3f7228f 100644 --- a/Sources/App/Migrations/CreateToken.swift +++ b/Sources/App/Migrations/CreateToken.swift @@ -6,3 +6,26 @@ // import Foundation +import Vapor +import Fluent + +struct CreateTokens: Migration { + func prepare(on database: Database) -> EventLoopFuture { + // 2 + database.schema(Token.schema) + // 3 + .id() + .field("user_id", .uuid, .references("user", "id")) + .field("value", .string, .required) + .unique(on: "value") + .field("source", .int, .required) + .field("created_at", .datetime, .required) + .field("expires_at", .datetime) + .create() + } + + // 5 + func revert(on database: Database) -> EventLoopFuture { + database.schema(Token.schema).delete() + } +} diff --git a/Sources/App/Migrations/CreateUser.swift b/Sources/App/Migrations/CreateUser.swift index cc4702c..bd3990b 100644 --- a/Sources/App/Migrations/CreateUser.swift +++ b/Sources/App/Migrations/CreateUser.swift @@ -6,3 +6,22 @@ // import Foundation +import Vapor +import Fluent + +struct CreateUser: AsyncMigration { + func prepare(on database: Database) async throws { + try await database.schema(User.schema) + .id() + .field("username", .string, .required) + .unique(on: "username") + .field("password_hash", .string, .required) + .field("created_at", .datetime, .required) + .field("updated_at", .datetime, .required) + .create() + } + + func revert(on database: Database) async throws { + try await database.schema(User.schema).delete() + } +} diff --git a/Sources/App/Models/FuelEntry.swift b/Sources/App/Models/FuelEntry.swift index 9d60f10..2a8df86 100755 --- a/Sources/App/Models/FuelEntry.swift +++ b/Sources/App/Models/FuelEntry.swift @@ -10,6 +10,39 @@ import Vapor final class FuelEntry: Model, Content { static let schema = "fuel_entries" + + struct woimage: Content{ + let id: UUID? + let timestamp: Date + let userID: String + let latitude: Double + let longitutde: Double + let product: String + let make: String + let model: String + let serialNumber: String + let tankID: String + let fuelAmount: Double + let fuelType: String + let isOverride: Bool + } + + struct wimage: Content{ + let id: UUID? + let timestamp: Date + let userID: String + let latitude: Double + let longitutde: Double + let product: String + let make: String + let model: String + let serialNumber: String + let tankID: String + let fuelAmount: Double + let fuelType: String + let isOverride: Bool + let image: Data? + } @ID(key: .id) var id: UUID? @@ -53,17 +86,58 @@ final class FuelEntry: Model, Content { @Field(key: "is_override") var isOverride: Bool + @Field(key: "downloaded") + var downloaded: Bool? + // var imageData: Data? init() {} + init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool, downloaded: Bool?) { //imageData: Data? + self.id = id + self.timestamp = timestamp + self.userID = userID + self.latitude = latitude + self.longitude = longitude + self.image = image ?? nil + self.product = product + self.make = make + self.model = model + self.serialNumber = serialNumber + self.tankID = tankID + self.fuelAmount = fuelAmount + self.fuelType = fuelType + self.isOverride = isOverride + self.downloaded = downloaded ?? nil + self.image = image ?? nil +// self.imageData = imageData + } init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, image: Data?, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool) { //imageData: Data? self.id = id self.timestamp = timestamp self.userID = userID self.latitude = latitude self.longitude = longitude - self.image = image + self.image = image ?? nil + self.product = product + self.make = make + self.model = model + self.serialNumber = serialNumber + self.tankID = tankID + self.fuelAmount = fuelAmount + self.fuelType = fuelType + self.isOverride = isOverride + self.downloaded = downloaded ?? nil + self.image = image ?? nil +// self.imageData = imageData + } + init(id: UUID? = nil, timestamp: Date, userID: String, latitude: Double, longitude: Double, product: String, make: String, model: String, serialNumber: String, tankID: String, fuelAmount: Double, fuelType: String, isOverride: Bool) { //imageData: Data? + self.id = id + self.timestamp = timestamp + self.userID = userID + self.latitude = latitude + self.longitude = longitude + self.image = image ?? nil self.product = product self.make = make self.model = model diff --git a/Sources/App/Models/Token.swift b/Sources/App/Models/Token.swift index b2a1ea5..8b7e109 100644 --- a/Sources/App/Models/Token.swift +++ b/Sources/App/Models/Token.swift @@ -5,4 +5,56 @@ // Created by Michiel Carman on 9/24/24. // -import Foundation +import Vapor +import Fluent + +enum SessionSource: Int, Content { + case signup + case login +} + +final class Token: Model { + static let schema = "token" + + @ID() + var id: UUID? + + @Parent(key: "user_id") + var user: User + + @Field(key: "value") + var value: String + + @Field(key: "source") + var source: SessionSource + + @Field(key: "expires_at") + var expiresAt: Date? + + @Timestamp(key: "created_at", on: .create) + var createdAt: Date? + + init() {} + + init(id: UUID? = nil, userId: User.IDValue, token: String, + source: SessionSource, expiresAt: Date?) { + self.id = id + self.$user.id = userId + self.value = token + self.source = source + self.expiresAt = expiresAt + } +} + +extension Token: ModelTokenAuthenticatable { + static let valueKey = \Token.$value + static let userKey = \Token.$user + + var isValid: Bool { + guard let expiryDate = expiresAt else { + return true + } + + return expiryDate > Date() + } +} diff --git a/Sources/App/Models/User.swift b/Sources/App/Models/User.swift index caa91d5..be1cbf2 100644 --- a/Sources/App/Models/User.swift +++ b/Sources/App/Models/User.swift @@ -5,12 +5,68 @@ // Created by Michiel Carman on 9/24/24. // -import Foundation -import Vapor import Fluent +import Vapor final class User: Model { - @ID var id: UUID? - - @Field(key: "name") var name: String + struct Public: Content { + let username: String + let id: UUID + let createdAt: Date? + let updatedAt: Date? + } + + static let schema = "user" + + @ID() + var id: UUID? + + @Field(key: "username") + var username: String + + @Field(key: "password_hash") + var passwordHash: String + + @Timestamp(key: "created_at", on: .create) + var createdAt: Date? + + @Timestamp(key: "updated_at", on: .update) + var updatedAt: Date? + + init() {} + + init(id: UUID? = nil, username: String, passwordHash: String) { + self.id = id + self.username = username + self.passwordHash = passwordHash + } +} + +extension User { + static func create(from userSignup: UserSignup) throws -> User { + User(username: userSignup.username, passwordHash: try Bcrypt.hash(userSignup.password)) + } + + func createToken(source: SessionSource) throws -> Token { + let calendar = Calendar(identifier: .gregorian) + let expiryDate = calendar.date(byAdding: .year, value: 1, to: Date()) + return try Token(userId: requireID(), + token: [UInt8].random(count: 16).base64, source: source, expiresAt: expiryDate) + } + + func asPublic() throws -> Public { + Public(username: username, + id: try requireID(), + createdAt: createdAt, + updatedAt: updatedAt) + } +} + +extension User: ModelAuthenticatable { + static let usernameKey = \User.$username + static let passwordHashKey = \User.$passwordHash + + func verify(password: String) throws -> Bool { + try Bcrypt.verify(password, created: self.passwordHash) + } } diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index 06fe51f..177900a 100755 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -4,6 +4,7 @@ import Vapor // configures your application public func configure(_ app: Application) async throws { + app.middleware.use(ErrorMiddleware.default(environment: app.environment)) // uncomment to serve files from /Public folder // app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory)) app.routes.defaultMaxBodySize = "128mb" @@ -15,6 +16,9 @@ public func configure(_ app: Application) async throws { app.migrations.add(AddLatitudeAndLongitudeAndRemoveGpsLocationAndImage()) app.migrations.add(AddImageBackIn()) app.migrations.add(StoreImageDataInDatabase()) + app.migrations.add(AddDownloadedBool()) + app.migrations.add(CreateUser()) + app.migrations.add(CreateTokens()) try await app.autoMigrate().get() // register routes diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index cd36958..787b8cc 100755 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -1,6 +1,12 @@ import Vapor func routes(_ app: Application) throws { + + app.routes.caseInsensitive = true + app.routes.defaultMaxBodySize = "64mb"; + let v2 = app.grouped("api").grouped("v2") + try v2.register(collection: FuelEntryV2Controller()) + try v2.register(collection: UserController()) let fuelEntryController = FuelEntryController() app.get("fuel-entries") { req in @@ -15,30 +21,33 @@ func routes(_ app: Application) throws { try await fuelEntryController.delete(req: req) } + + + // V2 API routes with image upload - let v2Routes = app.group("api", "v2") { v2 in - let fuelEntryV2Controller = FuelEntryV2Controller() - - v2.get("fuel-entries") {req in - try await fuelEntryV2Controller.index(req: req) - } - -// v2.get("fuel-entries", "with-images") {req in -// try await fuelEntryV2Controller.getAllEntriesWithImages(req: req) +// let v2Routes: () = app.group("api", "v2") { v2 in +// let fuelEntryV2Controller = FuelEntryV2Controller() +// +// v2.get("fuel-entries") {req in +// try await fuelEntryV2Controller.index(req: req) // } - - v2.post("fuel-entries") {req in - try await fuelEntryV2Controller.create(req: req) - } - -// v2.post("fuel-entries", ":id", "upload-image") { req -> FuelEntry in -// return try await fuelEntryV2Controller.uploadImage(req: req) +// +//// v2.get("fuel-entries", "with-images") {req in +//// try await fuelEntryV2Controller.getAllEntriesWithImages(req: req) +//// } +// +// v2.post("fuel-entries") {req in +// try await fuelEntryV2Controller.create(req: req) // } - - v2.delete("fuel-entries", ":fuelEntryID") { req in - try await fuelEntryV2Controller.delete(req: req) - } - } +// +//// v2.post("fuel-entries", ":id", "upload-image") { req -> FuelEntry in +//// return try await fuelEntryV2Controller.uploadImage(req: req) +//// } +// +// v2.delete("fuel-entries", ":fuelEntryID") { req in +// try await fuelEntryV2Controller.delete(req: req) +// } +// } }