Skip to content

Commit ae88e8e

Browse files
committed
add userField to CLP
1 parent cd9bbd0 commit ae88e8e

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

ParseSwift.playground/Pages/20 - Schema.xcplaygroundpage/Contents.swift

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ struct GameScore2: ParseObject {
4848

4949
//: Your own properties.
5050
var points: Int?
51+
var level: Int?
5152
var data: ParseBytes?
5253
var owner: User?
54+
var rivals: [User]?
5355

5456
//: Implement your own version of merge
5557
func merge(with object: Self) throws -> Self {
@@ -58,6 +60,10 @@ struct GameScore2: ParseObject {
5860
original: object) {
5961
updated.points = object.points
6062
}
63+
if updated.shouldRestoreKey(\.level,
64+
original: object) {
65+
updated.level = object.level
66+
}
6167
if updated.shouldRestoreKey(\.data,
6268
original: object) {
6369
updated.data = object.data
@@ -66,6 +72,10 @@ struct GameScore2: ParseObject {
6672
original: object) {
6773
updated.owner = object.owner
6874
}
75+
if updated.shouldRestoreKey(\.rivals,
76+
original: object) {
77+
updated.rivals = object.rivals
78+
}
6979
return updated
7080
}
7181
}
@@ -93,14 +103,21 @@ var gameScoreSchema = ParseSchema<GameScore2>(classLevelPermissions: clp)
93103
.addField("points",
94104
type: .number,
95105
options: ParseFieldOptions<Int>(required: false, defauleValue: nil))
106+
.addField("level",
107+
type: .number,
108+
options: ParseFieldOptions<Int>(required: false, defauleValue: nil))
96109
.addField("data",
97110
type: .bytes,
98111
options: ParseFieldOptions<String>(required: false, defauleValue: nil))
99112

100113
do {
101-
gameScoreSchema = try gameScoreSchema.addField("owner",
102-
type: .pointer,
103-
options: ParseFieldOptions<User>(required: false, defauleValue: nil))
114+
gameScoreSchema = try gameScoreSchema
115+
.addField("owner",
116+
type: .pointer,
117+
options: ParseFieldOptions<User>(required: false, defauleValue: nil))
118+
.addField("rivals",
119+
type: .array,
120+
options: ParseFieldOptions<[User]>(required: false, defauleValue: nil))
104121
} catch {
105122
print("Can't add field: \(gameScoreSchema)")
106123
}
@@ -120,7 +137,7 @@ let clp2 = clp.setPointerFields(Set(["owner"]), on: .get)
120137
gameScoreSchema.classLevelPermissions = clp2
121138

122139
//: In addition, we can add an index.
123-
gameScoreSchema = gameScoreSchema.addIndex("myIndex", field: "points", index: 1)
140+
gameScoreSchema = gameScoreSchema.addIndex("myIndex", field: "level", index: 1)
124141

125142
//: Next, we need to update the schema on the server with the changes.
126143
gameScoreSchema.update { result in
@@ -174,11 +191,13 @@ gameScoreSchema.update { result in
174191
}
175192

176193
/*:
177-
Fields can also be deleted on a schema. Lets remove
178-
the **data** field since it's not going being used.
194+
Sets of fields can also be protected from access. Lets protect
195+
some fields from access.
179196
*/
180197
var clp3 = gameScoreSchema.classLevelPermissions
181-
clp3 = clp3?.setProtectedFieldsPublic(["owner"])
198+
clp3 = clp3?
199+
.setProtectedFieldsPublic(["owner"])
200+
.setProtectedFields(["level"], userField: "rivals")
182201
gameScoreSchema.classLevelPermissions = clp3
183202

184203
//: Next, we need to update the schema on the server with the changes.

Sources/ParseSwift/Types/ParseCLP.swift

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ public struct ParseCLP: Codable, Equatable {
122122

123123
// MARK: Default Implementation
124124
extension ParseCLP {
125+
static func getUserFieldAccess(_ field: String) -> String {
126+
"userField:\(field)"
127+
}
128+
125129
func hasAccess(_ keyPath: KeyPath<Self, [String: AnyCodable]?>,
126130
for entity: String) -> Bool {
127131
self[keyPath: keyPath]?[entity]?.value as? Bool ?? false
@@ -801,6 +805,17 @@ public extension ParseCLP {
801805
getProtectedFields(Access.requiresAuthentication.rawValue)
802806
}
803807

808+
/**
809+
Get the protected fields either a field of `ParseUser` type or
810+
an array of `ParseUser`'s in a Parse class cannot access.
811+
- parameter field: A field in a Parse class that is either of `ParseUser` type or
812+
an array of `ParseUser`'s.
813+
- returns: The set protected fields that cannot be accessed.
814+
*/
815+
func getProtectedFieldsUser(_ field: String) -> Set<String> {
816+
getProtectedFields(Self.getUserFieldAccess(field))
817+
}
818+
804819
/**
805820
Get the protected fields the given `ParseUser` objectId cannot access.
806821
- parameter objectId: The `ParseUser` objectId access to check.
@@ -862,10 +877,25 @@ public extension ParseCLP {
862877
setProtected(fields, on: \.protectedFields, for: Access.requiresAuthentication.rawValue)
863878
}
864879

880+
/**
881+
Set whether the given field that is either of `ParseUser` type or an array of `ParseUser`'s
882+
should not have access to specific fields of a Parse class.
883+
- parameter fields: The set of fields that should be protected from access.
884+
- parameter userField: A field in a Parse class that is either of `ParseUser` type or
885+
an array of `ParseUser`'s to restrict access to.
886+
- returns: A mutated instance of `ParseCLP` for easy chaining.
887+
- throws: An error of type `ParseError`.
888+
*/
889+
func setProtectedFields(_ fields: Set<String>, userField: String) -> Self {
890+
setProtected(fields,
891+
on: \.protectedFields,
892+
for: Self.getUserFieldAccess(userField))
893+
}
894+
865895
/**
866896
Set whether the given `ParseUser` objectId should not have access to specific fields of a Parse class.
867-
- parameter objectId: The `ParseUser` objectId to restrict access to.
868897
- parameter fields: The set of fields that should be protected from access.
898+
- parameter objectId: The `ParseUser` objectId to restrict access to.
869899
- returns: A mutated instance of `ParseCLP` for easy chaining.
870900
- throws: An error of type `ParseError`.
871901
*/
@@ -930,6 +960,20 @@ public extension ParseCLP {
930960
addProtected(fields, on: \.protectedFields, for: Access.requiresAuthentication.rawValue)
931961
}
932962

963+
/**
964+
Add to the set of specific fields the given field that is either of `ParseUser` type or an array of `ParseUser`'s
965+
should not have access to on a Parse class.
966+
- parameter fields: The set of fields that should be protected from access.
967+
- parameter userField: A field in a Parse class that is either of `ParseUser` type or
968+
an array of `ParseUser`'s to restrict access to.
969+
- returns: A mutated instance of `ParseCLP` for easy chaining.
970+
- throws: An error of type `ParseError`.
971+
- note: This method adds on to the current set of `fields` in the CLP.
972+
*/
973+
func addProtectedFieldsUser(_ fields: Set<String>, userField: String) -> Self {
974+
addProtected(fields, on: \.protectedFields, for: Self.getUserFieldAccess(userField))
975+
}
976+
933977
/**
934978
Add to the set of specific fields the given `ParseUser` objectId should not have access to on a Parse class.
935979
- parameter fields: The set of fields that should be protected from access.
@@ -1003,6 +1047,20 @@ public extension ParseCLP {
10031047
removeProtected(fields, on: \.protectedFields, for: Access.requiresAuthentication.rawValue)
10041048
}
10051049

1050+
/**
1051+
Remove fields from the set of specific fields the given field that is either of `ParseUser` type
1052+
or an array of `ParseUser`'s should not have access to on a Parse class.
1053+
- parameter fields: The set of fields that should be removed from protected access.
1054+
- parameter userField: A field in a Parse class that is either of `ParseUser` type or
1055+
an array of `ParseUser`'s to restrict access to.
1056+
- returns: A mutated instance of `ParseCLP` for easy chaining.
1057+
- throws: An error of type `ParseError`.
1058+
- note: This method removes from the current set of `fields` in the CLP.
1059+
*/
1060+
func removeProtectedFieldsUser(_ fields: Set<String>, userField: String) -> Self {
1061+
removeProtected(fields, on: \.protectedFields, for: Self.getUserFieldAccess(userField))
1062+
}
1063+
10061064
/**
10071065
Remove fields from the set of specific fields the given `ParseUser` objectId
10081066
should not have access to on a Parse class.

Tests/ParseSwiftTests/ParseCLPTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ class ParseCLPTests: XCTestCase { // swiftlint:disable:this type_body_length
210210
XCTAssertEqual(clp4.getProtectedFieldsRequiresAuthentication(), newField)
211211
}
212212

213+
func testProtectedFieldsUserField() throws {
214+
let fields = Set<String>(["hello", "world"])
215+
let userField = "peace"
216+
let clp = ParseCLP().setProtectedFields(fields, userField: userField)
217+
XCTAssertEqual(clp.getProtectedFieldsUser(userField), fields)
218+
219+
let newField = Set<String>(["new"])
220+
let clp2 = clp.addProtectedFieldsUser(newField, userField: userField)
221+
XCTAssertEqual(clp2.getProtectedFieldsUser(userField), fields.union(newField))
222+
223+
let clp3 = clp2.removeProtectedFieldsUser(newField, userField: userField)
224+
XCTAssertEqual(clp3.getProtectedFieldsUser(userField), fields)
225+
226+
let clp4 = ParseCLP().addProtectedFieldsUser(newField, userField: userField)
227+
XCTAssertEqual(clp4.getProtectedFieldsUser(userField), newField)
228+
}
229+
213230
func testProtectedFieldsObjectId() throws {
214231
let fields = Set<String>(["hello", "world"])
215232
let clp = ParseCLP().setProtectedFields(fields, for: objectId)

0 commit comments

Comments
 (0)