feat: Begins creating an auth client and integrates into view controller routes.

This commit is contained in:
2026-01-16 17:04:05 -05:00
parent 761ba29c1e
commit 3ec1ee2814
5 changed files with 78 additions and 31 deletions

View File

@@ -12,11 +12,7 @@ extension ViewController {
.init(
route: route,
isHtmxRequest: request.isHtmxRequest,
logger: request.logger,
authenticateUser: { request.session.authenticate($0) },
currentUser: {
try request.auth.require(User.self)
}
logger: request.logger
)
)
return AnyHTMLResponse(value: html)

View File

@@ -1,12 +1,13 @@
import ApiController
import AuthClient
import DatabaseClient
import Dependencies
import ManualDCore
import Vapor
import ViewController
// Taken from discussions page on `swift-dependencies`.
// FIX: Use live view controller.
struct DependenciesMiddleware: AsyncMiddleware {
private let values: DependencyValues.Continuation
@@ -29,6 +30,7 @@ struct DependenciesMiddleware: AsyncMiddleware {
try await values.yield {
try await withDependencies {
$0.apiController = apiController
$0.authClient = .live(on: request)
$0.database = database
// $0.dateFormatter = .liveValue
$0.viewController = viewController

View File

@@ -0,0 +1,51 @@
import DatabaseClient
import Dependencies
import DependenciesMacros
import ManualDCore
import Vapor
extension DependencyValues {
public var authClient: AuthClient {
get { self[AuthClient.self] }
set { self[AuthClient.self] = newValue }
}
}
@DependencyClient
public struct AuthClient: Sendable {
public var createAndLogin: @Sendable (User.Create) async throws -> User
public var currentUser: @Sendable () throws -> User
public var login: @Sendable (User.Login) async throws -> User
public var logout: @Sendable () throws -> Void
}
extension AuthClient: TestDependencyKey {
public static let testValue = Self()
public static func live(on request: Request) -> Self {
@Dependency(\.database) var database
return .init(
createAndLogin: { createForm in
let user = try await database.users.create(createForm)
_ = try await database.users.login(
.init(email: createForm.email, password: createForm.password)
)
request.auth.login(user)
request.logger.debug("LOGGED IN: \(user.id)")
return user
},
currentUser: {
try request.auth.require(User.self)
},
login: { loginForm in
let token = try await database.users.login(loginForm)
let user = try await database.users.get(token.userID)!
request.session.authenticate(user)
request.logger.debug("LOGGED IN: \(user.id)")
return user
},
logout: { request.auth.logout(User.self) }
)
}
}

View File

@@ -1,3 +1,4 @@
import AuthClient
import Dependencies
import DependenciesMacros
import Elementary
@@ -15,10 +16,6 @@ public typealias AnySendableHTML = (any HTML & Sendable)
@DependencyClient
public struct ViewController: Sendable {
public typealias AuthenticateHandler = @Sendable (User) -> Void
public typealias CurrentUserHandler = @Sendable () throws -> User
public var view: @Sendable (Request) async throws -> AnySendableHTML
}
@@ -29,21 +26,15 @@ extension ViewController {
public let route: SiteRoute.View
public let isHtmxRequest: Bool
public let logger: Logger
public let authenticateUser: AuthenticateHandler
public let currentUser: CurrentUserHandler
public init(
route: SiteRoute.View,
isHtmxRequest: Bool,
logger: Logger,
authenticateUser: @escaping AuthenticateHandler,
currentUser: @escaping CurrentUserHandler
logger: Logger
) {
self.route = route
self.isHtmxRequest = isHtmxRequest
self.logger = logger
self.authenticateUser = authenticateUser
self.currentUser = currentUser
}
}
@@ -62,28 +53,23 @@ extension ViewController: DependencyKey {
extension ViewController.Request {
func currentUser() throws -> User {
@Dependency(\.authClient.currentUser) var currentUser
return try currentUser()
}
func authenticate(
_ login: User.Login
) async throws -> User {
@Dependency(\.database.users) var users
let token = try await users.login(login)
let user = try await users.get(token.userID)!
authenticateUser(user)
logger.debug("Logged in user: \(user.id)")
return user
@Dependency(\.authClient) var auth
return try await auth.login(login)
}
@discardableResult
func createAndAuthenticate(
_ signup: User.Create
) async throws -> User {
@Dependency(\.database.users) var users
let user = try await users.create(signup)
let _ = try await users.login(
.init(email: signup.email, password: signup.password)
)
authenticateUser(user)
logger.debug("Created and logged in user: \(user.id)")
return user
@Dependency(\.authClient) var auth
return try await auth.createAndLogin(signup)
}
}