Merge pull request #1409 from realm/kneth/bugfix/invalid-token

adminUser() throws an exception if token or url is invalid
This commit is contained in:
Brian Munkholm 2017-10-16 14:10:57 +02:00 committed by GitHub
commit 4055c9e047
6 changed files with 87 additions and 24 deletions

View File

@ -1,3 +1,14 @@
X.Y.Z Release notes
=============================================================
### Breaking changes
* `Realm.Sync.User.adminUser()` will now throw an exception if either token or server argument is invalid.
### Enhancements
* None.
### Bug fixes
* None.
2.0.0-rc22 Release notes (2017-10-13) 2.0.0-rc22 Release notes (2017-10-13)
============================================================= =============================================================
### Breaking changes ### Breaking changes

View File

@ -21,9 +21,9 @@
* migrated to the v2.x format. In case this migration * migrated to the v2.x format. In case this migration
* is not possible, an exception is thrown. The exception´s `message` property will be equal * is not possible, an exception is thrown. The exception´s `message` property will be equal
* to `IncompatibleSyncedRealmException`. The Realm is backed up, and the property `configuration` * to `IncompatibleSyncedRealmException`. The Realm is backed up, and the property `configuration`
* is a {Realm~Configuration} which refers to it. You can open it as a local, read-only Realm, and * is a {Realm~Configuration} which refers to it. You can open it as a local, read-only Realm, and
* copy objects to a new synced Realm. * copy objects to a new synced Realm.
* *
* @memberof Realm * @memberof Realm
*/ */
class Sync { class Sync {
@ -153,7 +153,7 @@ class IncompatibleSyncedRealmError {
* The name of the error is 'IncompatibleSyncedRealmError' * The name of the error is 'IncompatibleSyncedRealmError'
*/ */
get name() {} get name() {}
/** /**
* The {Realm~Configuration} of the backed up Realm. * The {Realm~Configuration} of the backed up Realm.
* @type {Realm~Configuration} * @type {Realm~Configuration}
@ -209,6 +209,7 @@ class User {
* @param {string} adminToken - existing admin token * @param {string} adminToken - existing admin token
* @param {string} server - authentication server * @param {string} server - authentication server
* @return {User} - admin user populated with the given token and server * @return {User} - admin user populated with the given token and server
* @throws {Error} If adminToken or server is invalid.
*/ */
static adminUser(adminToken, server) {} static adminUser(adminToken, server) {}

View File

@ -129,10 +129,10 @@ function refreshAccessToken(user, localRealmPath, realmUrl) {
/** /**
* The base authentication method. It fires a JSON POST to the server parameter plus the auth url * The base authentication method. It fires a JSON POST to the server parameter plus the auth url
* For example, if the server parameter is `http://myapp.com`, this url will post to `http://myapp.com/auth` * For example, if the server parameter is `http://myapp.com`, this url will post to `http://myapp.com/auth`
* @param {object} userConstructor * @param {object} userConstructor
* @param {string} server the http or https server url * @param {string} server the http or https server url
* @param {object} json the json to post to the auth endpoint * @param {object} json the json to post to the auth endpoint
* @param {Function} callback an optional callback with an error and user parameter * @param {Function} callback an optional callback with an error and user parameter
* @returns {Promise} only returns a promise if the callback parameter was omitted * @returns {Promise} only returns a promise if the callback parameter was omitted
*/ */
function _authenticate(userConstructor, server, json, callback) { function _authenticate(userConstructor, server, json, callback) {
@ -161,8 +161,8 @@ function _authenticate(userConstructor, server, json, callback) {
}); });
if (callback) { if (callback) {
promise.then(user => { promise.then(user => {
callback(null, user); callback(null, user);
}) })
.catch(err => { .catch(err => {
callback(err); callback(err);
@ -187,7 +187,19 @@ const staticMethods = {
adminUser(token, server) { adminUser(token, server) {
checkTypes(arguments, ['string', 'string']); checkTypes(arguments, ['string', 'string']);
return this._adminUser(server, token); const user = this._adminUser(server, token);
// FIXME: find a better way to detect that token or server is invalid
// check if object is empty
var isEmpty = true;
for(var prop in user) {
if (user.hasOwnProperty(prop)) {
isEmpty = false;
}
}
if (isEmpty) {
throw new Error('Invalid adminToken or server.');
}
return user;
}, },
register(server, username, password, callback) { register(server, username, password, callback) {
@ -197,12 +209,12 @@ const staticMethods = {
user_info: { password: password, register: true }, user_info: { password: password, register: true },
data: username data: username
}; };
if (callback) { if (callback) {
const message = "register(..., callback) is now deprecated in favor of register(): Promise<User>. This function argument will be removed in future versions."; const message = "register(..., callback) is now deprecated in favor of register(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message); (console.warn || console.log).call(console, message);
} }
return _authenticate(this, server, json, callback); return _authenticate(this, server, json, callback);
}, },
@ -213,7 +225,7 @@ const staticMethods = {
user_info: { password: password }, user_info: { password: password },
data: username data: username
}; };
if (callback) { if (callback) {
const message = "login(..., callback) is now deprecated in favor of login(): Promise<User>. This function argument will be removed in future versions."; const message = "login(..., callback) is now deprecated in favor of login(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message); (console.warn || console.log).call(console, message);
@ -224,7 +236,7 @@ const staticMethods = {
registerWithProvider(server, options, callback) { registerWithProvider(server, options, callback) {
// Compatibility with previous signature: // Compatibility with previous signature:
// registerWithProvider(server, provider, providerToken, callback) // registerWithProvider(server, provider, providerToken, callback)
if (arguments.length === 4) { if (arguments.length === 4) {
checkTypes(arguments, ['string', 'string', 'string', 'function']); checkTypes(arguments, ['string', 'string', 'string', 'function']);
@ -250,7 +262,7 @@ const staticMethods = {
const message = "registerWithProvider(..., callback) is now deprecated in favor of registerWithProvider(): Promise<User>. This function argument will be removed in future versions."; const message = "registerWithProvider(..., callback) is now deprecated in favor of registerWithProvider(): Promise<User>. This function argument will be removed in future versions.";
(console.warn || console.log).call(console, message); (console.warn || console.log).call(console, message);
} }
return _authenticate(this, server, json, callback); return _authenticate(this, server, json, callback);
}, },

View File

@ -71,14 +71,22 @@ module.exports = {
}, },
}; };
if (global.enableSyncTests) { if (global.enableSyncTests) {
module.exports.testEncryptionWithSync = function() { module.exports.testEncryptionWithSync = function() {
new Realm({ Realm.Sync.User.login('http://localhost:9080', global.testAdminUserInfo.username, global.testAdminUserInfo.password, (error, user) => {
encryptionKey: new Int8Array(64), if (error) {
sync: { reject(error);
user: Realm.Sync.User.adminUser('fake-token', 'http://fake-server'),
url: 'realm://fake-server'
} }
new Realm({
encryptionKey: new Int8Array(64),
sync: {
user: user,
url: 'realm://localhost:9080'
}
});
user.logout(); // FIXME: clearTestState() doesn't clean up enough and Realm.Sync.User.current might not work
resolve();
}); });
}; }
} }

View File

@ -49,7 +49,7 @@ if (global.enableSyncTests) {
// FIXME: Permission tests currently fail in chrome debugging mode. // FIXME: Permission tests currently fail in chrome debugging mode.
if (typeof navigator === 'undefined' || if (typeof navigator === 'undefined' ||
!/Chrome/.test(navigator.userAgent)) { // eslint-disable-line no-undef !/Chrome/.test(navigator.userAgent)) { // eslint-disable-line no-undef
TESTS.PermissionTests = require('./permission-tests'); TESTS.PermissionTests = require('./permission-tests');
} }
} }

View File

@ -129,11 +129,11 @@ module.exports = {
assertIsUser(user); assertIsUser(user);
Realm.Sync.User.register('http://localhost:9080', username, 'password', (error, user) => { Realm.Sync.User.register('http://localhost:9080', username, 'password', (error, user) => {
try { try {
assertIsAuthError(error, 611, "The provided credentials are invalid or the user does not exist."); assertIsAuthError(error, 611, "The provided credentials are invalid or the user does not exist.");
TestCase.assertUndefined(user); TestCase.assertUndefined(user);
resolve(); resolve();
} catch(e) { } catch(e) {
reject(e); reject(e);
} }
}); });
@ -371,6 +371,38 @@ module.exports = {
}); });
}, },
testAdminUser() {
return new Promise((resolve, reject) => {
if (!isNodeProcess) {
resolve();
}
// FIXME: check if adminUser() returns user iff valid token/server
let didThrow = false;
try {
let user = Realm.Sync.User.adminUser('THIS_IS_INVALID', 'http://localhost:9080');
}
catch (e) {
didThrow = true;
TestCase.assertTrue(e.message === 'Invalid adminToken or server.');
}
TestCase.assertTrue(didThrow);
// FIXME: find a way to set up a proper admin token
didThrow = false;
try {
Realm.Sync.User.adminUser('THIS_IS_VALID', 'http://foo.bar:9080');
}
catch (e) {
didThrow = true;
TestCase.assertTrue(e.message === 'Invalid adminToken or server.');
}
TestCase.assertTrue(didThrow);
resolve();
});
}
/* This test fails because of realm-object-store #243 . We should use 2 users. /* This test fails because of realm-object-store #243 . We should use 2 users.
testSynchronizeChangesWithTwoClientsAndOneUser() { testSynchronizeChangesWithTwoClientsAndOneUser() {
// Test Schema // Test Schema
@ -432,4 +464,3 @@ module.exports = {
}, */ }, */
}; };