Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update from Hummingbird Project Template #80

Merged
merged 3 commits into from
Nov 28, 2024
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
6 changes: 1 addition & 5 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@ concurrency:

jobs:
validate:
runs-on: macOS-latest
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install Dependencies
run: |
brew install mint
mint install NickLockwood/[email protected] --no-link
- name: run script
run: ./scripts/validate.sh
63 changes: 63 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"version" : 1,
"indentation" : {
"spaces" : 4
},
"tabWidth" : 4,
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"spacesAroundRangeFormationOperators" : false,
"indentConditionalCompilationBlocks" : false,
"indentSwitchCaseLabels" : false,
"lineBreakAroundMultilineExpressionChainComponents" : false,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : true,
"lineBreakBeforeEachGenericRequirement" : true,
"lineLength" : 150,
"maximumBlankLines" : 1,
"respectsExistingLineBreaks" : true,
"prioritizeKeepingFunctionOutputTogether" : true,
"multiElementCollectionTrailingCommas" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : false,
"AlwaysUseLowerCamelCase" : false,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OmitExplicitReturns" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReplaceForEachWithForLoop" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"UseEarlyExits" : false,
"UseExplicitNilCheckInConditions" : false,
"UseLetInEveryBoundCaseVariable" : false,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : false,
"UseSynthesizedInitializer" : false,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
}
}
26 changes: 0 additions & 26 deletions .swiftformat

This file was deleted.

2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ The main development branch of the repository is `main`.

### Formatting

