public void GetInstanceAsync_ShouldDownloadRealm(bool singleTransaction)
        {
            SyncTestHelpers.RequiresRos();

            AsyncContext.Run(async() =>
            {
                var user = await SyncTestHelpers.GetUserAsync();

                var realmUri = SyncTestHelpers.RealmUri("~/GetInstanceAsync_ShouldDownloadRealm");

                var config      = new FullSyncConfiguration(realmUri, user, Guid.NewGuid().ToString());
                var asyncConfig = new FullSyncConfiguration(realmUri, user, config.DatabasePath + "_async");

                using (var realm = GetRealm(config))
                {
                    AddDummyData(realm, singleTransaction);

                    await GetSession(realm).WaitForUploadAsync();
                }

                using (var asyncRealm = await GetRealmAsync(asyncConfig))
                {
                    Assert.That(asyncRealm.All <IntPrimaryKeyWithValueObject>().Count(), Is.EqualTo(500));
                }
            });
        }
예제 #2
0
        private async Task <Realm> GetPartialRealm(Action <SyncConfiguration> setupConfig = null, [CallerMemberName] string realmPath = null)
        {
            SyncTestHelpers.RequiresRos();

            var user = await SyncTestHelpers.GetUserAsync();

            var config = new SyncConfiguration(user, SyncTestHelpers.RealmUri($"~/{realmPath}"), Guid.NewGuid().ToString())
            {
                ObjectClasses = new[] { typeof(ObjectA), typeof(ObjectB) },
                IsPartial     = true
            };

            setupConfig?.Invoke(config);

            using (var original = GetRealm(config))
            {
                original.Write(() =>
                {
                    for (var i = 0; i < 10; i++)
                    {
                        original.Add(new ObjectA
                        {
                            StringValue = "A #" + i,
                            IntValue    = i,
                            B           = new ObjectB
                            {
                                StringValue = "B #" + i,
                                BoolValue   = i % 2 == 0,
                            }
                        });
                    }
                });

                await GetSession(original).WaitForUploadAsync();
            }

            try
            {
                Realm.DeleteRealm(config);
            }
            catch
            {
            }

            config = new SyncConfiguration(config.User, config.ServerUri, config.DatabasePath + "_partial")
            {
                ObjectClasses = config.ObjectClasses,
                IsPartial     = true
            };

            var result = GetRealm(config);

            await GetSession(result).WaitForDownloadAsync();

            Assert.That(result.All <ObjectB>().Count(), Is.EqualTo(0));
            Assert.That(result.All <ObjectA>().Count(), Is.EqualTo(0));

            return(result);
        }
예제 #3
0
 public void TrustedCA_WhenFileDoesntExist_Throws()
 {
     AsyncContext.Run(async() =>
     {
         var user   = await SyncTestHelpers.GetUserAsync();
         var config = new SyncConfiguration(user, SyncTestHelpers.RealmUri("~/TrustedCA_WhenFileDoesntExist_Throws"))
         {
             TrustedCAPath = "something.pem"
         };
         Assert.That(() => GetRealm(config), Throws.TypeOf <FileNotFoundException>());
     });
 }
예제 #4
0
        public void User_OfferPermissions_WhenNoAccess_ShouldThrow()
        {
            AsyncContext.Run(async() =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();

                var realmUrl = SyncTestHelpers.RealmUri($"{alice.Identity}/testPermission").AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                await AssertThrows <ArgumentException>(() => alice.OfferPermissionsAsync(realmUrl, AccessLevel.None));
            });
        }
예제 #5
0
        public void User_OfferPermissions_WhenExpired_ShouldThrow()
        {
            AsyncContext.Run(async() =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();

                var realmUrl = SyncTestHelpers.RealmUri($"{alice.Identity}/testPermission").AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                await AssertThrows <ArgumentException>(() => alice.OfferPermissionsAsync(realmUrl, AccessLevel.Write, DateTimeOffset.UtcNow.AddDays(-1)));
            });
        }
