Add better error message for wrong Realm types (#2151)

This commit is contained in:
Christian Melchior 2018-11-27 14:46:30 +01:00 committed by GitHub
parent 26723b8d94
commit 98b75a1317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 3 deletions

View File

@ -1,11 +1,10 @@
x.x.x Release notes (yyyy-MM-dd)
=============================================================
### Enhancements
* None.
* Using methods only available for Query-based Realms now throw a better error message if called on the wrong Realm file type.
### Fixed
* `_initializeSyncManager` missing when debugging React Native. Resulted in messages like `realmConstructor.Sync._initializeSyncManager is not a function` ([#2128](https://github.com/realm/realm-js/issues/2128), since v2.20.0)
* None.
### Compatibility
* Realm Object Server: 3.11.0 or later.

View File

@ -389,6 +389,9 @@ module.exports = function(realmConstructor) {
// Add instance methods to the Realm object that are only applied if Sync is
Object.defineProperties(realmConstructor.prototype, getOwnPropertyDescriptors({
permissions(arg) {
if (!this._isPartialRealm) {
throw new Error("Wrong Realm type. 'permissions()' is only available for Query-based Realms.");
}
// If no argument is provided, return the Realm-level permissions
if (arg === undefined) {
return this.objects('__Realm').filtered(`id = 0`)[0];
@ -404,6 +407,9 @@ module.exports = function(realmConstructor) {
},
subscriptions(name) {
if (!this._isPartialRealm) {
throw new Error("Wrong Realm type. 'subscriptions()' is only available for Query-based Realms.");
}
let all_subscriptions = this.objects('__ResultSets');
if (name) {
if (typeof(name) !== 'string') {
@ -429,6 +435,9 @@ module.exports = function(realmConstructor) {
},
unsubscribe(name) {
if (!this._isPartialRealm) {
throw new Error("Wrong Realm type. 'unsubscribe()' is only available for Query-based Realms.");
}
if (typeof(name) === 'string') {
if (name !== '') {
let named_subscriptions = this.objects('__ResultSets').filtered(`name == '${name}'`);

1
lib/index.d.ts vendored
View File

@ -821,7 +821,6 @@ declare class Realm {
*/
writeCopyTo(path: string, encryptionKey?: ArrayBuffer | ArrayBufferView): void;
privileges() : Realm.Permissions.Realm;
privileges() : Realm.Permissions.RealmPrivileges;
privileges(objectType: string | Realm.ObjectSchema | Function) : Realm.Permissions.ClassPrivileges;
privileges(obj: Realm.Object) : Realm.Permissions.ObjectPrivileges;

View File

@ -253,6 +253,7 @@ public:
static void get_is_closed(ContextType, ObjectType, ReturnValue &);
#if REALM_ENABLE_SYNC
static void get_sync_session(ContextType, ObjectType, ReturnValue &);
static void get_is_partial_realm(ContextType, ObjectType, ReturnValue &);
#endif
// static methods
@ -318,6 +319,7 @@ public:
{"isClosed", {wrap<get_is_closed>, nullptr}},
#if REALM_ENABLE_SYNC
{"syncSession", {wrap<get_sync_session>, nullptr}},
{"_isPartialRealm", {wrap<get_is_partial_realm>, nullptr}},
#endif
};
@ -818,6 +820,13 @@ void RealmClass<T>::get_sync_session(ContextType ctx, ObjectType object, ReturnV
}
}
template<typename T>
void RealmClass<T>::get_is_partial_realm(ContextType ctx, ObjectType object, ReturnValue &return_value) {
auto realm = *get_internal<T, RealmClass<T>>(object);
auto config = realm->config();
return_value.set(config.sync_config && config.sync_config->is_partial);
}
#endif
#if REALM_ENABLE_SYNC
@ -1219,12 +1228,17 @@ template<typename T>
void RealmClass<T>::privileges(ContextType ctx, ObjectType this_object, Arguments &args, ReturnValue &return_value) {
args.validate_maximum(1);
#if REALM_ENABLE_SYNC
using Privilege = realm::ComputedPrivileges;
auto has_privilege = [](Privilege actual, Privilege expected) {
return (static_cast<int>(actual) & static_cast<int>(expected)) == static_cast<int>(expected);
};
SharedRealm realm = *get_internal<T, RealmClass<T>>(this_object);
auto config = realm->config();
if (!(config.sync_config && config.sync_config->is_partial)) {
throw std::runtime_error("Wrong Realm type. 'privileges()' is only available for Query-based Realms.");
}
if (args.count == 0) {
auto p = realm->get_privileges();
ObjectType object = Object::create_empty(ctx);
@ -1261,6 +1275,9 @@ void RealmClass<T>::privileges(ContextType ctx, ObjectType this_object, Argument
Object::set_property(ctx, object, "subscribe", Value::from_boolean(ctx, has_privilege(p, Privilege::Query)));
Object::set_property(ctx, object, "setPermissions", Value::from_boolean(ctx, has_privilege(p, Privilege::SetPermissions)));
return_value.set(object);
#else
throw std::logic_error("Realm.privileges() can only be used with Query-based Realms.");
#endif
}
} // js

View File

@ -1465,4 +1465,31 @@ module.exports = {
realm.close();
},
testQueryBasedOnlyMethods: function() {
if (!global.enableSyncTests) {
return;
}
const realm = new Realm({sync: true});
TestCase.assertThrowsContaining(() => {
realm.privileges();
}, 'Wrong Realm type');
TestCase.assertThrowsContaining(() => {
realm.privileges('__Role');
}, 'Wrong Realm type');
TestCase.assertThrowsContaining(() => {
realm.permissions();
}, 'Wrong Realm type');
TestCase.assertThrowsContaining(() => {
realm.permissions('__Class');
}, 'Wrong Realm type');
TestCase.assertThrowsContaining(() => {
realm.subscriptions();
}, 'Wrong Realm type');
TestCase.assertThrowsContaining(() => {
realm.unsubscribe('foo');
}, 'Wrong Realm type');
} ,
};