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

Adopt swift-format #198

Merged
merged 8 commits into from
Oct 3, 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
9 changes: 9 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ on:
push: { branches: [ main ] }

jobs:
lint:
runs-on: ubuntu-latest
container: swift:jammy
steps:
- name: Check out JWTKit
uses: actions/checkout@v4
- name: Run format lint check
run: swift format lint --strict --recursive --parallel .

linux-integration:
if: ${{ !(github.event.pull_request.draft || false) }}
runs-on: ubuntu-latest
Expand Down
70 changes: 70 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"fileScopedDeclarationPrivacy": {
"accessLevel": "private"
},
"indentation": {
"spaces": 4
},
"indentConditionalCompilationBlocks": true,
"indentSwitchCaseLabels": false,
"lineBreakAroundMultilineExpressionChainComponents": false,
"lineBreakBeforeControlFlowKeywords": false,
"lineBreakBeforeEachArgument": false,
"lineBreakBeforeEachGenericRequirement": false,
"lineLength": 140,
"maximumBlankLines": 1,
"multiElementCollectionTrailingCommas": true,
"noAssignmentInExpressions": {
"allowedFunctions": [
"XCTAssertNoThrow"
]
},
"prioritizeKeepingFunctionOutputTogether": false,
"respectsExistingLineBreaks": true,
"rules": {
"AllPublicDeclarationsHaveDocumentation": false,
"AlwaysUseLiteralForEmptyCollectionInit": false,
"AlwaysUseLowerCamelCase": true,
"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,
"NoPlaygroundLiterals": true,
"NoVoidReturnOnFunctionSignature": true,
"OmitExplicitReturns": false,
"OneCasePerLine": true,
"OneVariableDeclarationPerLine": true,
"OnlyOneTrailingClosureArgument": true,
"OrderedImports": true,
"ReplaceForEachWithForLoop": true,
"ReturnVoidInsteadOfEmptyTuple": true,
"TypeNamesShouldBeCapitalized": true,
"UseEarlyExits": false,
"UseExplicitNilCheckInConditions": true,
"UseLetInEveryBoundCaseVariable": true,
"UseShorthandTypeNames": true,
"UseSingleLinePropertyGetter": true,
"UseSynthesizedInitializer": true,
"UseTripleSlashForDocumentationComments": true,
"UseWhereClausesInForLoops": false,
"ValidateDocumentationComments": false
},
"spacesAroundRangeFormationOperators": false,
"tabWidth": 8,
"version": 1
}
14 changes: 7 additions & 7 deletions Snippets/JWKExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import JWTKit
let rsaModulus = "..."

let json = """
{
"keys": [
{"kty": "RSA", "alg": "RS256", "kid": "a", "n": "\(rsaModulus)", "e": "AQAB"},
{"kty": "RSA", "alg": "RS512", "kid": "b", "n": "\(rsaModulus)", "e": "AQAB"},
]
}
"""
{
"keys": [
{"kty": "RSA", "alg": "RS256", "kid": "a", "n": "\(rsaModulus)", "e": "AQAB"},
{"kty": "RSA", "alg": "RS512", "kid": "b", "n": "\(rsaModulus)", "e": "AQAB"},
]
}
"""

// Create key collection and add JWKS
let keys = try await JWTKeyCollection().add(jwksJSON: json)
31 changes: 18 additions & 13 deletions Snippets/JWTKitExamples.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Foundation
// snippet.KEY_COLLECTION
import JWTKit

Expand Down Expand Up @@ -51,8 +52,8 @@ do {
do {
// snippet.VERIFYING
let exampleJWT = """
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ2YXBvciIsImV4cCI6NjQwOTIyMTEyMDAsImFkbWluIjp0cnVlfQ.lS5lpwfRNSZDvpGQk6x5JI1g40gkYCOWqbc3J_ghowo
"""
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ2YXBvciIsImV4cCI6NjQwOTIyMTEyMDAsImFkbWluIjp0cnVlfQ.lS5lpwfRNSZDvpGQk6x5JI1g40gkYCOWqbc3J_ghowo
"""

// snippet.VERIFYING_PAYLOAD
// Parse the JWT, verifies its signature, and decodes its content
Expand Down Expand Up @@ -105,8 +106,6 @@ do {
// snippet.end
}

import Foundation