예제 #6
0
        private async Task<string> GrantPermissions(User granter, User receiver, bool mayRead = true, bool mayWrite = true, bool mayManage = false, string realmUrl = null)
        {
            var permissionOffer = await CreateOffer(granter, mayRead, mayWrite, mayManage, realmUrl: realmUrl);

            Assert.That(permissionOffer.Status, Is.EqualTo(ManagementObjectStatus.Success));
            Assert.That(permissionOffer.Token, Is.Not.Null);

            var permissionResponse = await CreateResponse(receiver, permissionOffer.Token);
            Assert.That(permissionResponse.Status, Is.EqualTo(ManagementObjectStatus.Success));
            Assert.That(permissionResponse.RealmUrl, Is.Not.Null);

            return SyncTestHelpers.RealmUri(permissionResponse.RealmUrl).AbsoluteUri;
        }
예제 #7
0
        private async Task <Realm> GetSyncedRealm(Type objectType)
        {
            var credentials = Credentials.UsernamePassword(Constants.AdminUsername, Constants.AdminPassword, false);
            var user        = await User.LoginAsync(credentials, SyncTestHelpers.AuthServerUri);

            var configuration = new SyncConfiguration(user, SyncTestHelpers.RealmUri($"~/merge_by_pk_{objectType.Name}"), Guid.NewGuid().ToString())
            {
                ObjectClasses = new[] { objectType }
            };

            Realm.DeleteRealm(configuration);

            return(GetRealm(configuration));
        }
예제 #8
0
        public void WriteToReadOnlyRealm_ThrowsPermissionDenied()
        {
            SyncTestHelpers.RequiresRos();

            AsyncContext.Run(async () =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();
                var bob = await SyncTestHelpers.GetUserAsync();

                var realmPath = $"/{alice.Identity}/willBeReadonly";
                var realmUrl = SyncTestHelpers.RealmUri(realmPath).AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                // Give Bob just read permissions
                await alice.ApplyPermissionsAsync(PermissionCondition.UserId(bob.Identity), realmUrl, AccessLevel.Read);

                var config = new SyncConfiguration(bob, new Uri(realmUrl), Guid.NewGuid().ToString());

                var sessionErrorTask = TestHelpers.EventToTask<ErrorEventArgs>(h => Session.Error += h, h => Session.Error -= h);

                using (var realm = GetRealm(config))
                {
                    realm.Write(() => realm.Add(new Person()));

                    try
                    {
                        // Sometimes PermissionDenied will be thrown too fast moving the session to an error state
                        await GetSession(realm).WaitForUploadAsync();
                    }
                    catch
                    {
                    }
                }

                var sessionError = await sessionErrorTask.Timeout(1000);
                Assert.That(sessionError.Exception, Is.TypeOf<PermissionDeniedException>());

                var pde = (PermissionDeniedException)sessionError.Exception;

                Assert.That(pde.ErrorCode, Is.EqualTo(ErrorCode.PermissionDenied));
                Assert.That(File.Exists(config.DatabasePath), Is.True);

                var result = pde.DeleteRealmUserInfo(deleteRealm: true);

                Assert.That(result, Is.True);
                Assert.That(File.Exists(config.DatabasePath), Is.False);
            });
        }
        public void GetInstanceAsync_OpensReadonlyRealm(bool singleTransaction)
        {
            SyncTestHelpers.RequiresRos();

            AsyncContext.Run(async() =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();
                var bob   = await SyncTestHelpers.GetUserAsync();

                var realmUri    = SyncTestHelpers.RealmUri($"{alice.Identity}/GetInstanceAsync_OpensReadonlyRealm");
                var aliceConfig = new FullSyncConfiguration(realmUri, alice, Guid.NewGuid().ToString());
                var aliceRealm  = GetRealm(aliceConfig);

                await alice.ApplyPermissionsAsync(PermissionCondition.UserId(bob.Identity), realmUri.AbsoluteUri, AccessLevel.Read).Timeout(1000);

                AddDummyData(aliceRealm, singleTransaction);

                var bobConfig = new FullSyncConfiguration(realmUri, bob, Guid.NewGuid().ToString());
                var bobRealm  = await GetRealmAsync(bobConfig);

                var bobsObjects   = bobRealm.All <IntPrimaryKeyWithValueObject>();
                var alicesObjects = aliceRealm.All <IntPrimaryKeyWithValueObject>();
                Assert.That(bobsObjects.Count(), Is.EqualTo(alicesObjects.Count()));

                var bobTcs = new TaskCompletionSource <object>();
                bobsObjects.AsRealmCollection().CollectionChanged += (sender, e) =>
                {
                    bobTcs.TrySetResult(null);
                };

                aliceRealm.Write(() =>
                {
                    aliceRealm.Add(new IntPrimaryKeyWithValueObject
                    {
                        Id          = 9999,
                        StringValue = "Some value"
                    });
                });

                await bobTcs.Task.Timeout(1000);

                Assert.That(bobsObjects.Count(), Is.EqualTo(alicesObjects.Count()));

                var bobObject = bobRealm.Find <IntPrimaryKeyWithValueObject>(9999);
                Assert.That(bobObject, Is.Not.Null);
                Assert.That(bobObject.StringValue, Is.EqualTo("Some value"));
            });
        }
