123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2018 Realm Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- ////////////////////////////////////////////////////////////////////////////
- XCTestExpectation *ex = [self expectationWithDescription:@"apply permission"]; \
- [ma_user applyPermission:ma_permission callback:^(NSError *err) { \
- XCTAssertNil(err, @"Received an error when applying permission: %@", err); \
- [ex fulfill]; \
- }]; \
- [self waitForExpectationsWithTimeout:10.0 handler:nil]; \
- } while (0) \
- @interface ObjectWithPermissions : RLMObject
- @property (nonatomic) int value;
- @property (nonatomic) RLMArray<RLMPermission *><RLMPermission> *permissions;
- @end
- @implementation ObjectWithPermissions
- @end
- @interface LinkToObjectWithPermissions : RLMObject
- @property (nonatomic) int value;
- @property (nonatomic) ObjectWithPermissions *link;
- @property (nonatomic) RLMArray<RLMPermission *><RLMPermission> *permissions;
- @end
- @implementation LinkToObjectWithPermissions
- @end
- @interface RLMPermissionsTests : RLMSyncTestCase
- @property (nonatomic, strong) RLMSyncUser *userA;
- @property (nonatomic, strong) RLMSyncUser *userB;
- @property (nonatomic, strong) RLMSyncUser *userC;
- @property (nonatomic, strong) void (^errorBlock)(NSError *);
- @end
- @implementation RLMPermissionsTests
- - (void)setUp {
- [super setUp];
- NSString *accountNameBase = [[NSUUID UUID] UUIDString];
- NSString *userNameA = [accountNameBase stringByAppendingString:@"a"];
- self.userA = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:userNameA register:YES]
- server:[RLMSyncTestCase authServerURL]];
- NSString *userNameB = [accountNameBase stringByAppendingString:@"b"];
- self.userB = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:userNameB register:YES]
- server:[RLMSyncTestCase authServerURL]];
- NSString *userNameC = [accountNameBase stringByAppendingString:@"c"];
- self.userC = [self logInUserForCredentials:[RLMSyncTestCase basicCredentialsWithName:userNameC register:YES]
- server:[RLMSyncTestCase authServerURL]];
- RLMSyncManager.sharedManager.errorHandler = ^(NSError *error, __unused RLMSyncSession *session) {
- if (self.errorBlock) {
- self.errorBlock(error);
- self.errorBlock = nil;
- } else {
- XCTFail(@"Error handler should not be called unless explicitly expected. Error: %@", error);
- }
- };
- }
- - (void)tearDown {
- [self.userA logOut];
- [self.userB logOut];
- [self.userC logOut];
- RLMSyncManager.sharedManager.errorHandler = nil;
- [super tearDown];
- }
- - (BOOL)isPartial {
- return YES;
- }
- - (NSError *)subscribeToRealm:(RLMRealm *)realm type:(Class)cls where:(NSString *)pred {
- __block NSError *error;
- XCTestExpectation *ex = [self expectationWithDescription:@"Should be able to successfully complete a query"];
- [realm subscribeToObjects:cls where:pred callback:^(__unused RLMResults *results, NSError *err) {
- error = err;
- [ex fulfill];
- }];
- [self waitForExpectations:@[ex] timeout:20.0];
- return error;
- }
- - (NSURL *)createRealmWithName:(SEL)sel permissions:(void (^)(RLMRealm *realm))block {
- // Create a new Realm with an admin user
- RLMSyncUser *admin = [self createAdminUserForURL:[RLMSyncTestCase authServerURL]
- username:[[NSUUID UUID] UUIDString]];
- auto url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"realm://127.0.0.1:9080/%@", NSStringFromSelector(sel)]];
- RLMRealm *adminRealm = [self openRealmForURL:url user:admin];
- [self addSyncObjectsToRealm:adminRealm descriptions:@[@"child-1", @"child-2", @"child-3"]];
- CHECK_COUNT(3, SyncObject, adminRealm);
- [self waitForUploadsForRealm:adminRealm error:nil];
- [self waitForDownloadsForRealm:adminRealm error:nil];
- // FIXME: we currently need to add a subscription to get the permissions types sent to us
- [adminRealm refresh];
- CHECK_COUNT(0, SyncObject, adminRealm);
- [self subscribeToRealm:adminRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_COUNT(3, SyncObject, adminRealm);
- // Set up permissions on the Realm
- [adminRealm transactionWithBlock:^{ block(adminRealm); }];
- // FIXME: we currently need to also add the old realm-level permissions
- RLMSyncPermission *p = [[RLMSyncPermission alloc] initWithRealmPath:[url path]
- identity:self.userA.identity
- accessLevel:RLMSyncAccessLevelRead];
- APPLY_PERMISSION(p, admin);
- p = [[RLMSyncPermission alloc] initWithRealmPath:[url path] identity:self.userB.identity
- accessLevel:RLMSyncAccessLevelRead];
- APPLY_PERMISSION(p, admin);
- p = [[RLMSyncPermission alloc] initWithRealmPath:[url path] identity:self.userC.identity
- accessLevel:RLMSyncAccessLevelRead];
- APPLY_PERMISSION(p, admin);
- [self waitForSync:adminRealm];
- return url;
- }
- - (void)waitForSync:(RLMRealm *)realm {
- [self waitForUploadsForRealm:realm error:nil];
- [self waitForDownloadsForRealm:realm error:nil];
- [realm refresh];
- }
- static RLMPermissionRole *getRole(RLMRealm *realm, NSString *roleName) {
- return [RLMPermissionRole createOrUpdateInRealm:realm withValue:@{@"name": roleName}];
- }
- static void addUserToRole(RLMRealm *realm, NSString *roleName, NSString *user) {
- [getRole(realm, roleName).users addObject:[RLMPermissionUser userInRealm:realm withIdentity:user]];
- }
- static void createPermissions(RLMArray<RLMPermission> *permissions) {
- auto permission = [RLMPermission permissionForRoleNamed:@"everyone" inArray:permissions];
- permission.canCreate = false;
- permission.canRead = false;
- permission.canQuery = false;
- permission.canDelete = false;
- permission.canUpdate = false;
- permission.canModifySchema = false;
- permission.canSetPermissions = false;
- permission = [RLMPermission permissionForRoleNamed:@"reader" inArray:permissions];
- permission.canRead = true;
- permission.canQuery = true;
- permission = [RLMPermission permissionForRoleNamed:@"writer" inArray:permissions];
- permission.canUpdate = true;
- permission.canCreate = true;
- permission.canDelete = true;
- permission = [RLMPermission permissionForRoleNamed:@"admin" inArray:permissions];
- permission.canSetPermissions = true;
- }
- RLMRealmPrivileges expected{__VA_ARGS__}; \
- auto actual = [realm privilegesForRealm]; \
- XCTAssertEqual(expected.read, actual.read); \
- XCTAssertEqual(expected.update, actual.update); \
- XCTAssertEqual(expected.setPermissions, actual.setPermissions); \
- XCTAssertEqual(expected.modifySchema, actual.modifySchema); \
- } while (0)
- RLMClassPrivileges expected{__VA_ARGS__}; \
- auto actual = [realm privilegesForClass:SyncObject.class]; \
- XCTAssertEqual(expected.read, actual.read); \
- XCTAssertEqual(expected.create, actual.create); \
- XCTAssertEqual(expected.update, actual.update); \
- XCTAssertEqual(expected.subscribe, actual.subscribe); \
- XCTAssertEqual(expected.setPermissions, actual.setPermissions); \
- } while (0)
- RLMObjectPrivileges expected{__VA_ARGS__}; \
- auto actual = [realm privilegesForObject:[SyncObject allObjectsInRealm:realm].firstObject]; \
- XCTAssertEqual(expected.read, actual.read); \
- XCTAssertEqual(expected.del, actual.del); \
- XCTAssertEqual(expected.update, actual.update); \
- XCTAssertEqual(expected.setPermissions, actual.setPermissions); \
- } while (0)
- - (void)testRealmReadAccess {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMRealmPermission objectInRealm:realm].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- }];
- // userA should now be able to open the Realm and see objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userARealm, .read = true);
- CHECK_CLASS_PRIVILEGE(userARealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userARealm, .read = true);
- // userA should not be able to create new objects
- CHECK_COUNT(3, SyncObject, userARealm);
- [self addSyncObjectsToRealm:userARealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(3, SyncObject, userARealm);
- // userB should not be able to read any objects
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userBRealm, .read = false);
- CHECK_CLASS_PRIVILEGE(userBRealm, .read = false);
- CHECK_COUNT(0, SyncObject, userBRealm);
- }
- - (void)testRealmWriteAccess {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMRealmPermission objectInRealm:realm].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"writer", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- }];
- // userA should be able to add objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userARealm, .read = true, .update = true);
- CHECK_CLASS_PRIVILEGE(userARealm, .read = true, .subscribe = true,
- .update = true, .create = true, .setPermissions = true);
- CHECK_OBJECT_PRIVILEGE(userARealm, .read = true, .update = true, .del = true, .setPermissions = true);
- CHECK_COUNT(3, SyncObject, userARealm);
- [self addSyncObjectsToRealm:userARealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(6, SyncObject, userARealm);
- // userB's insertions should be reverted
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userBRealm, .read = true);
- CHECK_CLASS_PRIVILEGE(userBRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userBRealm, .read = true);
- CHECK_COUNT(6, SyncObject, userBRealm);
- [self addSyncObjectsToRealm:userBRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(9, SyncObject, userBRealm);
- [self waitForSync:userBRealm];
- CHECK_COUNT(6, SyncObject, userBRealm);
- }
- - (void)testRealmManagePermissions {
- // FIXME: this test is wrong; setPermission doesn't govern adding users to roles
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMRealmPermission objectInRealm:realm].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"writer", self.userA.identity);
- addUserToRole(realm, @"admin", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- addUserToRole(realm, @"writer", self.userB.identity);
- addUserToRole(realm, @"reader", self.userC.identity);
- }];
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- RLMRealm *userCRealm = [self openRealmForURL:url user:self.userC];
- // userC should initially not be able to write to the Realm
- [self subscribeToRealm:userCRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userCRealm, .read = true);
- CHECK_CLASS_PRIVILEGE(userCRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userCRealm, .read = true);
- [self addSyncObjectsToRealm:userCRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- [self waitForSync:userCRealm];
- CHECK_COUNT(3, SyncObject, userCRealm);
- // userB should not be able to grant write permissions to userC
- [userBRealm transactionWithBlock:^{
- addUserToRole(userBRealm, @"writer", self.userC.identity);
- }];
- [self waitForSync:userBRealm];
- [self waitForSync:userCRealm];
- CHECK_REALM_PRIVILEGE(userCRealm, .read = true);
- CHECK_CLASS_PRIVILEGE(userCRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userCRealm, .read = true);
- [self addSyncObjectsToRealm:userCRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- [self waitForSync:userCRealm];
- CHECK_COUNT(3, SyncObject, userCRealm);
- // userA should be able to grant write permissions to userC
- [userARealm transactionWithBlock:^{
- addUserToRole(userARealm, @"writer", self.userC.identity);
- }];
- [self waitForSync:userARealm];
- [self waitForSync:userCRealm];
- CHECK_REALM_PRIVILEGE(userCRealm, .read = true, .update = true);
- CHECK_CLASS_PRIVILEGE(userCRealm, .read = true, .subscribe = true, .update = true, .create = true);
- CHECK_OBJECT_PRIVILEGE(userCRealm, .read = true, .update = true, .del = true);
- [self addSyncObjectsToRealm:userCRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- [self waitForSync:userCRealm];
- CHECK_COUNT(6, SyncObject, userCRealm);
- }
- - (void)testRealmModifySchema {
- // awkward to test due to that reverts will normally crash
- // probably need to spawn a child process?
- }
- - (void)testClassRead {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMClassPermission objectInRealm:realm forClass:SyncObject.class].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- }];
- // userA should now be able to open the Realm and see objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userARealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userARealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userARealm, .read = true);
- CHECK_COUNT(3, SyncObject, userARealm);
- // userA should not be able to create new objects
- [self addSyncObjectsToRealm:userARealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(3, SyncObject, userARealm);
- // userB should not be able to read any objects
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userBRealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userBRealm, .read = false);
- CHECK_COUNT(0, SyncObject, userBRealm);
- }
- - (void)testClassUpdate {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMClassPermission objectInRealm:realm forClass:SyncObject.class].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"writer", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- }];
- // userA should be able to mutate objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userARealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userARealm, .read = true, .subscribe = true, .update = true, .create = true);
- CHECK_OBJECT_PRIVILEGE(userARealm, .read = true, .update = true, .del = true, .setPermissions = true);
- SyncObject *objA = [SyncObject allObjectsInRealm:userARealm].firstObject;
- [userARealm transactionWithBlock:^{
- objA.stringProp = @"new value";
- }];
- [self waitForSync:userARealm];
- XCTAssertEqualObjects(objA.stringProp, @"new value");
- // userB's mutations should be reverted
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userBRealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userBRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userBRealm, .read = true);
- SyncObject *objB = [SyncObject allObjectsInRealm:userBRealm].firstObject;
- [userBRealm transactionWithBlock:^{
- objB.stringProp = @"new value 2";
- }];
- XCTAssertEqualObjects(objB.stringProp, @"new value 2");
- [self waitForSync:userBRealm];
- XCTAssertEqualObjects(objB.stringProp, @"new value");
- }
- - (void)testClassCreate {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMClassPermission objectInRealm:realm forClass:SyncObject.class].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"writer", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- }];
- // userA should be able to add objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userARealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userARealm, .read = true, .subscribe = true, .update = true, .create = true);
- CHECK_OBJECT_PRIVILEGE(userARealm, .read = true, .update = true, .del = true, .setPermissions = true);
- CHECK_COUNT(3, SyncObject, userARealm);
- [self addSyncObjectsToRealm:userARealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(6, SyncObject, userARealm);
- // userB's insertions should be reverted
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userBRealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userBRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userBRealm, .read = true);
- CHECK_COUNT(6, SyncObject, userBRealm);
- [self addSyncObjectsToRealm:userBRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(9, SyncObject, userBRealm);
- [self waitForSync:userBRealm];
- CHECK_COUNT(6, SyncObject, userBRealm);
- }
- - (void)testClassSetPermissions {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- createPermissions([RLMClassPermission objectInRealm:realm forClass:SyncObject.class].permissions);
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"writer", self.userA.identity);
- addUserToRole(realm, @"admin", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- addUserToRole(realm, @"writer", self.userB.identity);
- addUserToRole(realm, @"reader", self.userC.identity);
- }];
- // Despite having write access userB should not be able to add "update" access to "reader"
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- [userBRealm transactionWithBlock:^{
- auto permission = [RLMPermission permissionForRoleNamed:@"reader" onClass:SyncObject.class realm:userBRealm];
- permission.canCreate = true;
- permission.canUpdate = true;
- }];
- [self waitForSync:userBRealm];
- // userC should be unable to create objects
- RLMRealm *userCRealm = [self openRealmForURL:url user:self.userC];
- [self subscribeToRealm:userCRealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- CHECK_REALM_PRIVILEGE(userCRealm, .read = true, .update = true, .setPermissions = true, .modifySchema = true);
- CHECK_CLASS_PRIVILEGE(userCRealm, .read = true, .subscribe = true);
- CHECK_OBJECT_PRIVILEGE(userCRealm, .read = true);
- [self addSyncObjectsToRealm:userCRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userCRealm);
- [self waitForSync:userCRealm];
- CHECK_COUNT(3, SyncObject, userCRealm);
- // userA should able to add "update" access to "reader"
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[SyncObject class] where:@"TRUEPREDICATE"];
- [userARealm transactionWithBlock:^{
- auto permission = [RLMPermission permissionForRoleNamed:@"reader" onClass:SyncObject.class realm:userARealm];
- permission.canCreate = true;
- permission.canUpdate = true;
- }];
- [self waitForSync:userARealm];
- // userC should now be able to create objects
- [self waitForSync:userCRealm];
- CHECK_CLASS_PRIVILEGE(userCRealm, .read = true, .subscribe = true, .update = true, .create = true);
- CHECK_OBJECT_PRIVILEGE(userCRealm, .read = true, .update = true, .del = true, .setPermissions = true);
- [self addSyncObjectsToRealm:userCRealm descriptions:@[@"child-4", @"child-5", @"child-6"]];
- CHECK_COUNT(6, SyncObject, userCRealm);
- [self waitForSync:userCRealm];
- CHECK_COUNT(6, SyncObject, userCRealm);
- }
- - (void)testObjectRead {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- addUserToRole(realm, @"reader", self.userA.identity);
- auto obj1 = [ObjectWithPermissions createInRealm:realm withValue:@[@1]];
- createPermissions(obj1.permissions);
- [ObjectWithPermissions createInRealm:realm withValue:@[@2]];
- }];
- // userA should be able to see both objects
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- CHECK_COUNT(1, ObjectWithPermissions, userARealm);
- // userB should not be able to read any objects
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- CHECK_COUNT(0, ObjectWithPermissions, userBRealm);
- }
- - (void)testObjectTransitiveRead {
- }
- - (void)testObjectUpdate {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- addUserToRole(realm, @"writer", self.userB.identity);
- auto obj1 = [ObjectWithPermissions createInRealm:realm withValue:@[@1]];
- createPermissions(obj1.permissions);
- }];
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- ObjectWithPermissions *objA = [ObjectWithPermissions allObjectsInRealm:userARealm].firstObject;
- [userARealm transactionWithBlock:^{
- objA.value = 3;
- }];
- [self waitForSync:userARealm];
- XCTAssertEqual(objA.value, 1);
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- ObjectWithPermissions *objB = [ObjectWithPermissions allObjectsInRealm:userBRealm].firstObject;
- [userBRealm transactionWithBlock:^{
- objB.value = 3;
- }];
- [self waitForSync:userBRealm];
- [self waitForSync:userARealm];
- XCTAssertEqual(objA.value, 3);
- XCTAssertEqual(objB.value, 3);
- }
- - (void)testObjectDelete {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- addUserToRole(realm, @"reader", self.userA.identity);
- addUserToRole(realm, @"reader", self.userB.identity);
- addUserToRole(realm, @"writer", self.userB.identity);
- auto obj1 = [ObjectWithPermissions createInRealm:realm withValue:@[@1]];
- createPermissions(obj1.permissions);
- }];
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- ObjectWithPermissions *objA = [ObjectWithPermissions allObjectsInRealm:userARealm].firstObject;
- [userARealm transactionWithBlock:^{
- [userARealm deleteObject:objA];
- }];
- CHECK_COUNT(0, ObjectWithPermissions, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(1, ObjectWithPermissions, userARealm);
- objA = [ObjectWithPermissions allObjectsInRealm:userARealm].firstObject;
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- ObjectWithPermissions *objB = [ObjectWithPermissions allObjectsInRealm:userBRealm].firstObject;
- [userBRealm transactionWithBlock:^{
- [userBRealm deleteObject:objB];
- }];
- [self waitForSync:userBRealm];
- [self waitForSync:userARealm];
- CHECK_COUNT(0, ObjectWithPermissions, userARealm);
- CHECK_COUNT(0, ObjectWithPermissions, userBRealm);
- XCTAssertTrue(objA.invalidated);
- XCTAssertTrue(objB.invalidated);
- }
- - (void)testObjectSetPermissions {
- NSURL *url = [self createRealmWithName:_cmd permissions:^(RLMRealm *) {}];
- RLMRealm *userARealm = [self openRealmForURL:url user:self.userA];
- [self subscribeToRealm:userARealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- [userARealm transactionWithBlock:^{
- auto obj = [ObjectWithPermissions createInRealm:userARealm withValue:@[@1]];
- auto permissions = [RLMPermission permissionForRoleNamed:@"foo" onObject:obj];
- permissions.canRead = true;
- addUserToRole(userARealm, @"foo", self.userB.identity);
- }];
- CHECK_COUNT(1, ObjectWithPermissions, userARealm);
- [self waitForSync:userARealm];
- CHECK_COUNT(0, ObjectWithPermissions, userARealm);
- RLMRealm *userBRealm = [self openRealmForURL:url user:self.userB];
- [self subscribeToRealm:userBRealm type:[ObjectWithPermissions class] where:@"TRUEPREDICATE"];
- CHECK_COUNT(1, ObjectWithPermissions, userBRealm);
- }
- - (void)testRetrieveClassPermissionsForRenamedClass {
- [self createRealmWithName:_cmd permissions:^(RLMRealm *realm) {
- XCTAssertNotNil([RLMClassPermission objectInRealm:realm forClass:RLMPermissionRole.class]);
- }];
- }
- @end
|