Skip to content

Commit 72b50d6

Browse files
Fixed an issue where VAPID.Configuration would encode the same key twice
1 parent 239029a commit 72b50d6

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ To uninstall the generator:
111111
Once installed, a new configuration can be generated as needed:
112112
```
113113
% ~/.swiftpm/bin/vapid-key-generator https://example.com
114-
VAPID.Configuration: {"contactInformation":"https://example.com","expirationDuration":79200,"keys":["g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E="],"primaryKey":"g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E=","validityDuration":72000}
114+
VAPID.Configuration: {"contactInformation":"https://example.com","expirationDuration":79200,"primaryKey":"6PSSAJiMj7uOvtE4ymNo5GWcZbT226c5KlV6c+8fx5g=","validityDuration":72000}
115115
116116
117117
Example Usage:
118118
// TODO: Load this data from .env or from file system
119-
let configurationData = Data(#" {"contactInformation":"https://example.com","expirationDuration":79200,"keys":["g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E="],"primaryKey":"g7PXKzeMR/B+ndQWa92Dl9u22CibXJnm6vN9L6Gri1E=","validityDuration":72000} "#.utf8)
119+
let configurationData = Data(#" {"contactInformation":"https://example.com","expirationDuration":79200,"primaryKey":"6PSSAJiMj7uOvtE4ymNo5GWcZbT226c5KlV6c+8fx5g=","validityDuration":72000} "#.utf8)
120120
let vapidConfiguration = try JSONDecoder().decode(VAPID.Configuration.self, from: configurationData)
121121
```
122122

Sources/WebPush/VAPID/VAPIDConfiguration.swift

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import Foundation
1010

1111
extension VoluntaryApplicationServerIdentification {
12-
public struct Configuration: Hashable, Codable, Sendable {
12+
public struct Configuration: Hashable, Sendable {
1313
/// The VAPID key that identifies the push service to subscribers.
1414
///
1515
/// 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.
@@ -64,26 +64,6 @@ extension VoluntaryApplicationServerIdentification {
6464
self.validityDuration = validityDuration
6565
}
6666

67-
public init(from decoder: any Decoder) throws {
68-
let container = try decoder.container(keyedBy: CodingKeys.self)
69-
70-
let primaryKey = try container.decodeIfPresent(Key.self, forKey: CodingKeys.primaryKey)
71-
let keys = try container.decode(Set<Key>.self, forKey: CodingKeys.keys)
72-
let deprecatedKeys = try container.decodeIfPresent(Set<Key>.self, forKey: CodingKeys.deprecatedKeys)
73-
let contactInformation = try container.decode(ContactInformation.self, forKey: CodingKeys.contactInformation)
74-
let expirationDuration = try container.decode(Duration.self, forKey: CodingKeys.expirationDuration)
75-
let validityDuration = try container.decode(Duration.self, forKey: CodingKeys.validityDuration)
76-
77-
try self.init(
78-
primaryKey: primaryKey,
79-
keys: keys,
80-
deprecatedKeys: deprecatedKeys,
81-
contactInformation: contactInformation,
82-
expirationDuration: expirationDuration,
83-
validityDuration: validityDuration
84-
)
85-
}
86-
8767
mutating func updateKeys(
8868
primaryKey: Key?,
8969
keys: Set<Key>,
@@ -105,6 +85,57 @@ extension VoluntaryApplicationServerIdentification {
10585
}
10686
}
10787

88+
extension VAPID.Configuration: Codable {
89+
public enum CodingKeys: CodingKey {
90+
case primaryKey
91+
case keys
92+
case deprecatedKeys
93+
case contactInformation
94+
case expirationDuration
95+
case validityDuration
96+
}
97+
98+
public init(from decoder: any Decoder) throws {
99+
let container = try decoder.container(keyedBy: CodingKeys.self)
100+
101+
let primaryKey = try container.decodeIfPresent(VAPID.Key.self, forKey: CodingKeys.primaryKey)
102+
let keys = try container.decodeIfPresent(Set<VAPID.Key>.self, forKey: CodingKeys.keys) ?? []
103+
let deprecatedKeys = try container.decodeIfPresent(Set<VAPID.Key>.self, forKey: CodingKeys.deprecatedKeys)
104+
let contactInformation = try container.decode(ContactInformation.self, forKey: CodingKeys.contactInformation)
105+
let expirationDuration = try container.decode(Duration.self, forKey: CodingKeys.expirationDuration)
106+
let validityDuration = try container.decode(Duration.self, forKey: CodingKeys.validityDuration)
107+
108+
try self.init(
109+
primaryKey: primaryKey,
110+
keys: keys,
111+
deprecatedKeys: deprecatedKeys,
112+
contactInformation: contactInformation,
113+
expirationDuration: expirationDuration,
114+
validityDuration: validityDuration
115+
)
116+
}
117+
118+
public func encode(to encoder: any Encoder) throws {
119+
var container = encoder.container(keyedBy: CodingKeys.self)
120+
121+
/// Remove the primary key from the list so it's not listed twice
122+
var keys: Set<VAPID.Key>? = self.keys
123+
if let primaryKey {
124+
keys?.remove(primaryKey)
125+
}
126+
if keys?.isEmpty == true {
127+
keys = nil
128+
}
129+
130+
try container.encodeIfPresent(primaryKey, forKey: .primaryKey)
131+
try container.encodeIfPresent(keys, forKey: .keys)
132+
try container.encodeIfPresent(deprecatedKeys, forKey: .deprecatedKeys)
133+
try container.encode(contactInformation, forKey: .contactInformation)
134+
try container.encode(expirationDuration, forKey: .expirationDuration)
135+
try container.encode(validityDuration, forKey: .validityDuration)
136+
}
137+
}
138+
108139
extension VAPID.Configuration {
109140
/// The contact information for the push service.
110141
///

0 commit comments

Comments
 (0)