예제 #10
0
        private async Task TestApplyPermissions(User alice, User bob, PermissionCondition condition)
        {
            var realmPath = $"/{alice.Identity}/testPermission";
            var realmUrl = SyncTestHelpers.RealmUri(realmPath).AbsoluteUri;
            EnsureRealmExists(alice, realmUrl);

            // Grant write permissions
            await alice.ApplyPermissionsAsync(condition, realmUrl, AccessLevel.Write);

            await ValidateWriteAndSync(realmUrl, alice, bob, 1, 2);
            await AssertPermissions(alice, bob, realmPath, AccessLevel.Write);

            // Revoke permissions
            await alice.ApplyPermissionsAsync(condition, realmUrl, AccessLevel.None);

            await AssertPermissions(alice, bob, realmPath, AccessLevel.None);
        }
예제 #11
0
        public void PermissionChange_UpdatesPermissionRealm()
        {
            SyncTestHelpers.RequiresRos();

            AsyncContext.Run(async () =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();
                var bob = await SyncTestHelpers.GetUserAsync();

                var permissionRealm = alice.GetPermissionRealm();
                var tcs = new TaskCompletionSource<PathPermission>();
                var aliceId = alice.Identity; // LINQ :/
                var token = permissionRealm.All<PathPermission>()
                                           .Where(p => p.UserId != aliceId)
                                           .SubscribeForNotifications((sender, changes, error) =>
                                           {
                                               if (sender.Count > 0)
                                               {
                                                   try
                                                   {
                                                       tcs.TrySetResult(sender.Single());
                                                   }
                                                   catch (Exception ex)
                                                   {
                                                       tcs.TrySetException(ex);
                                                   }
                                               }
                                           });

                var realmPath = $"/{alice.Identity}/testPermission";
                var realmUrl = SyncTestHelpers.RealmUri(realmPath).AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                await CreateChange(alice, bob.Identity, realmUrl);
                var permission = await tcs.Task.Timeout(2000);

                Assert.That(permission.UserId, Is.EqualTo(bob.Identity));
                Assert.That(permission.Path, Is.EqualTo(realmPath));
                Assert.That(permission.MayRead, Is.True);
                Assert.That(permission.MayWrite, Is.False);
                Assert.That(permission.MayManage, Is.False);

                token.Dispose();
                permissionRealm.Dispose();
            });
        }
