Created
July 23, 2018 17:27
-
-
Save clayellis/cee738595532114173b6268a85b3c74c to your computer and use it in GitHub Desktop.
Verify ownership of objects in Vapor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vapor | |
import Fluent | |
/// An object that can be owned. | |
protocol Ownable { | |
/// The Owner type that owns this object. | |
associatedtype OwnerType | |
/// Type of the Owner's ID | |
associatedtype OwnerIDType | |
/// Key path to the owner ID | |
typealias OwnerIDKey = WritableKeyPath<Self, OwnerIDType> | |
/// A relation to the owner that owns this object. | |
static var ownerIDKey: OwnerIDKey { get } | |
} | |
extension Model where Self: Ownable, Self.OwnerType: Model { | |
/// See `Ownable`. | |
typealias OwnerIDType = OwnerType.ID | |
} | |
extension Ownable where Self.OwnerType: Model, Self.OwnerIDType == Self.OwnerType.ID { | |
/// Whether `self` is owned by the `owner`. | |
/// - parameter owner: The possible owner. | |
/// - returns: `true` if `self` is owned by `owner`, otherwise `false`. | |
func isOwned(by owner: OwnerType) -> Bool { | |
do { | |
return try owner.requireID() == self[keyPath: Self.ownerIDKey] | |
} catch { | |
return false | |
} | |
} | |
/// Checks that `self` is owned by `owner` and throws if not. | |
/// - parameter owner: The possible owner. | |
/// - parameter error: The error to throw if `owner` is not `self`'s owner. | |
/// Default is `Abort(.unauthorized)`. | |
/// - throws: `error` if `self` is not owned by the `owner`. | |
func requireOwner(_ owner: OwnerType, orThrow error: Error = Abort(.unauthorized)) throws { | |
guard isOwned(by: owner) else { | |
throw error | |
} | |
} | |
} | |
extension Model { | |
/// Whether `self` owns the `object`. | |
/// - parameter object: The object that `self` might own. | |
/// - returns: `true` is `self` owns `object`, otherwise `false`. | |
func owns<T: Ownable>(_ object: T) -> Bool where T.OwnerType == Self, Self.ID == T.OwnerIDType { | |
return object.isOwned(by: self) | |
} | |
/// Checks that `self` owns `object` and throws if not. | |
/// - parameter object: The object that `self` might own. | |
/// - parameter error: The error to throw if `self` does not own `object`. | |
/// Default is `Abort(.unauthorized)`. | |
/// - throws: `error` if `self` does not own `object`. | |
func requireOwnership<T: Ownable>(of object: T, orThrow error: Error = Abort(.unauthorized)) throws where T.OwnerType == Self, Self.ID == T.OwnerIDType { | |
guard self.owns(object) else { | |
throw error | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment