Skip to content

Commit 453ebdb

Browse files
authored
Allow custom objectIds (#100)
* Allow custom objectIds * Let server throw missing objectId error instead of SDK * Fix date comparisons in new tests * Simplify new tests * Merge main and add missing Android * nits * prepare for release * Fix anonymous user strip bug * lower codecov patch * more codecov * Add missing user signup tests * Update .codecov.yml
1 parent fa74a7c commit 453ebdb

File tree

16 files changed

+1859
-197
lines changed

16 files changed

+1859
-197
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ coverage:
99
changes: false
1010
project:
1111
default:
12-
target: 76
12+
target: 80
1313
comment:
1414
require_changes: true

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
# Parse-Swift Changelog
22

33
### main
4-
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.1...main)
4+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.2...main)
55
* _Contributing to this repo? Add info about your change here to be included in the next release_
66

7+
8+
### 1.2.2
9+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.1...1.2.2)
10+
711
__New features__
12+
- Allow custom objectIds ([#100](https://github.com/parse-community/Parse-Swift/pull/100)), thanks to [Corey Baker](https://github.com/cbaker6).
813
- Add ParseTwitter and ParseFacebook authentication ([#97](https://github.com/parse-community/Parse-Swift/pull/97)), thanks to [Abdulaziz Alhomaidhi](https://github.com/abs8090).
14+
- Add build support for Android ([#90](https://github.com/parse-community/Parse-Swift/pull/90)), thanks to [jt9897253](https://github.com/jt9897253).
15+
16+
__Fixes__
17+
- There was another bug after a user first logs in anonymously and then becomes a real user. The authData sent to the server wasn't stripped, keep the user anonymous instead of making them a real user ([#100](https://github.com/parse-community/Parse-Swift/pull/100)), thanks to [Corey Baker](https://github.com/cbaker6).
918

1019
### 1.2.1
1120
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.0...1.2.1)

ParseSwift.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "ParseSwift"
3-
s.version = "1.2.1"
3+
s.version = "1.2.2"
44
s.summary = "Parse Pure Swift SDK"
55
s.homepage = "https://github.com/parse-community/Parse-Swift"
66
s.authors = {

ParseSwift.xcodeproj/project.pbxproj

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@
197197
70647E9D259E3A9A004C1004 /* ParseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70647E9B259E3A9A004C1004 /* ParseType.swift */; };
198198
70647E9E259E3A9A004C1004 /* ParseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70647E9B259E3A9A004C1004 /* ParseType.swift */; };
199199
70647E9F259E3A9A004C1004 /* ParseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70647E9B259E3A9A004C1004 /* ParseType.swift */; };
200+
70732C5A2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectId.swift */; };
201+
70732C5B2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectId.swift */; };
202+
70732C5C2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectId.swift */; };
200203
707A3BF125B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
201204
707A3BF225B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
202205
707A3BF325B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
@@ -599,6 +602,7 @@
599602
705D950725BE4C08003EF6F8 /* SubscriptionCallback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionCallback.swift; sourceTree = "<group>"; };
600603
70647E8D259E3375004C1004 /* LocallyIdentifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocallyIdentifiable.swift; sourceTree = "<group>"; };
601604
70647E9B259E3A9A004C1004 /* ParseType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseType.swift; sourceTree = "<group>"; };
605+
70732C592606CCAD000CAB81 /* ParseObjectCustomObjectId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseObjectCustomObjectId.swift; sourceTree = "<group>"; };
602606
707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAuthentication.swift; sourceTree = "<group>"; };
603607
707A3C1025B0A8E8000D215C /* ParseAnonymous.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAnonymous.swift; sourceTree = "<group>"; };
604608
707A3C1F25B14BCF000D215C /* ParseApple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseApple.swift; sourceTree = "<group>"; };
@@ -830,6 +834,7 @@
830834
7003963A25A288100052CB31 /* ParseLiveQueryTests.swift */,
831835
70C7DC2024D20F190050419B /* ParseObjectBatchTests.swift */,
832836
7044C1DE25C5C70D0011F6E7 /* ParseObjectCombine.swift */,
837+
70732C592606CCAD000CAB81 /* ParseObjectCustomObjectId.swift */,
833838
911DB13524C4FC100027F3C7 /* ParseObjectTests.swift */,
834839
7044C1EB25C5CC930011F6E7 /* ParseOperationCombineTests.swift */,
835840
70C5508425B4A68700B5DBC2 /* ParseOperationTests.swift */,
@@ -1660,6 +1665,7 @@
16601665
89899D772603CF66002E2043 /* ParseFacebookTests.swift in Sources */,
16611666
70386A4625D99C8B0048EC1B /* ParseLDAPTests.swift in Sources */,
16621667
911DB12E24C4837E0027F3C7 /* APICommandTests.swift in Sources */,
1668+
70732C5A2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */,
16631669
911DB12C24C3F7720027F3C7 /* MockURLResponse.swift in Sources */,
16641670
7044C24325C5EA360011F6E7 /* ParseAppleCombineTests.swift in Sources */,
16651671
7044C1DF25C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */,
@@ -1810,6 +1816,7 @@
18101816
89899D822603CF67002E2043 /* ParseFacebookTests.swift in Sources */,
18111817
70386A4825D99C8B0048EC1B /* ParseLDAPTests.swift in Sources */,
18121818
709B984C2556ECAA00507778 /* APICommandTests.swift in Sources */,
1819+
70732C5C2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */,
18131820
709B984D2556ECAA00507778 /* AnyDecodableTests.swift in Sources */,
18141821
7044C24525C5EA360011F6E7 /* ParseAppleCombineTests.swift in Sources */,
18151822
7044C1E125C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */,
@@ -1863,6 +1870,7 @@
18631870
89899D812603CF67002E2043 /* ParseFacebookTests.swift in Sources */,
18641871
70386A4725D99C8B0048EC1B /* ParseLDAPTests.swift in Sources */,
18651872
70F2E2B5254F283000B2EA5C /* ParseEncoderTests.swift in Sources */,
1873+
70732C5B2606CCAD000CAB81 /* ParseObjectCustomObjectId.swift in Sources */,
18661874
70F2E2C2254F283000B2EA5C /* APICommandTests.swift in Sources */,
18671875
7044C24425C5EA360011F6E7 /* ParseAppleCombineTests.swift in Sources */,
18681876
7044C1E025C5C70D0011F6E7 /* ParseObjectCombine.swift in Sources */,
@@ -2313,7 +2321,7 @@
23132321
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
23142322
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
23152323
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2316-
MARKETING_VERSION = 1.2.1;
2324+
MARKETING_VERSION = 1.2.2;
23172325
PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift;
23182326
PRODUCT_NAME = ParseSwift;
23192327
SKIP_INSTALL = YES;
@@ -2337,7 +2345,7 @@
23372345
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
23382346
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
23392347
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2340-
MARKETING_VERSION = 1.2.1;
2348+
MARKETING_VERSION = 1.2.2;
23412349
PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift;
23422350
PRODUCT_NAME = ParseSwift;
23432351
SKIP_INSTALL = YES;
@@ -2403,7 +2411,7 @@
24032411
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
24042412
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
24052413
MACOSX_DEPLOYMENT_TARGET = 10.13;
2406-
MARKETING_VERSION = 1.2.1;
2414+
MARKETING_VERSION = 1.2.2;
24072415
PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift;
24082416
PRODUCT_NAME = ParseSwift;
24092417
SDKROOT = macosx;
@@ -2429,7 +2437,7 @@
24292437
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
24302438
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
24312439
MACOSX_DEPLOYMENT_TARGET = 10.13;
2432-
MARKETING_VERSION = 1.2.1;
2440+
MARKETING_VERSION = 1.2.2;
24332441
PRODUCT_BUNDLE_IDENTIFIER = com.parse.ParseSwift;
24342442
PRODUCT_NAME = ParseSwift;
24352443
SDKROOT = macosx;
@@ -2576,7 +2584,7 @@
25762584
INFOPLIST_FILE = "ParseSwift-watchOS/Info.plist";
25772585
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
25782586
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2579-
MARKETING_VERSION = 1.2.1;
2587+
MARKETING_VERSION = 1.2.2;
25802588
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
25812589
MTL_FAST_MATH = YES;
25822590
PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-watchOS";
@@ -2605,7 +2613,7 @@
26052613
INFOPLIST_FILE = "ParseSwift-watchOS/Info.plist";
26062614
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
26072615
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2608-
MARKETING_VERSION = 1.2.1;
2616+
MARKETING_VERSION = 1.2.2;
26092617
MTL_FAST_MATH = YES;
26102618
PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-watchOS";
26112619
PRODUCT_NAME = ParseSwift;
@@ -2632,7 +2640,7 @@
26322640
INFOPLIST_FILE = "ParseSwift-tvOS/Info.plist";
26332641
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
26342642
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2635-
MARKETING_VERSION = 1.2.1;
2643+
MARKETING_VERSION = 1.2.2;
26362644
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
26372645
MTL_FAST_MATH = YES;
26382646
PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-tvOS";
@@ -2660,7 +2668,7 @@
26602668
INFOPLIST_FILE = "ParseSwift-tvOS/Info.plist";
26612669
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
26622670
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
2663-
MARKETING_VERSION = 1.2.1;
2671+
MARKETING_VERSION = 1.2.2;
26642672
MTL_FAST_MATH = YES;
26652673
PRODUCT_BUNDLE_IDENTIFIER = "com.parse.ParseSwift-tvOS";
26662674
PRODUCT_NAME = ParseSwift;

