From b321808f4b2127e60855848272f051acb8d16ca6 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 25 Apr 2018 10:23:47 +0100 Subject: [PATCH] Add password reset wrappers (#1699). (#1757) * Add password reset wrappers (#1699). --- CHANGELOG.md | 2 +- docs/sync.js | 49 +++++++++++++++++++++++++++++++ lib/index.d.ts | 8 +++++ lib/user-methods.js | 71 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cad9dd63..184a94fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ X.Y.Z Release notes * None. ### Enhancements -* None. +* Add password reset wrappers (#1699). ### Bug fixes * Fixed logout error due to fetch body not being stringified (#1731). diff --git a/docs/sync.js b/docs/sync.js index cd435ea5..0e3c02f6 100644 --- a/docs/sync.js +++ b/docs/sync.js @@ -270,6 +270,55 @@ class User { */ static register(server, username, password, callback) {} + /** + * Request a password reset email to be sent to a user's email. + * This will not throw an exception, even if the email doesn't belong to a Realm Object Server user. + * + * This can only be used for users who authenticated with the 'password' provider, and passed a valid email address as a username. + * + * @param {string} server - authentication server + * @param {string} email - The email that corresponds to the user's username. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static requestPasswordReset(server, email) {} + + /** + * Complete the password reset flow by using the reset token sent to the user's email as a one-time authorization token to change the password. + * + * By default, Realm Object Server will send a link to the user's email that will redirect to a webpage where they can enter their new password. + * If you wish to provide a native UX, you may wish to modify the password authentication provider to use a custom URL with deep linking, so you can + * open the app, extract the token, and navigate to a view that allows to change the password within the app. + * + * @param {string} server - authentication server + * @param {string} reset_token - The token that was sent to the user's email address. + * @param {string} new_password - The user's new password. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static completePasswordReset(server, reset_token, new_password) {} + + /** + * Request an email confirmation email to be sent to a user's email. + * This will not throw an exception, even if the email doesn't belong to a Realm Object Server user. + * + * @param {string} server - authentication server + * @param {string} email - The email that corresponds to the user's username. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static requestEmailConfirmation(server, email) {} + + /** + * Complete the email confirmation flow by using the confirmation token sent to the user's email as a one-time authorization token to confirm their email. + * + * By default, Realm Object Server will send a link to the user's email that will redirect to a webpage where they can enter their new password. + * If you wish to provide a native UX, you may wish to modify the password authentication provider to use a custom URL with deep linking, so you can + * open the app, extract the token, and navigate to a view that allows to confirm the email within the app. + * + * @param {string} server - authentication server + * @param {string} confirmation_token - The token that was sent to the user's email address. + * @return {Promise} A promise which is resolved when the request has been sent. + */ + static confirmEmail(server, confirmation_token) {} + /** * Create an admin user for the given authentication server with an existing token * @param {string} adminToken - existing admin token diff --git a/lib/index.d.ts b/lib/index.d.ts index 664168e4..7f80ad01 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -296,6 +296,14 @@ declare namespace Realm.Sync { static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }, callback: (error: Error | null, user: User | null) => void): void; static registerWithProvider(server: string, options: { provider: string, providerToken: string, userInfo: any }): Promise; + static requestPasswordReset(server: string, email: string): Promise; + + static completePasswordReset(server:string, reset_token:string, new_password:string): Promise; + + static requestEmailConfirmation(server:string, email:string): Promise; + + static confirmEmail(server:string, confirmation_token:string): Promise; + authenticate(server: string, provider: string, options: any): Promise; logout(): void; openManagementRealm(): Realm; diff --git a/lib/user-methods.js b/lib/user-methods.js index a15e31ae..f83b2a86 100644 --- a/lib/user-methods.js +++ b/lib/user-methods.js @@ -275,6 +275,32 @@ function _authenticate(userConstructor, server, json, callback) { } } +function _updateAccount(userConstructor, server, json) { + const url = append_url(server, 'auth/password/updateAccount'); + const options = { + method: 'POST', + body: JSON.stringify(json), + headers: postHeaders, + open_timeout: 5000 + }; + + return performFetch(url, options) + .then((response) => { + const contentType = response.headers.get('Content-Type'); + if (contentType.indexOf('application/json') === -1) { + return response.text().then((body) => { + throw new AuthError({ + title: `Could not update user account: Realm Object Server didn't respond with valid JSON`, + body, + }); + }); + } + if (!response.ok) { + return response.json().then((body) => Promise.reject(new AuthError(body))); + } + }); +} + const staticMethods = { get current() { const allUsers = this.all; @@ -379,6 +405,51 @@ const staticMethods = { return _authenticate(this, server, json) }, + requestPasswordReset(server, email) { + checkTypes(arguments, ['string', 'string']); + const json = { + provider_id: email, + data: { action: 'reset_password' } + }; + + return _updateAccount(this, server, json); + }, + + completePasswordReset(server, reset_token, new_password) { + checkTypes(arguments, ['string', 'string']); + const json = { + data: { + action: 'complete_reset', + token: reset_token, + new_password: new_password + } + }; + + return _updateAccount(this, server, json); + }, + + requestEmailConfirmation(server, email) { + checkTypes(arguments, ['string', 'string']); + const json = { + provider_id: email, + data: { action: 'request_email_confirmation' } + }; + + return _updateAccount(this, server, json); + }, + + confirmEmail(server, confirmation_token) { + checkTypes(arguments, ['string', 'string']); + const json = { + data: { + action: 'confirm_email', + token: confirmation_token + } + }; + + return _updateAccount(this, server, json); + }, + _refreshAccessToken: refreshAccessToken, };