diff --git a/Sources/App/Controllers/AdminController.swift b/Sources/App/Controllers/AdminController.swift index 1e4475d..f41b50a 100644 --- a/Sources/App/Controllers/AdminController.swift +++ b/Sources/App/Controllers/AdminController.swift @@ -83,6 +83,9 @@ final class AdminController: RouteCollection { user.confirmed = body.confirmed ?? user.confirmed user.permissionLevel = body.permissionLevel ?? user.permissionLevel + // Verify the updated property values of the user. + try user.validate() + // Save the updated user to the database and convert it to a `UserResponse`. return user.update(on: request) }.response(on: request, forProfile: true) diff --git a/Sources/App/Controllers/AuthController.swift b/Sources/App/Controllers/AuthController.swift index 0f34e1f..00ec95f 100644 --- a/Sources/App/Controllers/AuthController.swift +++ b/Sources/App/Controllers/AuthController.swift @@ -39,7 +39,7 @@ final class AuthController: RouteCollection { try user.validate() // Make sure no user exists yet with the email pssed in. - let count = try User.query(on: request).filter(\.email == user.email).count() + let count = User.query(on: request).filter(\.email == user.email).count() return count.map(to: User.self) { count in guard count < 1 else { throw Abort(.badRequest, reason: "This email is already registered.") } return user @@ -99,7 +99,7 @@ final class AuthController: RouteCollection { let email = try request.content.syncGet(String.self, at: "email") // Verify a user exists with the given email. - let user = try User.query(on: request).filter(\.email == email).first().unwrap(or: Abort(.badRequest, reason: "No user found with email '\(email)'.")) + let user = User.query(on: request).filter(\.email == email).first().unwrap(or: Abort(.badRequest, reason: "No user found with email '\(email)'.")) return user.flatMap(to: (User, String).self) { user in // Verifiy that the user has confimed their account. @@ -144,7 +144,7 @@ final class AuthController: RouteCollection { // Get the user with the ID that was just fetched. let userID = refreshJWT.payload.id - let user = try User.find(userID, on: request).unwrap(or: Abort(.badRequest, reason: "No user found with ID '\(userID)'.")) + let user = User.find(userID, on: request).unwrap(or: Abort(.badRequest, reason: "No user found with ID '\(userID)'.")) return user.flatMap(to: (JSON, Payload).self) { user in @@ -167,7 +167,7 @@ final class AuthController: RouteCollection { // Get the user from the database with the email code from the request. let code = try request.query.get(String.self, at: "code") - let user = try User.query(on: request).filter(\.emailCode == code).first().unwrap(or: Abort(.badRequest, reason: "No user found with the given code.")) + let user = User.query(on: request).filter(\.emailCode == code).first().unwrap(or: Abort(.badRequest, reason: "No user found with the given code.")) return user.flatMap(to: User.self) { user in guard !user.confirmed else { throw Abort(.badRequest, reason: "User already activated.") } diff --git a/Sources/App/Controllers/UserController.swift b/Sources/App/Controllers/UserController.swift index d569ec2..c0c0201 100644 --- a/Sources/App/Controllers/UserController.swift +++ b/Sources/App/Controllers/UserController.swift @@ -28,10 +28,6 @@ final class UserController: RouteCollection { router.delete("user", use: delete) } - func allData(_ request: Request)throws -> ResponseEncodable { - fatalError() - } - /// Gets the profile data for the authenticated user. /// The requeat passed in should be sent through the /// @@ -71,7 +67,7 @@ final class UserController: RouteCollection { // Get the attribute with the matching key. // If one exists, update its `text` property, // otherwise create a new one. - return try Attribute.query(on: request).filter(\.key == content.attributeKey).first().flatMap(to: Attribute.self) { attribute in + return Attribute.query(on: request).filter(\.key == content.attributeKey).first().flatMap(to: Attribute.self) { attribute in if let attribute = attribute { attribute.text = content.attributeText return attribute.save(on: request) diff --git a/Sources/App/Models/Attribute/Attribute.swift b/Sources/App/Models/Attribute/Attribute.swift index 227cd04..6b4e15e 100644 --- a/Sources/App/Models/Attribute/Attribute.swift +++ b/Sources/App/Models/Attribute/Attribute.swift @@ -34,7 +34,7 @@ extension Attribute { static func prepare(on connection: MySQLDatabase.Connection) -> Future { return Database.create(self, on: connection) { builder in try addProperties(to: builder) - try builder.addReference(from: \.userID, to: \User.id) + builder.reference(from: \.userID, to: \User.id) } } } diff --git a/Sources/App/Models/User/User+Attributes.swift b/Sources/App/Models/User/User+Attributes.swift index 2041963..157e079 100644 --- a/Sources/App/Models/User/User+Attributes.swift +++ b/Sources/App/Models/User/User+Attributes.swift @@ -2,9 +2,9 @@ import Fluent extension User { /// Create a query that gets all the attributes belonging to a user. - func attributes(on connection: DatabaseConnectable)throws -> QueryBuilder { + func attributes(on connection: DatabaseConnectable)throws -> QueryBuilder { // Return an `Attribute` query that filters on the `userId` field. - return try Attribute.query(on: connection).filter(\.userID == self.id) + return try Attribute.query(on: connection).filter(\.userID == self.requireID()) } /// Creates a dictionary where the key is the attribute's key and the value is the attribute's text. diff --git a/Sources/App/Models/User/User.swift b/Sources/App/Models/User/User.swift index dbb460d..1d3a962 100644 --- a/Sources/App/Models/User/User.swift +++ b/Sources/App/Models/User/User.swift @@ -93,15 +93,11 @@ final class User: Content, MySQLModel, Migration, Parameter { self.permissionLevel = try container.decodeIfPresent(UserStatus.self, forKey: .permissionLevel) ?? .standard self.deletedAt = try container.decodeIfPresent(Date.self, forKey: .deletedAt) } -} - -/// Conforms the `User` model to the `SoftDeletable` protocol. -/// Allows a `users` row to be temporarily deleted from the database -/// with the possibility to restore. -extension User: SoftDeletable { /// Allows Fluent to set the `deletedAt` property to the value stored in the database. - static var deletedAtKey: WritableKeyPath { + /// Allows a `users` row to be temporarily deleted from the database + /// with the possibility to restore. + static var deletedAtKey: WritableKeyPath? { return \.deletedAt } } diff --git a/Sources/App/Models/UserStatus/UserStatus.swift b/Sources/App/Models/UserStatus/UserStatus.swift index f761571..ea3c1b7 100644 --- a/Sources/App/Models/UserStatus/UserStatus.swift +++ b/Sources/App/Models/UserStatus/UserStatus.swift @@ -77,6 +77,10 @@ struct UserStatus: RawRepresentable, Codable, Hashable, MySQLEnumType { var container = encoder.singleValueContainer() try container.encode(id) } + + static func reflectDecoded() throws -> (UserStatus, UserStatus) { + return (.admin, .standard) + } } extension UserStatus: ExpressibleByIntegerLiteral {