Scripts/jazzy.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ bundle exec jazzy \
55
--author_url http://parseplatform.org \
66
--github_url https://github.com/parse-community/Parse-Swift \
77
--root-url http://parseplatform.org/Parse-Swift/api/ \
8-
--module-version 1.2.1 \
8+
--module-version 1.2.2 \
99
--theme fullwidth \
1010
--skip-undocumented \
1111
--output ./docs/api \

Sources/ParseSwift/Authentication/Protocols/ParseAuthentication.swift

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,12 @@ public extension ParseUser {
217217
static func login(_ type: String,
218218
authData: [String: String],
219219
options: API.Options) throws -> Self {
220-
let body = SignupLoginBody(authData: [type: authData])
221-
return try signupCommand(body: body).execute(options: options)
220+
if Self.current != nil {
221+
return try Self.link(type, authData: authData, options: options)
222+
} else {
223+
let body = SignupLoginBody(authData: [type: authData])
224+
return try signupCommand(body: body).execute(options: options)
225+
}
222226
}
223227

224228
/**
@@ -238,22 +242,28 @@ public extension ParseUser {
238242
options: API.Options,
239243
callbackQueue: DispatchQueue = .main,
240244
completion: @escaping (Result<Self, ParseError>) -> Void) {
241-
242-
let body = SignupLoginBody(authData: [type: authData])
243-
do {
244-
try signupCommand(body: body)
245-
.executeAsync(options: options) { result in
246-
callbackQueue.async {
247-
completion(result)
245+
if Self.current != nil {
246+
Self.link(type, authData: authData,
247+
options: options,
248+
callbackQueue: callbackQueue,
249+
completion: completion)
250+
} else {
251+
let body = SignupLoginBody(authData: [type: authData])
252+
do {
253+
try signupCommand(body: body)
254+
.executeAsync(options: options) { result in
255+
callbackQueue.async {
256+
completion(result)
257+
}
258+
}
259+
} catch {
260+
callbackQueue.async {
261+
if let parseError = error as? ParseError {
262+
completion(.failure(parseError))
263+
} else {
264+
let parseError = ParseError(code: .unknownError, message: error.localizedDescription)
265+
completion(.failure(parseError))
248266
}
249-
}
250-
} catch {
251-
callbackQueue.async {
252-
if let parseError = error as? ParseError {
253-
completion(.failure(parseError))
254-
} else {
255-
let parseError = ParseError(code: .unknownError, message: error.localizedDescription)
256-
completion(.failure(parseError))
257267
}
258268
}
259269
}
@@ -384,29 +394,47 @@ public extension ParseUser {
384394
}
385395
}
386396

397+
internal func linkCommand() -> API.NonParseBodyCommand<Self, Self> {
398+
Self.current?.anonymous.strip()
399+
return API.NonParseBodyCommand<Self, Self>(method: .PUT,
400+
path: endpoint,
401+
body: Self.current) { (data) -> Self in
402+
let user = try ParseCoding.jsonDecoder().decode(UpdateSessionTokenResponse.self, from: data)
403+
Self.current?.updatedAt = user.updatedAt
404+
guard let current = Self.current else {
405+
throw ParseError(code: .unknownError, message: "Should have a current user.")
406+
}
407+
Self.currentUserContainer = .init(currentUser: current,
408+
sessionToken: user.sessionToken)
409+
Self.saveCurrentContainerToKeychain()
410+
return current
411+
}
412+
}
413+
387414
internal func linkCommand(body: SignupLoginBody) -> API.NonParseBodyCommand<SignupLoginBody, Self> {
415+
var body = body
416+
Self.current?.anonymous.strip()
417+
if var currentAuthData = Self.current?.authData {
418+
if let bodyAuthData = body.authData {
419+
bodyAuthData.forEach { (key, value) in
420+
currentAuthData[key] = value
421+
}
422+
}
423+
body.authData = currentAuthData
424+
}
388425

389426
return API.NonParseBodyCommand<SignupLoginBody, Self>(method: .PUT,
390427
path: endpoint,
391428
body: body) { (data) -> Self in
392-
let user = try ParseCoding.jsonDecoder().decode(Self.self, from: data)
393-
if let authData = body.authData {
394-
Self.current?.anonymous.strip()
395-
if Self.current?.authData == nil {
396-
Self.current?.authData = authData
397-
} else {
398-
authData.forEach { (key, value) in
399-
Self.current?.authData?[key] = value
400-
}
401-
}
402-
if let updatedAt = user.updatedAt {
403-
Self.current?.updatedAt = updatedAt
404-
}
405-
}
406-
Self.saveCurrentContainerToKeychain()
429+
let user = try ParseCoding.jsonDecoder().decode(UpdateSessionTokenResponse.self, from: data)
430+
Self.current?.updatedAt = user.updatedAt
431+
Self.current?.authData = body.authData
407432
guard let current = Self.current else {
408433
throw ParseError(code: .unknownError, message: "Should have a current user.")
409434
}
435+
Self.currentUserContainer = .init(currentUser: current,
436+
sessionToken: user.sessionToken)
437+
Self.saveCurrentContainerToKeychain()
410438
return current
411439
}
412440
}

Sources/ParseSwift/Coding/ParseEncoder.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,16 @@ public struct ParseEncoder {
5656
case object
5757
case cloud
5858
case none
59+
case customObjectId
5960
case custom(Set<String>)
6061

6162
func keys() -> Set<String> {
6263
switch self {
6364

6465
case .object:
6566
return Set(["createdAt", "updatedAt", "objectId", "className"])
67+
case .customObjectId:
68+
return Set(["createdAt", "updatedAt", "className"])
6669
case .cloud:
6770
return Set(["functionJobName"])
6871
case .none:
@@ -99,7 +102,13 @@ public struct ParseEncoder {
99102
internal func encode<T: ParseObject>(_ value: T,
100103
objectsSavedBeforeThisOne: [String: PointerType]?,
101104
filesSavedBeforeThisOne: [UUID: ParseFile]?) throws -> (encoded: Data, unique: Set<UniqueObject>, unsavedChildren: [Encodable]) {
102-
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: SkippedKeys.object.keys())
105+
let keysToSkip: Set<String>!
106+
if !ParseConfiguration.allowCustomObjectId {
107+
keysToSkip = SkippedKeys.object.keys()
108+
} else {
109+
keysToSkip = SkippedKeys.customObjectId.keys()
110+
}
111+
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: keysToSkip)
103112
if let dateEncodingStrategy = dateEncodingStrategy {
104113
encoder.dateEncodingStrategy = dateEncodingStrategy
105114
}
@@ -110,7 +119,13 @@ public struct ParseEncoder {
110119
internal func encode(_ value: ParseType, collectChildren: Bool,
111120
objectsSavedBeforeThisOne: [String: PointerType]?,
112121
filesSavedBeforeThisOne: [UUID: ParseFile]?) throws -> (encoded: Data, unique: Set<UniqueObject>, unsavedChildren: [Encodable]) {
113-
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: SkippedKeys.object.keys())
122+
let keysToSkip: Set<String>!
123+
if !ParseConfiguration.allowCustomObjectId {
124+
keysToSkip = SkippedKeys.object.keys()
125+
} else {
126+
keysToSkip = SkippedKeys.customObjectId.keys()
127+
}
128+
let encoder = _ParseEncoder(codingPath: [], dictionary: NSMutableDictionary(), skippingKeys: keysToSkip)
114129
if let dateEncodingStrategy = dateEncodingStrategy {
115130
encoder.dateEncodingStrategy = dateEncodingStrategy
116131
}

0 commit comments

Comments
 (0)