Skip to content

Commit 5e3e1af

Browse files
tbartelmesstanner0101
authored andcommitted
Handle Authentication Errors (#14)
* Added special case handling for authentcation. When the authentication sends an error, there is no second message, which causes the authentication promise to never fail or succeed. This implementation is a bit "hacky" it adds the "errorMessageIsFinal" property to every `ConnectionHandler`. * Update Sources/NIOPostgres/Connection/PostgresConnectionHandler.swift Co-Authored-By: tbartelmess <[email protected]> * Added "testInvalidPassword" to all tests * Added warning
1 parent 9dcb2e7 commit 5e3e1af

File tree

5 files changed

+51
-13
lines changed

5 files changed

+51
-13
lines changed

Sources/NIOPostgres/Connection/PostgresConnection+Authenticate.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ private final class PostgresAuthenticationRequest: PostgresRequestHandler {
2424
let database: String?
2525
let password: String?
2626
var state: State
27-
27+
28+
var errorMessageIsFinal: Bool {
29+
return true
30+
}
31+
2832
init(username: String, database: String?, password: String?) {
2933
self.state = .ready
3034
self.username = username

Sources/NIOPostgres/Connection/PostgresConnectionHandler.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ extension PostgresConnection {
1111
public protocol PostgresRequestHandler {
1212
func respond(to message: PostgresMessage) throws -> [PostgresMessage]?
1313
func start() throws -> [PostgresMessage]
14+
15+
#warning("TODO: Workaround for Authentication see #14")
16+
var errorMessageIsFinal: Bool { get }
17+
}
18+
19+
20+
extension PostgresRequestHandler {
21+
var errorMessageIsFinal: Bool {
22+
return false
23+
}
1424
}
1525

1626
// MARK: Private
@@ -48,7 +58,12 @@ final class PostgresConnectionHandler: ChannelDuplexHandler {
4858
switch message.identifier {
4959
case .error:
5060
let error = try PostgresMessage.Error(message: message)
51-
request.error = PostgresError.server(error)
61+
let postgresError = PostgresError.server(error)
62+
if request.delegate.errorMessageIsFinal {
63+
request.promise.fail(postgresError)
64+
self.queue.removeFirst()
65+
}
66+
request.error = postgresError
5267
case .notice:
5368
let notice = try PostgresMessage.Error(message: message)
5469
print("[NIOPostgres] [NOTICE] \(notice)")

Tests/NIOPostgresTests/NIOPostgresTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,16 @@ final class NIOPostgresTests: XCTestCase {
284284
}
285285
}
286286
}
287+
288+
func testInvalidPassword() throws {
289+
let auth = PostgresConnection.testUnauthenticated(on: eventLoop).flatMap({ (connection) in
290+
connection.authenticate(username: "invalid", database: "invalid", password: "bad").map { connection }
291+
})
292+
do {
293+
let _ = try auth.wait()
294+
XCTFail("The authentication should fail")
295+
} catch let error as PostgresError {
296+
XCTAssertEqual(error.code, .invalid_password)
297+
}
298+
}
287299
}

Tests/NIOPostgresTests/Utilities.swift

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,28 @@ import NIO
22
import NIOPostgres
33

44
extension PostgresConnection {
5-
static func test(on eventLoop: EventLoop) -> EventLoopFuture<PostgresConnection> {
5+
static func address() throws -> SocketAddress {
6+
#if os(Linux)
7+
return try .newAddressResolving(host: "psql", port: 5432)
8+
#else
9+
return try .init(ipAddress: "127.0.0.1", port: 5432)
10+
#endif
11+
}
12+
13+
static func testUnauthenticated(on eventLoop: EventLoop) -> EventLoopFuture<PostgresConnection> {
614
do {
7-
let address: SocketAddress
8-
#if os(Linux)
9-
address = try .newAddressResolving(host: "psql", port: 5432)
10-
#else
11-
address = try .init(ipAddress: "127.0.0.1", port: 5432)
12-
#endif
13-
return connect(to: address, on: eventLoop).flatMap { conn in
14-
return conn.authenticate(username: "vapor_username", database: "vapor_database", password: "vapor_password")
15-
.map { conn }
16-
}
15+
return connect(to: try address(), on: eventLoop)
1716
} catch {
1817
return eventLoop.makeFailedFuture(error)
1918
}
2019
}
20+
21+
static func test(on eventLoop: EventLoop) -> EventLoopFuture<PostgresConnection> {
22+
return testUnauthenticated(on: eventLoop).flatMap { conn in
23+
return conn.authenticate(username: "vapor_username", database: "vapor_database", password: "vapor_password")
24+
.map { conn }
25+
}
26+
}
2127
}
2228

2329

Tests/NIOPostgresTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extension NIOPostgresTests {
1717
("testSelectPerformance", testSelectPerformance),
1818
("testRangeSelectPerformance", testRangeSelectPerformance),
1919
("testRangeSelectDecodePerformance", testRangeSelectDecodePerformance),
20+
("testInvalidPassword", testInvalidPassword),
2021
]
2122
}
2223

0 commit comments

Comments
 (0)