feat: working on detail views.

This commit is contained in:
2025-01-12 17:42:06 -05:00
parent 0e31d2c30c
commit 1ce369e156
27 changed files with 527 additions and 137 deletions

View File

@@ -1,8 +0,0 @@
import Vapor
extension Request {
func ensureValidContent<T>(_ decoding: T.Type) throws -> T where T: Content, T: Validatable {
try T.validate(content: self)
return try content.decode(T.self)
}
}

View File

@@ -0,0 +1,22 @@
import Vapor
extension Request {
func ensureValidContent<T>(_ decoding: T.Type) throws -> T where T: Content, T: Validatable {
try T.validate(content: self)
return try content.decode(T.self)
}
func ensureIDPathComponent<T: LosslessStringConvertible>(
as decoding: T.Type = UUID.self,
key: String = "id"
) throws -> T {
guard let id = parameters.get(key, as: T.self) else {
throw Abort(.badRequest, reason: "Id not supplied.")
}
return id
}
var isHtmxRequest: Bool {
headers.contains(name: "hx-request")
}
}

View File

@@ -5,12 +5,16 @@ extension RoutesBuilder {
// Used to ensure views are protected, redirects users to the login page if they're
// not authenticated.
var protected: any RoutesBuilder {
grouped(
User.credentialsAuthenticator(),
User.redirectMiddleware { req in
"login?next=\(req.url)"
}
)
#if DEBUG
return self
#else
return grouped(
User.credentialsAuthenticator(),
User.redirectMiddleware { req in
"login?next=\(req.url)"
}
)
#endif
}
func apiUnprotected(route: PathComponent) -> any RoutesBuilder {
@@ -20,11 +24,15 @@ extension RoutesBuilder {
// Allows basic or token authentication for api routes and prefixes the
// given route with "/api/v1".
func apiProtected(route: PathComponent) -> any RoutesBuilder {
let prefixed = grouped("api", "v1", route)
return prefixed.grouped(
User.authenticator(),
UserToken.authenticator(),
User.guardMiddleware()
)
#if DEBUG
return apiUnprotected(route: route)
#else
let prefixed = grouped("api", "v1", route)
return prefixed.grouped(
User.authenticator(),
UserToken.authenticator(),
User.guardMiddleware()
)
#endif
}
}