Skip to content

Commit 6e81c2f

Browse files
authored
fix: All object endpoints need to be public (#80)
* fix: All object endpoints need to be public * add public endpoint tests * add changelog
1 parent abd413f commit 6e81c2f

File tree

8 files changed

+157
-26
lines changed

8 files changed

+157
-26
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
__New features__
1212
* Add ParseUser.loginAs(objectId: String) method to allow impersonating a user. This method requires the server primaryKey and is intended to run server-side ([#79](https://github.com/netreconlab/Parse-Swift/pull/79)), thanks to [Corey Baker](https://github.com/cbaker6).
1313

14+
__Fixes__
15+
* Fix ParseUser.become(), ParseUser.linkCommand, and other calls that depend on a specific endpoint for specialized ParseObjects such as ParseUser, ParseInstallation, ParseRole, etc. ([#80](https://github.com/netreconlab/Parse-Swift/pull/80)), thanks to [Corey Baker](https://github.com/cbaker6).
16+
1417
### 5.2.0
1518
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.1.1...5.2.0), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.2.0/documentation/parseswift)
1619

ParseSwift.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@
462462
70732C5A2606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift */; };
463463
70732C5B2606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift */; };
464464
70732C5C2606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70732C592606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift */; };
465+
7073842B29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7073842A29C2910E00E21055 /* ObjectEndpointTests.swift */; };
466+
7073842C29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7073842A29C2910E00E21055 /* ObjectEndpointTests.swift */; };
467+
7073842D29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7073842A29C2910E00E21055 /* ObjectEndpointTests.swift */; };
465468
707A3BF125B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
466469
707A3BF225B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
467470
707A3BF325B0A4F0000D215C /* ParseAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */; };
@@ -1308,6 +1311,7 @@
13081311
706436A827341FD0007C6461 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
13091312
70647E9B259E3A9A004C1004 /* ParseEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseEncodable.swift; sourceTree = "<group>"; };
13101313
70732C592606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseObjectCustomObjectIdTests.swift; sourceTree = "<group>"; };
1314+
7073842A29C2910E00E21055 /* ObjectEndpointTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectEndpointTests.swift; sourceTree = "<group>"; };
13111315
707A3BF025B0A4F0000D215C /* ParseAuthentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAuthentication.swift; sourceTree = "<group>"; };
13121316
707A3C1025B0A8E8000D215C /* ParseAnonymous.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAnonymous.swift; sourceTree = "<group>"; };
13131317
707A3C1F25B14BCF000D215C /* ParseApple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseApple.swift; sourceTree = "<group>"; };
@@ -1625,6 +1629,7 @@
16251629
4AA8076E1F794C1C008CD551 /* KeychainStoreTests.swift */,
16261630
70D41D6A28B294C100613510 /* MigrateObjCSDKCombineTests.swift */,
16271631
70D41D6628B0235100613510 /* MigrateObjCSDKTests.swift */,
1632+
7073842A29C2910E00E21055 /* ObjectEndpointTests.swift */,
16281633
9194657724F16E330070296B /* ParseACLTests.swift */,
16291634
917BA4292703E03F00F8D747 /* ParseAnalyticsAsyncTests.swift */,
16301635
91CB9536265966DF0043E5D6 /* ParseAnalyticsCombineTests.swift */,
@@ -2973,6 +2978,7 @@
29732978
70C7DC2224D20F190050419B /* ParseObjectBatchTests.swift in Sources */,
29742979
7044C1BB25C52E410011F6E7 /* ParseInstallationCombineTests.swift in Sources */,
29752980
917BA45A2703FD2200F8D747 /* ParseAuthenticationAsyncTests.swift in Sources */,
2981+
7073842B29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */,
29762982
7FFF552F2217E72A007C3B4E /* AnyCodableTests.swift in Sources */,
29772983
70212D2D2855266400386163 /* ParsePushAsyncTests.swift in Sources */,
29782984
70F03A5E2780EAC700E5AFB4 /* ParseGitHubTests.swift in Sources */,
@@ -3299,6 +3305,7 @@
32993305
709B984E2556ECAA00507778 /* ParseGeoPointTests.swift in Sources */,
33003306
7044C1BD25C52E410011F6E7 /* ParseInstallationCombineTests.swift in Sources */,
33013307
917BA45C2703FD2200F8D747 /* ParseAuthenticationAsyncTests.swift in Sources */,
3308+
7073842D29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */,
33023309
709B984B2556ECAA00507778 /* MockURLProtocol.swift in Sources */,
33033310
70212D352855266600386163 /* ParsePushAsyncTests.swift in Sources */,
33043311
70F03A602780EAC700E5AFB4 /* ParseGitHubTests.swift in Sources */,
@@ -3418,6 +3425,7 @@
34183425
70F2E2C0254F283000B2EA5C /* MockURLResponse.swift in Sources */,
34193426
7044C1BC25C52E410011F6E7 /* ParseInstallationCombineTests.swift in Sources */,
34203427
917BA45B2703FD2200F8D747 /* ParseAuthenticationAsyncTests.swift in Sources */,
3428+
7073842C29C2910E00E21055 /* ObjectEndpointTests.swift in Sources */,
34213429
70F2E2BE254F283000B2EA5C /* ParseObjectBatchTests.swift in Sources */,
34223430
70212D312855266500386163 /* ParsePushAsyncTests.swift in Sources */,
34233431
70F03A5F2780EAC700E5AFB4 /* ParseGitHubTests.swift in Sources */,

