Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 20 additions & 22 deletions Sources/Grodt/Application/routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,33 @@ func routes(_ app: Application) async throws {
app.middleware.use(app.sessions.middleware)
app.middleware.use(globalRateLimiter)

try app.group("") { routeBuilder in
try routeBuilder
.grouped(loginRateLimiter)
.register(collection: UserController(dtoMapper: loginResponseDTOMapper))
}

let tokenAuthMiddleware = UserToken.authenticator()
let guardAuthMiddleware = User.guardMiddleware()

let protected = app.grouped([tokenAuthMiddleware, guardAuthMiddleware])
try protected.group("api") { routeBuilder in
try routeBuilder.register(collection:
PortfoliosController(
portfolioRepository: PostgresPortfolioRepository(database: app.db),
currencyRepository: PostgresCurrencyRepository(database: app.db),
historicalPortfolioPerformanceUpdater: portfolioPerformanceUpdater,
dataMapper: portfolioDTOMapper)
try app.group("api") { api in
// Public routes
try api
.grouped(loginRateLimiter)
.register(collection: UserController(dtoMapper: loginResponseDTOMapper))

// Protected routes
let protected = api.grouped([tokenAuthMiddleware, guardAuthMiddleware])
try protected.register(collection:
PortfoliosController(
portfolioRepository: PostgresPortfolioRepository(database: app.db),
currencyRepository: PostgresCurrencyRepository(database: app.db),
historicalPortfolioPerformanceUpdater: portfolioPerformanceUpdater,
dataMapper: portfolioDTOMapper)
)

let transactionController = TransactionsController(transactionsRepository: PostgresTransactionRepository(database: app.db),
currencyRepository: PostgresCurrencyRepository(database: app.db),
dataMapper: transactionDTOMapper)

currencyRepository: PostgresCurrencyRepository(database: app.db),
dataMapper: transactionDTOMapper)
transactionController.delegate = transactionChangedHandler
try routeBuilder.register(collection: transactionController)

try routeBuilder.register(collection: tickersController)
try routeBuilder.register(collection: investmentsController)
try routeBuilder.register(collection: accountController)
try protected.register(collection: transactionController)
try protected.register(collection: tickersController)
try protected.register(collection: investmentsController)
try protected.register(collection: accountController)
}

if app.environment != .testing {
Expand Down
10 changes: 6 additions & 4 deletions Sources/Grodt/Controllers/UserController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ struct UserController: RouteCollection {

func boot(routes: Vapor.RoutesBuilder) throws {
let passwordProtected = routes.grouped(User.authenticator())
passwordProtected.post("login") { req async throws -> LoginResponseDTO in
passwordProtected.post("login") { req async throws -> Response in
let user = try req.auth.require(User.self)
let token = try user.generateToken()
try await token.save(on: req.db)
return dtoMapper.response(from: token)

let response = Response(status: .ok)
response.headers.add(name: .authorization, value: "Bearer \(token.value)")

return response
}
}
}

extension LoginResponseDTO: Content { }
5 changes: 2 additions & 3 deletions Tests/GrodtTests/GrodtTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ class GrodtControllerTestCase: GrodtTestCase {
}

private func authHeader() async throws -> (String, String) {
let login = try await app.sendRequest(.POST, "login", headers: HTTPHeaders([AuthorizationHeader.basic(email: user.email, password: "password").value]))
let response = try login.content.decode(LoginResponseDTO.self)
return AuthorizationHeader.bearer(token: response.value).value
let login = try await app.sendRequest(.POST, "api/login", headers: HTTPHeaders([AuthorizationHeader.basic(email: user.email, password: "password").value]))
return AuthorizationHeader.bearer(token: login.headers.bearerAuthorization!.token).value
}
}

Expand Down