extension DataProtocol {
func base64URLDecodedBytes() -> [UInt8] {
let string = String(decoding: self, as: UTF8.self)
Expand Down Expand Up @@ -142,16 +141,20 @@ struct CustomSerializer: JWTSerializer {
struct CustomParser: JWTParser {
var jsonDecoder: JWTJSONDecoder = .defaultForJWT

func parse<Payload>(_ token: some DataProtocol, as _: Payload.Type) throws -> (header: JWTHeader, payload: Payload, signature: Data) where Payload: JWTPayload {
func parse<Payload>(_ token: some DataProtocol, as _: Payload.Type) throws -> (
header: JWTHeader, payload: Payload, signature: Data
) where Payload: JWTPayload {
let (encodedHeader, encodedPayload, encodedSignature) = try getTokenParts(token)

let header = try jsonDecoder.decode(JWTHeader.self, from: .init(encodedHeader.base64URLDecodedBytes()))
let header = try jsonDecoder.decode(
JWTHeader.self, from: .init(encodedHeader.base64URLDecodedBytes()))

let payload = if header.b64?.asBool ?? true {
try self.jsonDecoder.decode(Payload.self, from: .init(encodedPayload.base64URLDecodedBytes()))
} else {
try self.jsonDecoder.decode(Payload.self, from: .init(encodedPayload))
}
let payload =
if header.b64?.asBool ?? true {
try self.jsonDecoder.decode(Payload.self, from: .init(encodedPayload.base64URLDecodedBytes()))
} else {
try self.jsonDecoder.decode(Payload.self, from: .init(encodedPayload))
}

let signature = Data(encodedSignature.base64URLDecodedBytes())

Expand All @@ -175,8 +178,10 @@ do {

do {
// snippet.CUSTOM_ENCODING
let encoder = JSONEncoder(); encoder.dateEncodingStrategy = .iso8601
let decoder = JSONDecoder(); decoder.dateDecodingStrategy = .iso8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let parser = DefaultJWTParser(jsonDecoder: decoder)
let serializer = DefaultJWTSerializer(jsonEncoder: encoder)
Expand Down
10 changes: 5 additions & 5 deletions Sources/JWTKit/Claims/JWTClaim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ public protocol JWTClaim: Codable, Sendable {
init(value: Value)
}

public extension JWTClaim where Value == String, Self: ExpressibleByStringLiteral {
extension JWTClaim where Value == String, Self: ExpressibleByStringLiteral {
/// See `ExpressibleByStringLiteral`.
init(stringLiteral string: String) {
public init(stringLiteral string: String) {
self.init(value: string)
}
}

public extension JWTClaim {
extension JWTClaim {
/// See `Decodable`.
init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let single = try decoder.singleValueContainer()
try self.init(value: single.decode(Value.self))
}

/// See `Encodable`.
func encode(to encoder: Encoder) throws {
public func encode(to encoder: Encoder) throws {
var single = encoder.singleValueContainer()
try single.encode(value)
}
Expand Down
17 changes: 9 additions & 8 deletions Sources/JWTKit/Claims/JWTMultiValueClaim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ public protocol JWTMultiValueClaim: JWTClaim where Value: Collection, Value.Elem
init(value: Value.Element)
}

public extension JWTMultiValueClaim {
extension JWTMultiValueClaim {
/// Single-element initializer. Uses the `CollectionOfOneDecoder` to work
/// around the lack of an initializer on the `Collection` protocol. Not
/// spectacularly efficient, but it works.
init(value: Value.Element) {
public init(value: Value.Element) {
self.init(value: try! CollectionOfOneDecoder<Value>.decode(value))
}

Expand Down Expand Up @@ -39,13 +39,14 @@ public extension JWTMultiValueClaim {
/// in a list of more than one. This implementation behaves according to
/// the semantics of the particular `Collection` type used as its value;
/// `Array` will preserve ordering and duplicates, `Set` will not.
init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

do {
try self.init(value: container.decode(Value.Element.self))
} catch let DecodingError.typeMismatch(type, context)
where type == Value.Element.self && context.codingPath.count == container.codingPath.count
} catch DecodingError.typeMismatch(let type, let context)
where type == Value.Element.self
&& context.codingPath.count == container.codingPath.count
{
// Unfortunately, `typeMismatch()` doesn't let us explicitly look for what type found,
// only what type was expected, so we have to match the coding path depth instead.
Expand All @@ -65,11 +66,11 @@ public extension JWTMultiValueClaim {
/// - Warning: If the claim has zero values, this implementation will encode
/// an inefficient zero-element representation. See the notes regarding
/// this on `init(from decoder:)` above.
func encode(to encoder: Encoder) throws {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

switch self.value.first {
case let .some(value) where self.value.count == 1:
case .some(let value) where self.value.count == 1:
try container.encode(value)
default:
try container.encode(self.value)
Expand All @@ -85,7 +86,7 @@ public extension JWTMultiValueClaim {
/// `ExpressibleByArrayLiteral`, but what fun would that be?
private struct CollectionOfOneDecoder<T>: Decoder, UnkeyedDecodingContainer where T: Collection, T: Codable, T.Element: Codable {
static func decode(_ element: T.Element) throws -> T {
return try T(from: self.init(value: element))
try T(from: self.init(value: element))
}

/// The single value we're returning.
Expand Down
6 changes: 3 additions & 3 deletions Sources/JWTKit/Claims/JWTUnixEpochClaim.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import Foundation

public protocol JWTUnixEpochClaim: JWTClaim where Value == Date {}

public extension JWTUnixEpochClaim {
extension JWTUnixEpochClaim {
/// See `Decodable`.
init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
try self.init(value: container.decode(Date.self))
}

/// See `Encodable`.
func encode(to encoder: Encoder) throws {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.value)
}
Expand Down
6 changes: 1 addition & 5 deletions Sources/JWTKit/Claims/LocaleClaim.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#if compiler(<6.0) && !canImport(Darwin)
@preconcurrency import Foundation
#else
import Foundation
#endif
import Foundation

public struct LocaleClaim: JWTClaim, Equatable, ExpressibleByStringLiteral {
/// See ``JWTClaim``.
Expand Down
12 changes: 6 additions & 6 deletions Sources/JWTKit/ECDSA/ECDSA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public protocol ECDSAKey: Sendable {
var parameters: ECDSAParameters? { get }
}

public extension ECDSA {
struct PublicKey<Curve>: ECDSAKey, Equatable where Curve: ECDSACurveType {
extension ECDSA {
public struct PublicKey<Curve>: ECDSAKey, Equatable where Curve: ECDSACurveType {
typealias Signature = Curve.Signature
typealias PublicKey = Curve.PrivateKey.PublicKey

Expand Down Expand Up @@ -106,15 +106,15 @@ public extension ECDSA {
init(backing: PublicKey) {
self.backing = backing
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.parameters?.x == rhs.parameters?.x && lhs.parameters?.y == rhs.parameters?.y
}
}
}

public extension ECDSA {
struct PrivateKey<Curve>: ECDSAKey, Equatable where Curve: ECDSACurveType {
extension ECDSA {
public struct PrivateKey<Curve>: ECDSAKey, Equatable where Curve: ECDSACurveType {
typealias PrivateKey = Curve.PrivateKey
typealias Signature = PrivateKey.Signature

Expand Down Expand Up @@ -189,7 +189,7 @@ public extension ECDSA {
public init() {
self.backing = PrivateKey()
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.parameters?.x == rhs.parameters?.x && lhs.parameters?.y == rhs.parameters?.y
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/JWTKit/ECDSA/ECDSASigner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ struct ECDSASigner<Key: ECDSAKey>: JWTAlgorithm, CryptoSigner {
return [UInt8](signature.rawRepresentation)
}

public func verify(_ signature: some DataProtocol, signs plaintext: some DataProtocol) throws -> Bool {
public func verify(_ signature: some DataProtocol, signs plaintext: some DataProtocol) throws
-> Bool
{
let digest = try self.digest(plaintext)
return try publicKey.backing.isValidSignature(signature, for: digest)
}
Expand Down
16 changes: 9 additions & 7 deletions Sources/JWTKit/ECDSA/JWTKeyCollection+ECDSA.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Crypto

public extension JWTKeyCollection {
extension JWTKeyCollection {
/// Adds an ECDSA key to the collection.
///
/// Example Usage:
Expand All @@ -19,16 +19,18 @@ public extension JWTKeyCollection {
/// If `nil`, a default decoder is used.
/// - Returns: The same instance of the collection (`Self`), which allows for method chaining.
@discardableResult
func add(
public func add(
ecdsa key: some ECDSAKey,
kid: JWKIdentifier? = nil,
parser: some JWTParser = DefaultJWTParser(),
serializer: some JWTSerializer = DefaultJWTSerializer()
) -> Self {
add(.init(
algorithm: ECDSASigner(key: key),
parser: parser,
serializer: serializer
), for: kid)
add(
.init(
algorithm: ECDSASigner(key: key),
parser: parser,
serializer: serializer
), for: kid
)
}
}
9 changes: 1 addition & 8 deletions Sources/JWTKit/ECDSA/P256+CurveType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension P256: ECDSACurveType {
/// Thus:
/// - The X coordinate spans bytes 1 through 32 (byte 0 is for the prefix).
/// - The Y coordinate spans bytes 33 through 64.
public static let byteRanges: (x: Range<Int>, y: Range<Int>) = (1 ..< 33, 33 ..< 65)
public static let byteRanges: (x: Range<Int>, y: Range<Int>) = (1..<33, 33..<65)

public struct SigningAlgorithm: ECDSASigningAlgorithm {
public static let name = "ES256"
Expand All @@ -38,18 +38,11 @@ extension P256.Signing.PublicKey: ECDSAPublicKey {
}
}

#if compiler(<6)
// TODO: Remove @unchecked Sendable when Crypto is updated to use Sendable
extension P256.Signing.PrivateKey: ECDSAPrivateKey, @unchecked Sendable {}
extension P256.Signing.ECDSASignature: ECDSASignature, @unchecked Sendable {}
extension P256.Signing.PublicKey: @unchecked Sendable {}
extension P256: @unchecked Sendable {}
#else
extension P256.Signing.PrivateKey: ECDSAPrivateKey, @unchecked @retroactive Sendable {}
extension P256.Signing.ECDSASignature: ECDSASignature, @unchecked @retroactive Sendable {}
extension P256.Signing.PublicKey: @unchecked @retroactive Sendable {}
extension P256: @unchecked @retroactive Sendable {}
#endif

public typealias ES256PublicKey = ECDSA.PublicKey<P256>
public typealias ES256PrivateKey = ECDSA.PrivateKey<P256>
Loading