SwiftPermissionsTests.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2018 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. import XCTest
  19. import RealmSwift
  20. final class PermissionUser: Object {
  21. // A class with a name that conflicts with an Object class from RealmSwift to verify
  22. // that it doesn't break anything
  23. }
  24. class SwiftPermissionsAPITests: SwiftSyncTestCase {
  25. var userA: SyncUser!
  26. var userB: SyncUser!
  27. var userC: SyncUser!
  28. override func setUp() {
  29. super.setUp()
  30. let baseName = UUID().uuidString
  31. userA = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "-a", password: "a", register: true),
  32. server: SwiftSyncTestCase.authServerURL())
  33. userB = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "-b", password: "a", register: true),
  34. server: SwiftSyncTestCase.authServerURL())
  35. userC = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "-c", password: "a", register: true),
  36. server: SwiftSyncTestCase.authServerURL())
  37. }
  38. override func tearDown() {
  39. userA.logOut()
  40. userB.logOut()
  41. userC.logOut()
  42. super.tearDown()
  43. }
  44. // MARK: Helper functions
  45. func openRealm(_ url: URL, _ user: SyncUser) -> Realm {
  46. let realm = try! Realm(configuration: user.configuration(realmURL: url))
  47. waitForSync(realm)
  48. return realm
  49. }
  50. func subscribe<T: Object>(realm: Realm, type: T.Type, _ filter: String = "TRUEPREDICATE") {
  51. let ex = expectation(description: "Add partial sync query")
  52. realm.subscribe(to: type, where: filter) { _, err in
  53. if let err = err {
  54. XCTFail("Partial sync subsription failed: \(err)")
  55. } else {
  56. ex.fulfill()
  57. }
  58. }
  59. waitForExpectations(timeout: 2.0, handler: nil)
  60. }
  61. func waitForSync(_ realm: Realm) {
  62. waitForUploads(for: realm)
  63. waitForDownloads(for: realm)
  64. realm.refresh()
  65. }
  66. func createRealm(name: String, permissions: (Realm) -> Void) -> URL {
  67. // Create a new Realm with an admin user
  68. let admin = createAdminUser(for: SwiftSyncTestCase.authServerURL(),
  69. username: UUID().uuidString + "-admin")
  70. let url = URL(string: "realm://127.0.0.1:9080/\(name)")!
  71. let adminRealm = openRealm(url, admin)
  72. // FIXME: we currently need to add a subscription to get the permissions types sent to us
  73. subscribe(realm: adminRealm, type: SwiftSyncObject.self)
  74. // Set up permissions on the Realm
  75. try! adminRealm.write {
  76. adminRealm.create(SwiftSyncObject.self, value: ["obj 1"])
  77. permissions(adminRealm)
  78. }
  79. // FIXME: we currently need to also add the old realm-level permissions
  80. let ex1 = expectation(description: "Setting a permission should work.")
  81. let ex2 = expectation(description: "Setting a permission should work.")
  82. let ex3 = expectation(description: "Setting a permission should work.")
  83. admin.apply(SyncPermission(realmPath: url.path, identity: userA.identity!, accessLevel: .read)) { error in
  84. XCTAssertNil(error)
  85. ex1.fulfill()
  86. }
  87. admin.apply(SyncPermission(realmPath: url.path, identity: userB.identity!, accessLevel: .read)) { error in
  88. XCTAssertNil(error)
  89. ex2.fulfill()
  90. }
  91. admin.apply(SyncPermission(realmPath: url.path, identity: userC.identity!, accessLevel: .read)) { error in
  92. XCTAssertNil(error)
  93. ex3.fulfill()
  94. }
  95. waitForExpectations(timeout: 2.0, handler: nil)
  96. waitForSync(adminRealm)
  97. return url
  98. }
  99. func createDefaultPermisisons(_ permissions: List<Permission>) {
  100. var p = permissions.findOrCreate(forRoleNamed: "everyone")
  101. p.canCreate = false
  102. p.canRead = false
  103. p.canQuery = false
  104. p.canDelete = false
  105. p.canUpdate = false
  106. p.canModifySchema = false
  107. p.canSetPermissions = false
  108. p = permissions.findOrCreate(forRoleNamed: "reader")
  109. p.canRead = true
  110. p.canQuery = true
  111. p = permissions.findOrCreate(forRoleNamed: "writer")
  112. p.canUpdate = true
  113. p.canCreate = true
  114. p.canDelete = true
  115. p = permissions.findOrCreate(forRoleNamed: "admin")
  116. p.canSetPermissions = true
  117. }
  118. func add(user: SyncUser, toRole roleName: String, inRealm realm: Realm) {
  119. let user = realm.create(RealmSwift.PermissionUser.self, value: [user.identity!], update: true)
  120. realm.create(PermissionRole.self, value: [roleName], update: true).users.append(user)
  121. }
  122. // MARK: Tests
  123. func testRealmRead() {
  124. let url = createRealm(name: "testRealmRead") { realm in
  125. createDefaultPermisisons(realm.permissions)
  126. add(user: userA, toRole: "reader", inRealm: realm)
  127. }
  128. // userA should now be able to open the Realm and see objects
  129. let realmA = openRealm(url, userA)
  130. subscribe(realm: realmA, type: SwiftSyncObject.self)
  131. XCTAssertEqual(realmA.getPrivileges(), [.read])
  132. XCTAssertEqual(realmA.getPrivileges(SwiftSyncObject.self), [.read, .subscribe])
  133. XCTAssertEqual(realmA.getPrivileges(realmA.objects(SwiftSyncObject.self).first!), [.read])
  134. // userA should not be able to create new objects
  135. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 1)
  136. try! realmA.write {
  137. realmA.create(SwiftSyncObject.self, value: ["obj 2"])
  138. }
  139. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 2)
  140. waitForSync(realmA)
  141. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 1)
  142. // userB should not be able to read any objects
  143. let realmB = openRealm(url, userB)
  144. subscribe(realm: realmB, type: SwiftSyncObject.self)
  145. XCTAssertEqual(realmB.getPrivileges(), [])
  146. XCTAssertEqual(realmB.getPrivileges(SwiftSyncObject.self), [])
  147. XCTAssertEqual(realmB.objects(SwiftSyncObject.self).count, 0)
  148. }
  149. func testRealmWrite() {
  150. let url = createRealm(name: "testRealmWrite") { realm in
  151. createDefaultPermisisons(realm.permissions)
  152. add(user: userA, toRole: "reader", inRealm: realm)
  153. add(user: userA, toRole: "writer", inRealm: realm)
  154. add(user: userB, toRole: "reader", inRealm: realm)
  155. }
  156. // userA should now be able to open the Realm and see objects
  157. let realmA = openRealm(url, userA)
  158. subscribe(realm: realmA, type: SwiftSyncObject.self)
  159. XCTAssertEqual(realmA.getPrivileges(), [.read, .update])
  160. XCTAssertEqual(realmA.getPrivileges(SwiftSyncObject.self),
  161. [.read, .subscribe, .update, .create, .setPermissions])
  162. XCTAssertEqual(realmA.getPrivileges(realmA.objects(SwiftSyncObject.self).first!),
  163. [.read, .update, .delete, .setPermissions])
  164. // userA should be able to create new objects
  165. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 1)
  166. try! realmA.write {
  167. realmA.create(SwiftSyncObject.self, value: ["obj 2"])
  168. }
  169. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 2)
  170. waitForSync(realmA)
  171. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 2)
  172. // userB's insertions should be reverted
  173. let realmB = openRealm(url, userB)
  174. subscribe(realm: realmB, type: SwiftSyncObject.self)
  175. XCTAssertEqual(realmB.objects(SwiftSyncObject.self).count, 2)
  176. try! realmB.write {
  177. realmB.create(SwiftSyncObject.self, value: ["obj 3"])
  178. }
  179. XCTAssertEqual(realmB.objects(SwiftSyncObject.self).count, 3)
  180. waitForSync(realmB)
  181. XCTAssertEqual(realmB.objects(SwiftSyncObject.self).count, 2)
  182. }
  183. func testRealmSetPermissions() {
  184. }
  185. func testRealmModifySchema() {
  186. }
  187. func testClassRead() {
  188. let url = createRealm(name: "testClassRead") { realm in
  189. createDefaultPermisisons(realm.permissions(forType: SwiftSyncObject.self))
  190. add(user: userA, toRole: "reader", inRealm: realm)
  191. }
  192. // userA should now be able to open the Realm and see objects
  193. let realmA = openRealm(url, userA)
  194. subscribe(realm: realmA, type: SwiftSyncObject.self)
  195. XCTAssertEqual(realmA.getPrivileges(), [.read, .update, .setPermissions, .modifySchema])
  196. XCTAssertEqual(realmA.getPrivileges(SwiftSyncObject.self), [.read, .subscribe])
  197. XCTAssertEqual(realmA.getPrivileges(realmA.objects(SwiftSyncObject.self).first!), [.read])
  198. // userA should not be able to create new objects
  199. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 1)
  200. try! realmA.write {
  201. realmA.create(SwiftSyncObject.self, value: ["obj 2"])
  202. }
  203. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 2)
  204. waitForSync(realmA)
  205. XCTAssertEqual(realmA.objects(SwiftSyncObject.self).count, 1)
  206. // userB should not be able to read any objects
  207. let realmB = openRealm(url, userB)
  208. subscribe(realm: realmB, type: SwiftSyncObject.self)
  209. XCTAssertEqual(realmB.getPrivileges(), [.read, .update, .setPermissions, .modifySchema])
  210. XCTAssertEqual(realmB.getPrivileges(SwiftSyncObject.self), [])
  211. XCTAssertEqual(realmB.objects(SwiftSyncObject.self).count, 0)
  212. }
  213. func testClassWrite() {
  214. }
  215. func testClassSetPermissions() {
  216. }
  217. }