Skip to content

Commit

Permalink
Fixed an issue where VAPID.Configuration would encode the same key twice
Browse files Browse the repository at this point in the history
  • Loading branch information
dimitribouniol committed Dec 14, 2024
1 parent 239029a commit 72b50d6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,12 @@ To uninstall the generator:
Once installed, a new configuration can be generated as needed:
```
% ~/.swiftpm/bin/vapid-key-generator https://example.com
VAPID.Configuration: {"contactInformation":"https://example.com","expirationDuration":79200,"keys":["g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E="],"primaryKey":"g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E=","validityDuration":72000}
VAPID.Configuration: {"contactInformation":"https://example.com","expirationDuration":79200,"primaryKey":"6PSSAJiMj7uOvtE4ymNo5GWcZbT226c5KlV6c+8fx5g=","validityDuration":72000}
Example Usage:
// TODO: Load this data from .env or from file system
let configurationData = Data(#" {"contactInformation":"https://example.com","expirationDuration":79200,"keys":["g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E="],"primaryKey":"g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E=","validityDuration":72000} "#.utf8)
let configurationData = Data(#" {"contactInformation":"https://example.com","expirationDuration":79200,"primaryKey":"6PSSAJiMj7uOvtE4ymNo5GWcZbT226c5KlV6c+8fx5g=","validityDuration":72000} "#.utf8)
let vapidConfiguration = try JSONDecoder().decode(VAPID.Configuration.self, from: configurationData)
```

Expand Down
73 changes: 52 additions & 21 deletions Sources/WebPush/VAPID/VAPIDConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

extension VoluntaryApplicationServerIdentification {
public struct Configuration: Hashable, Codable, Sendable {
public struct Configuration: Hashable, Sendable {
/// The VAPID key that identifies the push service to subscribers.
///
/// This key should be shared by all instances of your push service, and should be kept secure. Rotating this key is not recommended as you'll lose access to subscribers that registered against it.
Expand Down Expand Up @@ -64,26 +64,6 @@ extension VoluntaryApplicationServerIdentification {
self.validityDuration = validityDuration
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let primaryKey = try container.decodeIfPresent(Key.self, forKey: CodingKeys.primaryKey)
let keys = try container.decode(Set<Key>.self, forKey: CodingKeys.keys)
let deprecatedKeys = try container.decodeIfPresent(Set<Key>.self, forKey: CodingKeys.deprecatedKeys)
let contactInformation = try container.decode(ContactInformation.self, forKey: CodingKeys.contactInformation)
let expirationDuration = try container.decode(Duration.self, forKey: CodingKeys.expirationDuration)
let validityDuration = try container.decode(Duration.self, forKey: CodingKeys.validityDuration)

try self.init(
primaryKey: primaryKey,
keys: keys,
deprecatedKeys: deprecatedKeys,
contactInformation: contactInformation,
expirationDuration: expirationDuration,
validityDuration: validityDuration
)
}

mutating func updateKeys(
primaryKey: Key?,
keys: Set<Key>,
Expand All @@ -105,6 +85,57 @@ extension VoluntaryApplicationServerIdentification {
}
}

extension VAPID.Configuration: Codable {
public enum CodingKeys: CodingKey {
case primaryKey
case keys
case deprecatedKeys
case contactInformation
case expirationDuration
case validityDuration
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let primaryKey = try container.decodeIfPresent(VAPID.Key.self, forKey: CodingKeys.primaryKey)
let keys = try container.decodeIfPresent(Set<VAPID.Key>.self, forKey: CodingKeys.keys) ?? []
let deprecatedKeys = try container.decodeIfPresent(Set<VAPID.Key>.self, forKey: CodingKeys.deprecatedKeys)
let contactInformation = try container.decode(ContactInformation.self, forKey: CodingKeys.contactInformation)
let expirationDuration = try container.decode(Duration.self, forKey: CodingKeys.expirationDuration)
let validityDuration = try container.decode(Duration.self, forKey: CodingKeys.validityDuration)

try self.init(
primaryKey: primaryKey,
keys: keys,
deprecatedKeys: deprecatedKeys,
contactInformation: contactInformation,
expirationDuration: expirationDuration,
validityDuration: validityDuration
)
}

public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

/// Remove the primary key from the list so it's not listed twice
var keys: Set<VAPID.Key>? = self.keys
if let primaryKey {
keys?.remove(primaryKey)
}
if keys?.isEmpty == true {
keys = nil
}

try container.encodeIfPresent(primaryKey, forKey: .primaryKey)
try container.encodeIfPresent(keys, forKey: .keys)
try container.encodeIfPresent(deprecatedKeys, forKey: .deprecatedKeys)
try container.encode(contactInformation, forKey: .contactInformation)
try container.encode(expirationDuration, forKey: .expirationDuration)
try container.encode(validityDuration, forKey: .validityDuration)
}
}

extension VAPID.Configuration {
/// The contact information for the push service.
///
Expand Down

0 comments on commit 72b50d6

Please sign in to comment.