We use Nick Lockwood's SwiftFormat for formatting code. PRs will not be accepted if they haven't be formatted. The current version of SwiftFormat we are using is v0.53.10.
We use Apple's swift-format for formatting code. PRs will not be accepted if they haven't be formatted.
76 changes: 47 additions & 29 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,53 @@ let package = Package(
.package(url: "https://github.com/swift-extras/swift-extras-base64.git", from: "1.0.0"),
],
targets: [
.target(name: "HummingbirdAuth", dependencies: [
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "ExtrasBase64", package: "swift-extras-base64"),
]),
.target(name: "HummingbirdBasicAuth", dependencies: [
.byName(name: "HummingbirdAuth"),
.byName(name: "HummingbirdBcrypt"),
.product(name: "Hummingbird", package: "hummingbird"),
]),
.target(name: "HummingbirdBcrypt", dependencies: [
.byName(name: "CBcrypt"),
]),
.target(name: "HummingbirdOTP", dependencies: [
.product(name: "Crypto", package: "swift-crypto"),
.product(name: "ExtrasBase64", package: "swift-extras-base64"),
]),
.target(name: "HummingbirdAuthTesting", dependencies: [
.byName(name: "HummingbirdAuth"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
]),
.target(
name: "HummingbirdAuth",
dependencies: [
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "ExtrasBase64", package: "swift-extras-base64"),
]
),
.target(
name: "HummingbirdBasicAuth",
dependencies: [
.byName(name: "HummingbirdAuth"),
.byName(name: "HummingbirdBcrypt"),
.product(name: "Hummingbird", package: "hummingbird"),
]
),
.target(
name: "HummingbirdBcrypt",
dependencies: [
.byName(name: "CBcrypt")
]
),
.target(
name: "HummingbirdOTP",
dependencies: [
.product(name: "Crypto", package: "swift-crypto"),
.product(name: "ExtrasBase64", package: "swift-extras-base64"),
]
),
.target(
name: "HummingbirdAuthTesting",
dependencies: [
.byName(name: "HummingbirdAuth"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
]
),
.target(name: "CBcrypt", dependencies: []),
.testTarget(name: "HummingbirdAuthTests", dependencies: [
.byName(name: "HummingbirdAuth"),
.byName(name: "HummingbirdBasicAuth"),
.byName(name: "HummingbirdBcrypt"),
.byName(name: "HummingbirdOTP"),
.byName(name: "HummingbirdAuthTesting"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
.product(name: "NIOPosix", package: "swift-nio"),
]),
.testTarget(
name: "HummingbirdAuthTests",
dependencies: [
.byName(name: "HummingbirdAuth"),
.byName(name: "HummingbirdBasicAuth"),
.byName(name: "HummingbirdBcrypt"),
.byName(name: "HummingbirdOTP"),
.byName(name: "HummingbirdAuthTesting"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
.product(name: "NIOPosix", package: "swift-nio"),
]
),
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ public struct ClosureAuthenticator<
}

public func authenticate(request: Request, context: Context) async throws -> Context.Identity? {
return try await self.closure(request, context)
try await self.closure(request, context)
}
}
4 changes: 2 additions & 2 deletions Sources/HummingbirdAuth/Sessions/SessionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ public struct SessionContext<Session: Sendable & Codable>: Sendable {

/// Internal access to full session data. Used by `SessionMiddleware`.
var sessionData: SessionData<Session>? {
get { self._storage.withLockedValue { $0 }}
nonmutating set { self._storage.withLockedValue { $0 = newValue }}
get { self._storage.withLockedValue { $0 } }
nonmutating set { self._storage.withLockedValue { $0 = newValue } }
}
}

Expand Down
6 changes: 5 additions & 1 deletion Sources/HummingbirdAuth/Sessions/SessionMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ public struct SessionMiddleware<Context: SessionRequestContext>: RouterMiddlewar
/// - storage: Persist driver to use for storage
/// - sessionCookieParameters: Session cookie parameters
/// - defaultSessionExpiration: Default expiration for session data
public init(storage: any PersistDriver, sessionCookieParameters: SessionCookieParameters, defaultSessionExpiration: Duration = .seconds(60 * 60 * 12)) {
public init(
storage: any PersistDriver,
sessionCookieParameters: SessionCookieParameters,
defaultSessionExpiration: Duration = .seconds(60 * 60 * 12)
) {
self.sessionStorage = .init(storage, sessionCookieParameters: sessionCookieParameters)
self.defaultSessionExpiration = defaultSessionExpiration
}
Expand Down
13 changes: 9 additions & 4 deletions Sources/HummingbirdAuthTesting/TestClient+Auth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,25 @@ import XCTest
public struct TestAuthentication: Equatable {
/// create basic authentication test
public static func basic(username: String, password: String) -> Self {
return .init(value: .basic(username: username, password: password))
.init(value: .basic(username: username, password: password))
}

/// create bearer authentication test
public static func bearer(_ token: String) -> Self {
return .init(value: .bearer(token))
.init(value: .bearer(token))
}

/// create cookie authentication test
public static func cookie(name: String, value: String) -> Self {
return .init(value: .cookie(name: name, value: value))
.init(value: .cookie(name: name, value: value))
}

func apply(uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) -> (uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) {
func apply(
uri: String,
method: HTTPRequest.Method,
headers: HTTPFields,
body: ByteBuffer?
) -> (uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) {
switch self.value {
case .basic(let username, let password):
var headers = headers
Expand Down
2 changes: 1 addition & 1 deletion Sources/HummingbirdBcrypt/Bcrypt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ public enum Bcrypt {
/// - text: plain text
/// - hash: hashed data
public static func verify(_ text: String, hash: String) -> Bool {
return c_hb_bcrypt_checkpass(text, hash) == 0
c_hb_bcrypt_checkpass(text, hash) == 0
}
}
7 changes: 4 additions & 3 deletions Sources/HummingbirdOTP/OTP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ extension OTP {
if let issuer {
url += "&issuer=\(issuer)"
}
url += parameters
url +=
parameters
.map { "&\($0.key)=\($0.value)" }
.joined()
return url
Expand Down Expand Up @@ -86,7 +87,7 @@ extension OTP {
return v
}
func pow(_ value: Int, _ power: Int) -> Int {
return repeatElement(value, count: power).reduce(1, *)
repeatElement(value, count: power).reduce(1, *)
}
return truncation % pow(10, length)
}
Expand Down Expand Up @@ -217,7 +218,7 @@ extension FixedWidthInteger {
}
}

extension Array<UInt8> {
extension [UInt8] {
/// Construct Array of UInt8 by copying memory
init(_ bytes: UnsafeRawPointer, count: Int) {
self.init(unsafeUninitializedCapacity: count) { buffer, c in
Expand Down
22 changes: 12 additions & 10 deletions Tests/HummingbirdAuthTests/AuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class AuthTests: XCTestCase {
}
let router = Router(context: BasicAuthRequestContext<User>.self)
router.get { request, _ -> String? in
return request.headers.bearer?.token
request.headers.bearer?.token
}
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
Expand All @@ -48,7 +48,7 @@ final class AuthTests: XCTestCase {
}
let router = Router(context: BasicAuthRequestContext<User>.self)
router.get { request, _ -> String? in
return request.headers.basic.map { "\($0.username):\($0.password)" }
request.headers.basic.map { "\($0.username):\($0.password)" }
}
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
Expand Down Expand Up @@ -160,10 +160,12 @@ final class AuthTests: XCTestCase {
}
let router = Router(context: BasicAuthRequestContext<User>.self)
router.group()
.add(middleware: ClosureAuthenticator { request, _ -> User? in
guard let user = request.uri.queryParameters.get("user") else { return nil }
return User(name: user)
})
.add(
middleware: ClosureAuthenticator { request, _ -> User? in
guard let user = request.uri.queryParameters.get("user") else { return nil }
return User(name: user)
}
)
.get("authenticate") { _, context in
let user = try context.requireIdentity()
return user.name
Expand Down Expand Up @@ -195,12 +197,12 @@ final class AuthTests: XCTestCase {
.add(middleware: TestAuthenticator())
.add(middleware: IsAuthenticatedMiddleware())
.get("authenticated") { _, _ -> HTTPResponse.Status in
return .ok
.ok
}
router.group()
.add(middleware: IsAuthenticatedMiddleware())
.get("unauthenticated") { _, _ -> HTTPResponse.Status in
return .ok
.ok
}
let app = Application(responder: router.buildResponder())

Expand All @@ -222,7 +224,7 @@ final class AuthTests: XCTestCase {

struct MyUserRepository: UserPasswordRepository {
func getUser(named username: String, context: UserRepositoryContext) -> User? {
return self.users[username].map { .init(username: username, passwordHash: $0) }
self.users[username].map { .init(username: username, passwordHash: $0) }
}

let users = ["admin": Bcrypt.hash("password", cost: 8)]
Expand Down Expand Up @@ -256,7 +258,7 @@ final class AuthTests: XCTestCase {
let router = Router(context: BasicAuthRequestContext<User>.self)
router.add(
middleware: BasicAuthenticator { username, _ in
return users[username].map { User(username: username, passwordHash: $0) }
users[username].map { User(username: username, passwordHash: $0) }
}
)
router.get { _, context -> String? in
Expand Down
7 changes: 4 additions & 3 deletions Tests/HummingbirdAuthTests/SessionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
//
//===----------------------------------------------------------------------===//

@testable import Hummingbird
import HummingbirdAuth
import HummingbirdAuthTesting
import HummingbirdTesting
import NIOPosix
import XCTest

@testable import Hummingbird

final class SessionTests: XCTestCase {
func testSessionAuthenticator() async throws {
struct User: Sendable {
Expand Down Expand Up @@ -87,7 +88,7 @@ final class SessionTests: XCTestCase {
router.group()
.addMiddleware {
SessionAuthenticator { session, _ -> User? in
return User(name: session.userID)
User(name: session.userID)
}
}
.get("session") { _, context -> HTTPResponse.Status in
Expand Down Expand Up @@ -279,7 +280,7 @@ final class SessionTests: XCTestCase {
let cookie = try await sessionStorage.save(session: 1, expiresIn: .seconds(60))
router.add(middleware: SessionMiddleware(storage: persist))
router.post("test") { _, context in
return context.sessions.session?.description
context.sessions.session?.description
}
let app = Application(responder: router.buildResponder())

Expand Down
Loading