Sources/ParseSwift/API/API.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public struct API {
5555
case hookTrigger(request: TriggerRequest)
5656
case any(String)
5757

58-
var urlComponent: String {
58+
public var urlComponent: String {
5959
switch self {
6060
case .batch:
6161
return "/batch"

Sources/ParseSwift/Objects/ParseInstallation.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ public extension ParseInstallation {
9595
"_Installation"
9696
}
9797

98+
var endpoint: API.Endpoint {
99+
if let objectId = objectId {
100+
return .installation(objectId: objectId)
101+
}
102+
return .installations
103+
}
104+
98105
// swiftlint:disable:next cyclomatic_complexity function_body_length
99106
func mergeParse(with object: Self) throws -> Self {
100107
guard hasSameObjectId(as: object) else {
@@ -164,13 +171,6 @@ public extension ParseInstallation {
164171

165172
// MARK: Convenience
166173
extension ParseInstallation {
167-
var endpoint: API.Endpoint {
168-
if let objectId = objectId {
169-
return .installation(objectId: objectId)
170-
}
171-
172-
return .installations
173-
}
174174

175175
func endpoint(_ method: API.Method) -> API.Endpoint {
176176
if !Parse.configuration.isRequiringCustomObjectIds || method != .POST {

Sources/ParseSwift/Objects/ParseRole.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ public extension ParseRole {
7676
"_Role"
7777
}
7878

79+
var endpoint: API.Endpoint {
80+
if let objectId = objectId {
81+
return .role(objectId: objectId)
82+
}
83+
return .roles
84+
}
85+
7986
var users: ParseRelation<Self>? {
8087
try? ParseRelation(parent: self, key: "users", className: RoleUser.className)
8188
}
@@ -130,12 +137,6 @@ public extension ParseRole {
130137

131138
// MARK: Convenience
132139
extension ParseRole {
133-
var endpoint: API.Endpoint {
134-
if let objectId = objectId {
135-
return .role(objectId: objectId)
136-
}
137-
return .roles
138-
}
139140

140141
static func checkName(_ name: String) throws {
141142
// swiftlint:disable:next line_length

Sources/ParseSwift/Objects/ParseSession.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ public extension ParseSession {
4343
static var className: String {
4444
"_Session"
4545
}
46-
}
4746

48-
// MARK: Convenience
49-
extension ParseSession {
5047
var endpoint: API.Endpoint {
5148
if let objectId = objectId {
5249
return .session(objectId: objectId)

Sources/ParseSwift/Objects/ParseUser.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ public extension ParseUser {
4444
"_User"
4545
}
4646

47+
var endpoint: API.Endpoint {
48+
if let objectId = objectId {
49+
return .user(objectId: objectId)
50+
}
51+
return .users
52+
}
53+
4754
func mergeParse(with object: Self) throws -> Self {
4855
guard hasSameObjectId(as: object) else {
4956
throw ParseError(code: .otherCause,
@@ -94,13 +101,6 @@ public extension ParseUser {
94101

95102
// MARK: Convenience
96103
extension ParseUser {
97-
var endpoint: API.Endpoint {
98-
if let objectId = objectId {
99-
return .user(objectId: objectId)
100-
}
101-
102-
return .users
103-
}
104104

105105
func endpoint(_ method: API.Method) -> API.Endpoint {
106106
if !Parse.configuration.isRequiringCustomObjectIds || method != .POST {
@@ -445,9 +445,8 @@ extension ParseUser {
445445
#endif
446446

447447
internal func meCommand(sessionToken: String) throws -> API.Command<Self, Self> {
448-
// BAKER: path endpoint isn't working here for some reason
449448
return API.Command(method: .GET,
450-
path: .user(objectId: "me")) { (data) async throws -> Self in
449+
path: endpoint) { (data) async throws -> Self in
451450
let user = try ParseCoding.jsonDecoder().decode(Self.self, from: data)
452451

453452
if let current = try? await Self.current() {
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//
2+
// ObjectEndpointTests.swift
3+
// ParseSwift
4+
//
5+
// Created by Corey Baker on 3/15/23.
6+
// Copyright © 2023 Network Reconnaissance Lab. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import XCTest
11+
import ParseSwift
12+
13+
class ObjectEndpointTests: XCTestCase {
14+
struct User: ParseUser {
15+
16+
//: These are required by ParseObject
17+
var objectId: String?
18+
var createdAt: Date?
19+
var updatedAt: Date?
20+
var ACL: ParseACL?
21+
var originalData: Data?
22+
23+
// These are required by ParseUser
24+
var username: String?
25+
var email: String?
26+
var emailVerified: Bool?
27+
var password: String?
28+
var authData: [String: [String: String]?]?
29+
30+
// Your custom keys
31+
var customKey: String?
32+
}
33+
34+
struct Installation: ParseInstallation {
35+
var installationId: String?
36+
var deviceType: String?
37+
var deviceToken: String?
38+
var badge: Int?
39+
var timeZone: String?
40+
var channels: [String]?
41+
var appName: String?
42+
var appIdentifier: String?
43+
var appVersion: String?
44+
var parseVersion: String?
45+
var localeIdentifier: String?
46+
var objectId: String?
47+
var createdAt: Date?
48+
var updatedAt: Date?
49+
var ACL: ParseACL?
50+
var originalData: Data?
51+
var customKey: String?
52+
}
53+
54+
struct Session<SessionUser: ParseUser>: ParseSession {
55+
56+
var sessionToken: String
57+
var user: User
58+
var restricted: Bool?
59+
var createdWith: [String: String]
60+
var installationId: String
61+
var expiresAt: Date
62+
var originalData: Data?
63+
64+
var objectId: String?
65+
var createdAt: Date?
66+
var updatedAt: Date?
67+
var ACL: ParseACL?
68+
69+
init() {
70+
sessionToken = "hello"
71+
user = User()
72+
restricted = false
73+
createdWith = ["yolo": "yaw"]
74+
installationId = "yes"
75+
expiresAt = Date()
76+
}
77+
}
78+
79+
struct Role<RoleUser: ParseUser>: ParseRole {
80+
81+
// required by ParseObject
82+
var objectId: String?
83+
var createdAt: Date?
84+
var updatedAt: Date?
85+
var ACL: ParseACL?
86+
var originalData: Data?
87+
88+
// provided by Role
89+
var name: String?
90+
}
91+
92+
func testUser() async throws {
93+
let objectId = "yarr"
94+
var user = User()
95+
96+
XCTAssertEqual(user.endpoint.urlComponent, "/users")
97+
user.objectId = objectId
98+
XCTAssertEqual(user.endpoint.urlComponent, "/users/\(objectId)")
99+
}
100+
101+
func testInstallation() async throws {
102+
let objectId = "yarr"
103+
var installation = Installation()
104+
105+
XCTAssertEqual(installation.endpoint.urlComponent, "/installations")
106+
installation.objectId = objectId
107+
XCTAssertEqual(installation.endpoint.urlComponent, "/installations/\(objectId)")
108+
}
109+
110+
func testSession() throws {
111+
var session = Session<User>()
112+
XCTAssertEqual(session.endpoint.urlComponent, "/sessions")
113+
session.objectId = "me"
114+
XCTAssertEqual(session.endpoint.urlComponent, "/sessions/me")
115+
}
116+
117+
func testRole() throws {
118+
var role = try Role<User>(name: "Administrator")
119+
XCTAssertEqual(role.endpoint.urlComponent, "/roles")
120+
role.objectId = "me"
121+
XCTAssertEqual(role.endpoint.urlComponent, "/roles/me")
122+
}
123+
}

0 commit comments

Comments
 (0)