feat: Removes old tests, fixes authentication middleware not working, view routes updated to not have delete routes and uses api routes for delete methods.
This commit is contained in:
@@ -7,13 +7,14 @@ import Vapor
|
||||
private let apiMiddleware: [any Middleware] = [
|
||||
UserPasswordAuthenticator(),
|
||||
UserTokenAuthenticator(),
|
||||
UserSessionAuthenticator(),
|
||||
User.guardMiddleware()
|
||||
]
|
||||
|
||||
extension ApiRoute {
|
||||
var middleware: [any Middleware]? { apiMiddleware }
|
||||
|
||||
func handle(request: Request) async throws -> any AsyncResponseEncodable {
|
||||
func respond(request: Request) async throws -> any AsyncResponseEncodable {
|
||||
switch self {
|
||||
case let .employee(route):
|
||||
return try await route.handleApiRequest(request: request)
|
||||
|
||||
53
Sources/App/Extensions/ViewController+respond.swift
Normal file
53
Sources/App/Extensions/ViewController+respond.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
import Elementary
|
||||
import SharedModels
|
||||
import Vapor
|
||||
import VaporElementary
|
||||
import ViewController
|
||||
|
||||
extension ViewController {
|
||||
func respond(route: ViewRoute, request: Vapor.Request) async throws -> any AsyncResponseEncodable {
|
||||
let html = try await view(
|
||||
for: route,
|
||||
isHtmxRequest: request.isHtmxRequest,
|
||||
logger: request.logger,
|
||||
authenticate: { request.session.authenticate($0) }
|
||||
)
|
||||
return AnyHTMLResponse(value: html)
|
||||
}
|
||||
}
|
||||
|
||||
// Re-adapted from `HTMLResponse` in the VaporElementary package to work with any html types
|
||||
// returned from the view controller.
|
||||
struct AnyHTMLResponse: AsyncResponseEncodable {
|
||||
|
||||
public var chunkSize: Int
|
||||
public var headers: HTTPHeaders = ["Content-Type": "text/html; charset=utf-8"]
|
||||
var value: _SendableAnyHTMLBox
|
||||
|
||||
init(chunkSize: Int = 1024, additionalHeaders: HTTPHeaders = [:], value: AnySendableHTML) {
|
||||
self.chunkSize = chunkSize
|
||||
if additionalHeaders.contains(name: .contentType) {
|
||||
self.headers = additionalHeaders
|
||||
} else {
|
||||
headers.add(contentsOf: additionalHeaders)
|
||||
}
|
||||
self.value = .init(value)
|
||||
}
|
||||
|
||||
func encodeResponse(for request: Request) async throws -> Response {
|
||||
Response(
|
||||
status: .ok,
|
||||
headers: headers,
|
||||
body: .init(asyncStream: { [value, chunkSize] writer in
|
||||
guard let html = value.tryTake() else {
|
||||
assertionFailure("Non-sendable HTML value consumed more than once")
|
||||
request.logger.error("Non-sendable HTML value consumed more than once")
|
||||
throw Abort(.internalServerError)
|
||||
}
|
||||
try await writer.writeHTML(html, chunkSize: chunkSize)
|
||||
try await writer.write(.end)
|
||||
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
import DatabaseClientLive
|
||||
import Dependencies
|
||||
import Vapor
|
||||
import ViewControllerLive
|
||||
|
||||
// Taken from discussions page on `swift-dependencies`.
|
||||
|
||||
// TODO: Pass dependencies to set into this middleware.
|
||||
struct DependenciesMiddleware: AsyncMiddleware {
|
||||
|
||||
private let values: DependencyValues.Continuation
|
||||
private let database: DatabaseClient
|
||||
private let viewController: ViewController
|
||||
|
||||
init(
|
||||
database: DatabaseClient
|
||||
database: DatabaseClient,
|
||||
viewController: ViewController = .liveValue
|
||||
) {
|
||||
self.values = withEscapedDependencies { $0 }
|
||||
self.database = database
|
||||
self.viewController = viewController
|
||||
}
|
||||
|
||||
func respond(to request: Request, chainingTo next: any AsyncResponder) async throws -> Response {
|
||||
@@ -22,6 +25,7 @@ struct DependenciesMiddleware: AsyncMiddleware {
|
||||
try await withDependencies {
|
||||
$0.database = database
|
||||
$0.dateFormatter = .liveValue
|
||||
$0.viewController = viewController
|
||||
} operation: {
|
||||
try await next.respond(to: request)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ extension SharedModels.ViewRoute {
|
||||
|
||||
var middleware: [any Middleware]? {
|
||||
switch self {
|
||||
case .index: return viewProtectedMiddleware
|
||||
// case .index: return viewProtectedMiddleware
|
||||
case let .employee(route): return route.middleware
|
||||
case .login: return nil
|
||||
case let .purchaseOrder(route): return route.middleware
|
||||
@@ -48,6 +48,11 @@ public func configure(
|
||||
|
||||
app.middleware.use(DependenciesMiddleware(database: databaseClient))
|
||||
|
||||
// Redirect the index path to purchase order route.
|
||||
app.get { req in
|
||||
req.redirect(to: ViewRoute.router.path(for: .purchaseOrder(.index)))
|
||||
}
|
||||
|
||||
app.mount(
|
||||
SiteRoute.router,
|
||||
middleware: {
|
||||
@@ -79,7 +84,6 @@ extension SiteRoute {
|
||||
case .health:
|
||||
return nil
|
||||
case let .view(route):
|
||||
// return nil
|
||||
return route.middleware
|
||||
}
|
||||
}
|
||||
@@ -90,62 +94,13 @@ func siteHandler(
|
||||
request: Request,
|
||||
route: SiteRoute
|
||||
) async throws -> any AsyncResponseEncodable {
|
||||
@Dependency(\.viewController) var viewController
|
||||
switch route {
|
||||
case let .api(route):
|
||||
return try await route.handle(request: request)
|
||||
return try await route.respond(request: request)
|
||||
case .health:
|
||||
return HTTPStatus.ok
|
||||
case let .view(route):
|
||||
return try await route.respond(request: request)
|
||||
// return try await route.handle(request: request)
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewRoute {
|
||||
func respond(request: Request) async throws -> any AsyncResponseEncodable {
|
||||
if self == .index {
|
||||
return request.redirect(to: ViewRoute.router.path(for: .purchaseOrder(.index)))
|
||||
} else {
|
||||
let html = try await view(isHtmxRequest: request.isHtmxRequest, authenticate: { request.auth.login($0) })
|
||||
// Delete routes return nil, but are valid routes.
|
||||
guard let html else {
|
||||
return HTTPStatus.ok
|
||||
}
|
||||
return AnyHTMLResponse(value: html)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AnyHTMLResponse: AsyncResponseEncodable {
|
||||
|
||||
public var chunkSize: Int
|
||||
public var headers: HTTPHeaders = ["Content-Type": "text/html; charset=utf-8"]
|
||||
var value: _SendableAnyHTMLBox
|
||||
|
||||
init(chunkSize: Int = 1024, additionalHeaders: HTTPHeaders = [:], value: any HTML & Sendable) {
|
||||
self.chunkSize = chunkSize
|
||||
if additionalHeaders.contains(name: .contentType) {
|
||||
self.headers = additionalHeaders
|
||||
} else {
|
||||
headers.add(contentsOf: additionalHeaders)
|
||||
}
|
||||
self.value = .init(value)
|
||||
}
|
||||
|
||||
func encodeResponse(for request: Request) async throws -> Response {
|
||||
Response(
|
||||
status: .ok,
|
||||
headers: headers,
|
||||
body: .init(asyncStream: { [value, chunkSize] writer in
|
||||
guard let html = value.tryTake() else {
|
||||
assertionFailure("Non-sendable HTML value consumed more than once")
|
||||
request.logger.error("Non-sendable HTML value consumed more than once")
|
||||
throw Abort(.internalServerError)
|
||||
}
|
||||
try await writer.writeHTML(html, chunkSize: chunkSize)
|
||||
try await writer.write(.end)
|
||||
|
||||
})
|
||||
)
|
||||
return try await viewController.respond(route: route, request: request)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import Dependencies
|
||||
import Elementary
|
||||
import SharedModels
|
||||
@_exported import ViewController
|
||||
Reference in New Issue
Block a user