diff --git a/CHANGELOG.md b/CHANGELOG.md index be46681f..0f2538f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ X.Y.Z Release notes * Added various methods for permission management (#1204). ### Bug fixes -* None +* Removed `loginWithProvider` from TypeScript definition files. This API never existed and was incorrectly added. 1.10.3 Release notes (2017-8-16) diff --git a/docs/sync.js b/docs/sync.js index f2f25bff..609f1663 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -135,9 +135,10 @@ class User { * @param {string} server - authentication server * @param {string} username * @param {string} password - * @param {function(error, user)} callback - called with the following arguments: + * @param {function(error, user)} [callback] - called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success + * @returns {Promise} Returns a promise with a user only if the callback was not specified */ static login(server, username, password, callback) {} @@ -148,9 +149,10 @@ class User { * @param {string} options.provider - The provider type * @param {string} options.providerToken - The access token for the given provider * @param {object} [options.userInfo] - A map containing additional data required by the provider - * @param {function(error, User)} callback - called with the following arguments: + * @param {function(error, User)} [callback] - an optional called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success + * @return {Promise} Returns a promise with a user only if the callback was not specified */ static registerWithProvider(server, options, callback) {} @@ -159,9 +161,10 @@ class User { * @param {string} server - authentication server * @param {string} username * @param {string} password - * @param {function(error, user)} callback - called with the following arguments: + * @param {function(error, user)} [callback] - called with the following arguments: * - `error` - an Error object is provided on failure * - `user` - a valid User object on success + * @return {Promise} Returns a promise with a user only if the callback was not specified */ static register(server, username, password, callback) {} diff --git a/lib/extensions.js b/lib/extensions.js index 3ec8f6cf..4e1d3de0 100644 --- a/lib/extensions.js +++ b/lib/extensions.js @@ -77,7 +77,9 @@ module.exports = function(realmConstructor) { }, openAsync(config, progressCallback, callback) { - + const message = "Realm.openAsync is now deprecated in favor of Realm.open. This function will be removed in future versions."; + (console.warn || console.log).call(console, message); + if (!callback) { callback = progressCallback; progressCallback = null; @@ -99,7 +101,7 @@ module.exports = function(realmConstructor) { //FIXME: RN hangs here. Remove when node's makeCallback alternative is implemented setTimeout(() => { callback(null, syncedRealm); }, 1); } catch (e) { - callback(e); + setTimeout(() => { callback(e); }, 1); } } }); diff --git a/lib/index.d.ts b/lib/index.d.ts index 9917de85..242174eb 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -264,9 +264,11 @@ declare namespace Realm.Sync { readonly server: string; readonly token: string; static adminUser(adminToken: string, server?: string): User; + static login(server: string, username: string, password: string): Promise; static login(server: string, username: string, password: string, callback: (error: any, user: User) => void): void; - static loginWithProvider(server: string, provider: string, providerToken: string, callback: (error: any, user: User) => void): void; + static register(server: string, username: string, password: string): Promise; static register(server: string, username: string, password: string, callback: (error: any, user: User) => void): void; + static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }): Promise; static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void; logout(): void; openManagementRealm(): Realm; @@ -446,6 +448,7 @@ declare class Realm { */ static open(config: Realm.Configuration): ProgressPromise; /** + * @deprecated in favor of `Realm.open` * Open a realm asynchronously with a callback. If the realm is synced, it will be fully synchronized before it is available. * @param {Configuration} config * @param {ProgressNotificationCallback} progressCallback? a progress notification callback for 'download' direction and 'forCurrentlyOutstandingWork' mode diff --git a/lib/user-methods.js b/lib/user-methods.js index 7994d71d..0b2d9d4e 100644 --- a/lib/user-methods.js +++ b/lib/user-methods.js @@ -114,6 +114,15 @@ function refreshAccessToken(user, localRealmPath, realmUrl) { }); } +/** + * 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` + * @param {object} userConstructor + * @param {string} server the http or https server url + * @param {object} json the json to post to the auth endpoint + * @param {Function} callback an optional callback with an error and user parameter + * @returns {Promise} only returns a promise if the callback parameter was omitted + */ function _authenticate(userConstructor, server, json, callback) { json.app_id = ''; const url = auth_url(server); @@ -123,7 +132,7 @@ function _authenticate(userConstructor, server, json, callback) { headers: postHeaders, open_timeout: 5000 }; - performFetch(url, options) + const promise = performFetch(url, options) .then((response) => { if (response.status !== 200) { return response.json().then((body) => callback(new AuthError(body))); @@ -136,8 +145,18 @@ function _authenticate(userConstructor, server, json, callback) { callback(undefined, userConstructor.createUser(server, identity, token, false, isAdmin)); }) } + }); + + if (callback) { + promise.then(user => { + callback(null, user); }) - .catch(callback); + .catch(err => { + callback(err) + }); + } else { + return promise; + } } const staticMethods = { @@ -164,20 +183,30 @@ const staticMethods = { register(server, username, password, callback) { checkTypes(arguments, ['string', 'string', 'string', 'function']); - _authenticate(this, server, { + const json = { provider: 'password', user_info: { password: password, register: true }, data: username - }, callback); + }; + if (callback) { + _authenticate(this, server, json, callback); + } else { + return _authenticate(this, server) + } }, login(server, username, password, callback) { checkTypes(arguments, ['string', 'string', 'string', 'function']); - _authenticate(this, server, { + const json = { provider: 'password', user_info: { password: password }, data: username - }, callback); + }; + if (callback) { + _authenticate(this, server, json, callback); + } else { + return _authenticate(this, server) + } }, registerWithProvider(server, options, callback) { @@ -195,16 +224,20 @@ const staticMethods = { checkTypes(arguments, ['string', 'object', 'function']); } - let reqOptions = { + let json = { provider: options.provider, data: options.providerToken, }; if (options.userInfo) { - reqOptions.user_info = options.userInfo; + json.user_info = options.userInfo; } - _authenticate(this, server, reqOptions, callback); + if (callback) { + _authenticate(this, server, json, callback); + } else { + return _authenticate(this, server) + } }, _refreshAccessToken: refreshAccessToken @@ -233,13 +266,11 @@ const instanceMethods = { }, retrieveAccount(provider, provider_id) { checkTypes(arguments, ['string', 'string']); - const url = url_parse(this.server); url.set('pathname', `/api/providers/${provider}/accounts/${provider_id}`); const headers = { Authorization: this.token }; - const options = { method: 'GET', headers, diff --git a/tests/js/session-tests.js b/tests/js/session-tests.js index 153bd6e9..6f61bcfd 100644 --- a/tests/js/session-tests.js +++ b/tests/js/session-tests.js @@ -50,32 +50,6 @@ function uuid() { }); } -function promisifiedRegister(server, username, password) { - return new Promise((resolve, reject) => { - Realm.Sync.User.register(server, username, password, (error, user) => { - if (error) { - console.log(`promisifiedRegister ${error}`); - reject(error); - } else { - resolve(user); - } - }); - }); -} - -function promisifiedLogin(server, username, password) { - return new Promise((resolve, reject) => { - Realm.Sync.User.login(server, username, password, (error, user) => { - if (error) { - console.log(`promisifiedLogin ${error}`); - reject(error); - } else { - resolve(user); - } - }); - }); -} - function runOutOfProcess(nodeJsFilePath) { var nodeArgs = Array.prototype.slice.call(arguments); let tmpDir = tmp.dirSync(); @@ -111,7 +85,7 @@ module.exports = { }, testProperties() { - return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', uuid(), 'password').then(user => { return new Promise((resolve, reject) => { const accessTokenRefreshed = this; @@ -162,7 +136,7 @@ module.exports = { return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { const accessTokenRefreshed = this; let successCounter = 0; @@ -198,7 +172,7 @@ module.exports = { return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { return new Promise((resolve, reject) => { const accessTokenRefreshed = this; let successCounter = 0; @@ -251,7 +225,7 @@ module.exports = { return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { const accessTokenRefreshed = this; let successCounter = 0; let progressNotificationCalled = false; @@ -287,7 +261,7 @@ module.exports = { return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { return new Promise((resolve, reject) => { let progressNotificationCalled = false; let config = { @@ -334,7 +308,7 @@ module.exports = { return runOutOfProcess(__dirname + '/download-api-helper.js', username, realmName, REALM_MODULE_PATH) .then(() => { - return promisifiedLogin('http://localhost:9080', username, 'password').then(user => { + return Realm.Sync.User.login('http://localhost:9080', username, 'password').then(user => { return new Promise((resolve, reject) => { const accessTokenRefreshed = this; let successCounter = 0; @@ -439,7 +413,7 @@ module.exports = { }, testErrorHandling() { - return promisifiedRegister('http://localhost:9080', uuid(), 'password').then(user => { + return Realm.Sync.User.register('http://localhost:9080', uuid(), 'password').then(user => { return new Promise((resolve, _reject) => { const config = { sync: { user, url: 'realm://localhost:9080/~/myrealm' } }; config.sync.error = (sender, error) => { diff --git a/tests/js/user-tests.js b/tests/js/user-tests.js index 4d2a24ab..466f80ca 100644 --- a/tests/js/user-tests.js +++ b/tests/js/user-tests.js @@ -297,73 +297,55 @@ module.exports = { }, testRetrieveAccount() { - return new Promise((resolve, reject) => { - if (!isNodeProcess) { - resolve(); - } - - if (!global.testAdminUserInfo) { - reject("Test requires an admin user"); - } - - Realm.Sync.User.login('http://localhost:9080', global.testAdminUserInfo.username, global.testAdminUserInfo.password, (error, user) => { - if (error) { - reject(error); - } - + if (!isNodeProcess) { + return Promise.resolve() + } + if (!global.testAdminUserInfo) { + return Promise.reject("Test requires an admin user"); + } + return Realm.Sync.User.login('http://localhost:9080', global.testAdminUserInfo.username, global.testAdminUserInfo.password) + .then(user => { TestCase.assertTrue(user.isAdmin, "Test requires an admin user"); - - user.retrieveAccount('password', global.testAdminUserInfo.username) - .then(account => { - // { - // "provider_id": "admin", - // "provider": "password", - // "user": { - // "id": "07ac9a0a-a97a-4ee1-b53c-b05a6542035a", - // "isAdmin": true, - // } - // } - - TestCase.assertEqual(account.provider_id, global.testAdminUserInfo.username); - TestCase.assertEqual(account.provider, 'password'); - TestCase.assertTrue(account.user); - TestCase.assertTrue(account.user.isAdmin !== undefined); - TestCase.assertTrue(account.user.id); - resolve(); - }) - .catch(e => reject(e)); + return user.retrieveAccount() }) - }); + .then(account => { + // { + // "provider_id": "admin", + // "provider": "password", + // "user": { + // "id": "07ac9a0a-a97a-4ee1-b53c-b05a6542035a", + // "isAdmin": true, + // } + // } + TestCase.assertEqual(account.provider_id, global.testAdminUserInfo.username); + TestCase.assertEqual(account.provider, 'password'); + TestCase.assertTrue(account.user); + TestCase.assertTrue(account.user.isAdmin !== undefined); + TestCase.assertTrue(account.user.id); + }) + .catch(e => reject(e)); }, testRetrieveNotExistingAccount() { - return new Promise((resolve, reject) => { - if (!isNodeProcess) { - resolve(); - } - - if (!global.testAdminUserInfo) { - reject("Test requires an admin user"); - } - - Realm.Sync.User.login('http://localhost:9080', global.testAdminUserInfo.username, global.testAdminUserInfo.password, (error, user) => { - if (error) { - reject(error); - } - + if (!isNodeProcess) { + return Promise.resolve() + } + if (!global.testAdminUserInfo) { + return Promise.reject("Test requires an admin user"); + } + return Realm.Sync.User.login('http://localhost:9080', global.testAdminUserInfo.username, global.testAdminUserInfo.password) + .then(user => { TestCase.assertTrue(user.isAdmin, "Test requires an admin user"); - let notExistingUsername = uuid(); - user.retrieveAccount('password', notExistingUsername) - .then(account => { - reject("Retrieving not existing account should fail"); - }) - .catch(e => { - TestCase.assertEqual(e.code, 404); - resolve() - }); + return user.retrieveAccount('password', notExistingUsername) }) - }); + .then(account => { + reject("Retrieving not existing account should fail"); + }) + .catch(e => { + TestCase.assertEqual(e.code, 404); + resolve() + }); }, /* This test fails because of realm-object-store #243 . We should use 2 users.