Skip to content

Commit dc037bd

Browse files
authored
fix: Update to user password should persist new sessionToken to Keychain (#147)
* fix: Update to user password should persist new sessionToken to Keychain * update sessionToken on merge and non-merged users
1 parent 32a96a4 commit dc037bd

31 files changed

+611
-330
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.8.2...5.9.0), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.9.0/documentation/parseswift)
1010

1111
__New features__
12+
* Cocoapods now defaults to Swift 5.9 ([#146](https://github.com/netreconlab/Parse-Swift/pull/146)), thanks to [Corey Baker](https://github.com/cbaker6).
1213
* Add support for visionOS ([#143](https://github.com/netreconlab/Parse-Swift/pull/143)), thanks to [Corey Baker](https://github.com/cbaker6).
1314
* Add fetchAll method to array of Parse Pointer Object's ([#141](https://github.com/netreconlab/Parse-Swift/pull/141)), thanks to [Corey Baker](https://github.com/cbaker6).
1415

16+
__Fixes__
17+
* Updates to ParseUser password now persist the updated sessionToken from the server to the client Keychain ([#147](https://github.com/netreconlab/Parse-Swift/pull/147)), thanks to [Corey Baker](https://github.com/cbaker6).
18+
1519
### 5.8.2
1620
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.8.1...5.8.2), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.8.2/documentation/parseswift)
1721

Sources/ParseSwift/API/Responses.swift

Lines changed: 94 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,93 @@ struct CreateResponse: Decodable {
1414
var updatedAt: Date {
1515
return createdAt
1616
}
17+
var sessionToken: String?
1718

18-
func apply<T>(to object: T) -> T where T: ParseObject {
19+
func setResponseProperties<T>(on object: T) -> T where T: ParseObject {
1920
var object = object
2021
object.objectId = objectId
2122
object.createdAt = createdAt
2223
object.updatedAt = updatedAt
2324
return object
2425
}
26+
27+
func apply<T>(to object: T) -> T where T: ParseObject {
28+
setResponseProperties(on: object)
29+
}
30+
31+
func apply<T>(to user: T) -> T where T: ParseUser {
32+
var user = setResponseProperties(on: user)
33+
user.password = nil
34+
return user
35+
}
36+
2537
}
2638

2739
struct ReplaceResponse: Decodable {
2840
var createdAt: Date?
2941
var updatedAt: Date?
42+
var sessionToken: String?
3043

31-
func apply<T>(to object: T) throws -> T where T: ParseObject {
44+
func setResponseProperties<T>(on object: T) throws -> T where T: ParseObject {
3245
guard let objectId = object.objectId else {
33-
throw ParseError(code: .missingObjectId,
34-
message: "Response from server should not have an objectId of nil")
46+
throw ParseError(
47+
code: .missingObjectId,
48+
message: "Response from server should not have an objectId of nil"
49+
)
3550
}
3651
guard let createdAt = createdAt else {
3752
guard let updatedAt = updatedAt else {
38-
throw ParseError(code: .otherCause,
39-
message: "Response from server should not have an updatedAt of nil")
53+
throw ParseError(
54+
code: .otherCause,
55+
message: "Response from server should not have an updatedAt of nil"
56+
)
4057
}
41-
return UpdateResponse(updatedAt: updatedAt).apply(to: object)
58+
let response = UpdateResponse(
59+
updatedAt: updatedAt,
60+
sessionToken: sessionToken
61+
).apply(to: object)
62+
63+
return response
4264
}
43-
return CreateResponse(objectId: objectId,
44-
createdAt: createdAt).apply(to: object)
65+
let response = CreateResponse(
66+
objectId: objectId,
67+
createdAt: createdAt,
68+
sessionToken: sessionToken
69+
).apply(to: object)
70+
71+
return response
72+
}
73+
74+
func apply<T>(to object: T) throws -> T where T: ParseObject {
75+
try setResponseProperties(on: object)
76+
}
77+
78+
func apply<T>(to user: T) throws -> T where T: ParseUser {
79+
var user = try setResponseProperties(on: user)
80+
user.password = nil // password should be removed
81+
return user
4582
}
4683
}
4784

4885
struct UpdateResponse: Decodable {
4986
var updatedAt: Date
87+
var sessionToken: String?
5088

51-
func apply<T>(to object: T) -> T where T: ParseObject {
89+
func setResponseProperties<T>(on object: T) -> T where T: ParseObject {
5290
var object = object
5391
object.updatedAt = updatedAt
5492
return object
5593
}
56-
}
5794

58-
struct UpdateSessionTokenResponse: Decodable {
59-
var updatedAt: Date
60-
let sessionToken: String?
95+
func apply<T>(to object: T) -> T where T: ParseObject {
96+
setResponseProperties(on: object)
97+
}
98+
99+
func apply<T>(to user: T) -> T where T: ParseUser {
100+
var user = setResponseProperties(on: user)
101+
user.password = nil // password should be removed
102+
return user
103+
}
61104
}
62105

63106
// MARK: ParseObject Batch
@@ -70,29 +113,50 @@ struct BatchResponse: Codable {
70113
var objectId: String?
71114
var createdAt: Date?
72115
var updatedAt: Date?
116+
var sessionToken: String?
73117

74118
func asCreateResponse() throws -> CreateResponse {
75119
guard let objectId = objectId else {
76-
throw ParseError(code: .missingObjectId,
77-
message: "Response from server should not have an objectId of nil")
120+
throw ParseError(
121+
code: .missingObjectId,
122+
message: "Response from server should not have an objectId of nil"
123+
)
78124
}
79125
guard let createdAt = createdAt else {
80-
throw ParseError(code: .otherCause,
81-
message: "Response from server should not have an createdAt of nil")
126+
throw ParseError(
127+
code: .otherCause,
128+
message: "Response from server should not have an createdAt of nil"
129+
)
82130
}
83-
return CreateResponse(objectId: objectId, createdAt: createdAt)
131+
132+
let response = CreateResponse(
133+
objectId: objectId,
134+
createdAt: createdAt, sessionToken: sessionToken
135+
)
136+
137+
return response
84138
}
85139

86140
func asReplaceResponse() -> ReplaceResponse {
87-
ReplaceResponse(createdAt: createdAt, updatedAt: updatedAt)
141+
ReplaceResponse(
142+
createdAt: createdAt,
143+
updatedAt: updatedAt,
144+
sessionToken: sessionToken
145+
)
88146
}
89147

90148
func asUpdateResponse() throws -> UpdateResponse {
91149
guard let updatedAt = updatedAt else {
92-
throw ParseError(code: .otherCause,
93-
message: "Response from server should not have an updatedAt of nil")
150+
throw ParseError(
151+
code: .otherCause,
152+
message: "Response from server should not have an updatedAt of nil"
153+
)
94154
}
95-
return UpdateResponse(updatedAt: updatedAt)
155+
let response = UpdateResponse(
156+
updatedAt: updatedAt,
157+
sessionToken: sessionToken
158+
)
159+
return response
96160
}
97161

98162
func apply<T>(to object: T, method: API.Method) throws -> T where T: ParseObject {
@@ -125,14 +189,14 @@ struct LoginSignupResponse: Codable {
125189
var updatedAt: Date?
126190
let username: String?
127191

128-
func applySignup<T>(to object: T) -> T where T: ParseUser {
129-
var object = object
130-
object.objectId = objectId
131-
object.createdAt = createdAt
132-
object.updatedAt = createdAt
133-
object.password = nil // password should be removed
192+
func apply<T>(to user: T) -> T where T: ParseUser {
193+
var user = user
194+
user.objectId = objectId
195+
user.createdAt = createdAt
196+
user.updatedAt = updatedAt ?? createdAt
197+
user.password = nil // password should be removed
134198

135-
return object
199+
return user
136200
}
137201
}
138202

Sources/ParseSwift/Authentication/Protocols/ParseAuthentication.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ public extension ParseUser {
407407
return API.Command<Self, Self>(method: .PUT,
408408
path: endpoint,
409409
body: mutableSelf) { (data) -> Self in
410-
let user = try ParseCoding.jsonDecoder().decode(UpdateSessionTokenResponse.self, from: data)
411-
mutableSelf.updatedAt = user.updatedAt
410+
let user = try ParseCoding.jsonDecoder().decode(UpdateResponse.self, from: data)
411+
mutableSelf = user.apply(to: mutableSelf)
412412
if let sessionToken = user.sessionToken {
413413
await Self.setCurrentContainer(.init(currentUser: mutableSelf,
414414
sessionToken: sessionToken))
@@ -434,9 +434,8 @@ public extension ParseUser {
434434
return API.Command<SignupLoginBody, Self>(method: .PUT,
435435
path: endpoint,
436436
body: body) { (data) -> Self in
437-
let user = try ParseCoding.jsonDecoder().decode(UpdateSessionTokenResponse.self, from: data)
438-
var currentUser = currentStrippedUser
439-
currentUser.updatedAt = user.updatedAt
437+
let user = try ParseCoding.jsonDecoder().decode(UpdateResponse.self, from: data)
438+
var currentUser = user.apply(to: currentStrippedUser)
440439
currentUser.authData = body.authData
441440
if let sessionToken = user.sessionToken {
442441
await Self.setCurrentContainer(.init(currentUser: currentUser,

Sources/ParseSwift/Objects/ParseUser+async.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,9 @@ internal extension ParseUser {
570570
let command: API.Command<Self, Self>!
571571
switch method {
572572
case .save:
573-
command = try await self.saveCommand(ignoringCustomObjectIdConfig: ignoringCustomObjectIdConfig)
573+
command = try await self.saveCommand(
574+
ignoringCustomObjectIdConfig: ignoringCustomObjectIdConfig
575+
)
574576
case .create:
575577
command = try await self.createCommand()
576578
case .replace:

0 commit comments

Comments
 (0)