SwiftPermissionsAPITests.swift 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2017 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. class SwiftRealmPermissionsAPITests: SwiftSyncTestCase {
  21. var userA: SyncUser!
  22. var userB: SyncUser!
  23. var userC: SyncUser!
  24. override func setUp() {
  25. super.setUp()
  26. let baseName = UUID().uuidString
  27. userA = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "a", password: "a", register: true),
  28. server: SwiftSyncTestCase.authServerURL())
  29. userB = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "b", password: "a", register: true),
  30. server: SwiftSyncTestCase.authServerURL())
  31. userC = try! synchronouslyLogInUser(for: .usernamePassword(username: baseName + "c", password: "a", register: true),
  32. server: SwiftSyncTestCase.authServerURL())
  33. }
  34. override func tearDown() {
  35. userA.logOut()
  36. userB.logOut()
  37. userC.logOut()
  38. super.tearDown()
  39. }
  40. /// Ensure the absence of a permission from a results after an elapsed time interval.
  41. /// This method is intended to be used to check that a permission never becomes
  42. /// present within a results to begin with.
  43. private func ensureAbsence(of permission: SyncPermission,
  44. from results: SyncPermissionResults,
  45. after wait: Double = 0.5,
  46. file: StaticString = #file,
  47. line: UInt = #line) {
  48. }
  49. private func tildeSubstitutedURL(for url: URL, user: SyncUser) -> URL {
  50. XCTAssertNotNil(user.identity)
  51. let identity = user.identity!
  52. return URL(string: url.absoluteString.replacingOccurrences(of: "~", with: identity))!
  53. }
  54. /// Setting a permission should work, and then that permission should be able to be retrieved.
  55. func testSettingPermissions() {
  56. // First, there should be no permissions.
  57. let ex = expectation(description: "No permissions for newly created user.")
  58. userB.retrievePermissions { (r, error) in
  59. XCTAssertNil(error)
  60. XCTAssertNotNil(r)
  61. XCTAssertEqual(r!.count, 0)
  62. ex.fulfill()
  63. }
  64. waitForExpectations(timeout: 2.0, handler: nil)
  65. // Open a Realm for user A.
  66. let uuid = UUID().uuidString
  67. let url = SwiftSyncTestCase.uniqueRealmURL(customName: uuid)
  68. _ = try! synchronouslyOpenRealm(url: url, user: userA)
  69. // Give user B read permissions to that Realm.
  70. let p = SyncPermission(realmPath: tildeSubstitutedURL(for: url, user: userA).path,
  71. identity: userB.identity!,
  72. accessLevel: .read)
  73. // Set the permission.
  74. let ex2 = expectation(description: "Setting a permission should work.")
  75. userA.apply(p) { (error) in
  76. XCTAssertNil(error)
  77. ex2.fulfill()
  78. }
  79. waitForExpectations(timeout: 2.0, handler: nil)
  80. // Now retrieve the permissions again and make sure the new permission is properly set.
  81. let ex3 = expectation(description: "One permission in results after setting the permission.")
  82. userB.retrievePermissions { (r, error) in
  83. XCTAssertNil(error)
  84. XCTAssertNotNil(r)
  85. guard let r = r else { return }
  86. XCTAssertTrue(r.contains(p))
  87. // Check getting permission by its index.
  88. let index = r.index(of: p)
  89. XCTAssertNotNil(index)
  90. XCTAssertTrue(p == r[index!])
  91. ex3.fulfill()
  92. }
  93. waitForExpectations(timeout: 2.0, handler: nil)
  94. }
  95. /// Observing permission changes should work.
  96. func testObservingPermissions() {
  97. // Open a Realm for user A.
  98. let uuid = UUID().uuidString
  99. let url = SwiftSyncTestCase.uniqueRealmURL(customName: uuid)
  100. _ = try! synchronouslyOpenRealm(url: url, user: userA)
  101. // Give user B read permissions to that Realm.
  102. let p = SyncPermission(realmPath: tildeSubstitutedURL(for: url, user: userA).path,
  103. identity: userB.identity!,
  104. accessLevel: .read)
  105. // Set the permission.
  106. let ex2 = expectation(description: "Setting a permission should work.")
  107. userA.apply(p) { (error) in
  108. XCTAssertNil(error)
  109. ex2.fulfill()
  110. }
  111. wait(for: [ex2], timeout: 2.0)
  112. // Verify that it was added
  113. let ex3 = expectation(description: "Retrieving the results should work.")
  114. userB.retrievePermissions { (r, error) in
  115. XCTAssertNil(error)
  116. XCTAssertNotNil(r)
  117. XCTAssertTrue(r!.contains(p))
  118. ex3.fulfill()
  119. }
  120. waitForExpectations(timeout: 2.0, handler: nil)
  121. }
  122. /// User should not be able to change a permission for a Realm they don't own.
  123. func testSettingUnownedRealmPermission() {
  124. // Open a Realm for user A.
  125. let uuid = UUID().uuidString
  126. let url = SwiftSyncTestCase.uniqueRealmURL(customName: uuid)
  127. _ = try! synchronouslyOpenRealm(url: url, user: userA)
  128. // Try to have user B give user C permissions to that Realm.
  129. let p = SyncPermission(realmPath: url.path, identity: userC.identity!, accessLevel: .read)
  130. // Attempt to set the permission.
  131. let ex2 = expectation(description: "Setting an invalid permission should fail.")
  132. userB.apply(p) { error in
  133. XCTAssertNotNil(error)
  134. ex2.fulfill()
  135. }
  136. waitForExpectations(timeout: 2.0, handler: nil)
  137. // Now retrieve the permissions again and make sure the new permission was not set.
  138. let ex3 = expectation(description: "Retrieving the results should work.")
  139. userB.retrievePermissions { (r, error) in
  140. XCTAssertNil(error)
  141. XCTAssertNotNil(r)
  142. XCTAssertFalse(r!.contains(p))
  143. ex3.fulfill()
  144. }
  145. waitForExpectations(timeout: 2.0, handler: nil)
  146. }
  147. // MARK: - Offer/response
  148. func testPermissionOffer() {
  149. _ = try! synchronouslyOpenRealm(url: realmURL, user: userA)
  150. var token: String?
  151. // Create an offer.
  152. let ex = expectation(description: "A new permission offer will be processed by the server.")
  153. userA.createOfferForRealm(at: realmURL, accessLevel: .write) { (t, error) in
  154. XCTAssertNil(error)
  155. XCTAssertNotNil(t)
  156. token = t
  157. ex.fulfill()
  158. }
  159. waitForExpectations(timeout: 10.0, handler: nil)
  160. XCTAssertGreaterThan(token!.lengthOfBytes(using: .utf8), 0)
  161. }
  162. func testPermissionOfferResponse() {
  163. _ = try! synchronouslyOpenRealm(url: realmURL, user: userA)
  164. var token: String?
  165. // Create an offer.
  166. let ex = expectation(description: "A new permission offer will be processed by the server.")
  167. userA.createOfferForRealm(at: realmURL, accessLevel: .write) { (t, error) in
  168. XCTAssertNil(error)
  169. XCTAssertNotNil(t)
  170. token = t
  171. ex.fulfill()
  172. }
  173. waitForExpectations(timeout: 10.0, handler: nil)
  174. guard let theToken = token else {
  175. XCTFail("We expected an offer token, but did not get one. Aborting the test.")
  176. return
  177. }
  178. XCTAssertGreaterThan(theToken.lengthOfBytes(using: .utf8), 0)
  179. // Accept the offer.
  180. let ex2 = expectation(description: "A permission offer response will be processed by the server.")
  181. var url: URL?
  182. userB.acceptOffer(forToken: theToken) { (u, error) in
  183. XCTAssertNil(error)
  184. XCTAssertNotNil(u)
  185. url = u
  186. ex2.fulfill()
  187. }
  188. waitForExpectations(timeout: 10.0, handler: nil)
  189. guard let theURL = url else {
  190. XCTFail("We expected a Realm URL, but did not get one. Aborting the test.")
  191. return
  192. }
  193. XCTAssertEqual(theURL.path, tildeSubstitutedURL(for: realmURL, user: userA).path)
  194. do {
  195. _ = try synchronouslyOpenRealm(url: theURL, user: userB)
  196. } catch {
  197. XCTFail("Was not able to successfully open the Realm with user B after accepting the offer.")
  198. }
  199. }
  200. }