예제 #12
0
        public void User_OfferPermissions_GrantsPermissions()
        {
            AsyncContext.Run(async() =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();
                var bob   = await SyncTestHelpers.GetUserAsync();

                var realmPath = $"/{alice.Identity}/testPermission";
                var realmUrl  = SyncTestHelpers.RealmUri(realmPath).AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                var token     = await alice.OfferPermissionsAsync(realmUrl, AccessLevel.Write).Timeout(2000);
                var alicesUrl = await bob.AcceptPermissionOfferAsync(token).Timeout(2000);

                Assert.That($"realm://{Constants.ServerUrl}:9080/{alicesUrl}", Is.EqualTo(realmUrl));

                await AssertPermissions(alice, bob, realmPath, AccessLevel.Write).Timeout(10000);
            });
        }
        private async Task <Realm> GetPartialRealm(Action <SyncConfiguration> setupConfig = null, [CallerMemberName] string realmPath = null)
        {
            var user = await SyncTestHelpers.GetUserAsync();

            var config = new SyncConfiguration(user, SyncTestHelpers.RealmUri($"~/{realmPath}"))
            {
                ObjectClasses = new[] { typeof(ObjectA), typeof(ObjectB) }
            };

            setupConfig?.Invoke(config);

            using (var original = GetRealm(config))
            {
                original.Write(() =>
                {
                    for (var i = 0; i < 10; i++)
                    {
                        original.Add(new ObjectA
                        {
                            StringValue = "A #" + i,
                            IntValue    = i,
                            B           = new ObjectB
                            {
                                StringValue = "B #" + i,
                                BoolValue   = i % 2 == 0,
                            }
                        });
                    }
                });

                await GetSession(original).WaitForUploadAsync();
            }

            Realm.DeleteRealm(config);

            config = new SyncConfiguration(config.User, config.ServerUri, config.DatabasePath + "_partial")
            {
                ObjectClasses = config.ObjectClasses,
                IsPartial     = true
            };

            return(GetRealm(config));
        }
예제 #14
0
        public void GetInstanceAsync_CreatesNonExistentRealm()
        {
            AsyncContext.Run(async() =>
            {
                var user     = await SyncTestHelpers.GetUserAsync();
                var realmUri = SyncTestHelpers.RealmUri("~/GetInstanceAsync_CreatesNonExistentRealm");
                var config   = new SyncConfiguration(user, realmUri, Guid.NewGuid().ToString());

                try
                {
                    await GetRealmAsync(config);
                }
                catch (Exception ex)
                {
                    Assert.That(ex, Is.TypeOf <RealmException>().And.InnerException.TypeOf <SessionException>());
                    var sessionException = (SessionException)ex.InnerException;
                    Assert.That(sessionException.ErrorCode, Is.EqualTo((ErrorCode)89));
                    Assert.That(sessionException.Message, Contains.Substring("Operation canceled"));
                }
            });
        }
예제 #15
0
        private async Task<T> CreatePermissionObject<T>(User user, Func<string, T> itemFactory, string realmUrl = null) where T : RealmObject, IPermissionObject
        {
            realmUrl = realmUrl ?? SyncTestHelpers.RealmUri($"{user.Identity}/offer").AbsoluteUri;
            EnsureRealmExists(user, realmUrl);

            var managementRealm = user.GetManagementRealm();
            var item = itemFactory(realmUrl);
            managementRealm.Write(() => managementRealm.Add(item));
            var tcs = new TaskCompletionSource<object>();

            item.PropertyChanged += (sender, e) =>
            {
                if (e.PropertyName == nameof(IPermissionObject.Status))
                {
                    tcs.TrySetResult(null);
                }
            };

            await tcs.Task.Timeout(5000);

            return item;
        }
예제 #16
0
        public void User_AcceptPermissionOffer_WhenOfferExpired_ShouldGetError()
        {
            AsyncContext.Run(async() =>
            {
                var alice = await SyncTestHelpers.GetUserAsync();
                var bob   = await SyncTestHelpers.GetUserAsync();

                var realmUrl = SyncTestHelpers.RealmUri($"{alice.Identity}/testPermission").AbsoluteUri;
                EnsureRealmExists(alice, realmUrl);

                var token = await alice.OfferPermissionsAsync(realmUrl, AccessLevel.Write, expiresAt: DateTimeOffset.UtcNow.AddSeconds(1));

                Assert.That(token, Is.Not.Null);

                await Task.Delay(2000);

                await AssertThrows <PermissionException>(() => bob.AcceptPermissionOfferAsync(token), ex =>
                {
                    Assert.That(ex.ErrorCode, Is.EqualTo(ErrorCode.ExpiredPermissionOffer));
                });
            });
        }
        private async Task <Uri> CreateRealm(Action <Realm> assignRoles = null, bool addObjects = true)
        {
            var uri   = SyncTestHelpers.RealmUri(Guid.NewGuid().ToString());
            var admin = await SyncTestHelpers.GetAdminUserAsync();

            var config = new SyncConfiguration(admin, uri)
            {
                ObjectClasses = new[] { typeof(ObjectWithPermissions) },
                IsPartial     = true
            };

            using (var realm = GetRealm(config))
            {
                var objects      = realm.All <ObjectWithPermissions>();
                var subscription = await SubscribeToObjectsAsync(realm);

                if (addObjects)
                {
                    Assert.That(subscription.Results.Count(), Is.EqualTo(0));
                    AddObjectsToRealm(realm, new[] { 1, 2, 3 });

                    await WaitForSyncAsync(realm);

                    Assert.That(subscription.Results.Count(), Is.EqualTo(3));
                }

                if (assignRoles != null)
                {
                    realm.Write(() =>
                    {
                        assignRoles(realm);
                    });
                }

                await WaitForSyncAsync(realm);
            }

            return(uri);
        }
예제 #18
0
        private void TestSSLCore(Action <SyncConfiguration> setupSecureConfig, bool openAsync)
        {
            AsyncContext.Run(async() =>
            {
                var user          = await SyncTestHelpers.GetUserAsync();
                const string path = "~/TestSSLCore";
                var realmUri      = SyncTestHelpers.RealmUri(path);
                var config        = new SyncConfiguration(user, realmUri);

                var secureRealmUri = SyncTestHelpers.SecureRealmUri(path);
                var secureConfig   = new SyncConfiguration(user, secureRealmUri, config.DatabasePath + "2");
                setupSecureConfig(secureConfig);

                using (var realm = GetRealm(config))
                {
                    realm.Write(() =>
                    {
                        realm.Add(new IntPrimaryKeyWithValueObject
                        {
                            Id          = 1,
                            StringValue = "some value"
                        });
                    });

                    await GetSession(realm).WaitForUploadAsync();
                }

                using (var newRealm = await SyncTestHelpers.GetInstanceAsync(secureConfig, openAsync))
                {
                    CleanupOnTearDown(newRealm);

                    var items = newRealm.All <IntPrimaryKeyWithValueObject>();

                    Assert.That(items.Count(), Is.EqualTo(1));
                    Assert.That(items.Single().StringValue, Is.EqualTo("some value"));
                }
            });
        }
예제 #19
0
        private async Task <Realm> GetQueryBasedRealm(bool openAsync, [CallerMemberName] string realmPath = null)
        {
            SyncTestHelpers.RequiresRos();

            var user = await SyncTestHelpers.GetUserAsync();

            var config = new QueryBasedSyncConfiguration(SyncTestHelpers.RealmUri($"~/{realmPath}_{openAsync}"), user, Guid.NewGuid().ToString())
            {
                ObjectClasses = new[] { typeof(ObjectA), typeof(ObjectB) }
            };

            using (var original = GetRealm(config))
            {
                original.Write(() =>
                {
                    for (var i = 0; i < 10; i++)
                    {
                        original.Add(new ObjectA
                        {
                            StringValue = "A #" + i,
                            IntValue    = i,
                            B           = new ObjectB
                            {
                                StringValue = "B #" + i,
                                BoolValue   = i % 2 == 0,
                            }
                        });
                    }
                });

                await GetSession(original).WaitForUploadAsync();
            }

            try
            {
                Realm.DeleteRealm(config);
            }
            catch
            {
            }

            config = new QueryBasedSyncConfiguration(config.ServerUri, config.User, config.DatabasePath + "_partial")
            {
                ObjectClasses = config.ObjectClasses
            };

            Realm result;

            // We test both `GetInstance` and `GetInstanceAsync` to guard against regressions:
            // https://github.com/realm/realm-dotnet/issues/1814
            if (openAsync)
            {
                result = await GetRealmAsync(config).Timeout(5000);
            }
            else
            {
                result = GetRealm(config);
                await GetSession(result).WaitForDownloadAsync();
            }

            Assert.That(result.All <ObjectB>().Count(), Is.EqualTo(0));
            Assert.That(result.All <ObjectA>().Count(), Is.EqualTo(0));

            return(result);
        }