import { constants } from '../enum/constants'; import { IReloginResponseDTO } from '../interfaces/dto/relogin-response-dto.interface'; import { IUserIdentityConfirmationStatus } from '../interfaces/identity-confirmation-status.interface'; import { AsyncUtils } from '../utils/async-utils'; import { Base64Utils } from '../utils/base64-utils'; import { FgBaseAPI } from './base-api'; export class FgIdentityAPI extends FgBaseAPI { cache: boolean; private _tokenForURL: string; private _window: any | null; constructor(args) { super(args); const { token, cache = true } = args; this.cache = cache; this._tokenForURL = token; this._window = null; } protected _afterLoad() { this.baseUrl += 'api/identity/'; } get baseIdentityUrl() { let publicBaseUrl = this.isProduction ? constants.urls.production : constants.urls.development; if (!publicBaseUrl.endsWith('/')) { publicBaseUrl += '/'; } return publicBaseUrl; } get identityPublicUrl() { const url = `${this.baseIdentityUrl}api/identity/public`; return url; } get changePasswordUrl() { let url = `${this.identityPublicUrl}/password?`; const headers = JSON.stringify(this._createHeaders()); const headersBase64 = Base64Utils.stringToBase64(headers); url += `headers=${headersBase64}`; if (!this.cache) { url += '&cache=false'; } return url; } get removeAccountUrl() { let url = `${this.identityPublicUrl}/delete?`; const headers = JSON.stringify(this._createHeaders()); const headersBase64 = Base64Utils.stringToBase64(headers); url += `headers=${headersBase64}`; if (!this.cache) { url += '&cache=false'; } return url; } get loginUrl() { let url = `${this.identityPublicUrl}?api-authorization=${this._tokenForURL}`; if (!this.cache) { url += '&cache=false'; } return url; } getViewProfileUrl(id: number) { let url = `${this.identityPublicUrl}/profile/${id}?`; const headers = JSON.stringify(this._createHeaders()); const headersBase64 = Base64Utils.stringToBase64(headers); url += `headers=${headersBase64}`; if (!this.cache) { url += '&cache=false'; } return url; } async tryToRelogin(token: string, refresh: string, session: string): Promise { const result = await this._post('login/token', { token, refresh, session }); return result; } async preLogin(code: string): Promise { const { secret } = await this._post('login/code', { code }); return secret; } async getAndUsePreLoginCode(code: string, secret: string) { const body = await this._delete('login/code', { code, secret }); if (body.ready) { const { ready, reloginToken, token } = body; return { ready, reloginToken, token }; } else { return { ready: false }; } } async getAccountConfirmationStatus(): Promise { const { status } = await this._get('user/confirm/email/status'); return status; } async sendAccountConfirmationRequestEmail(): Promise { const headers = JSON.stringify(this._createHeaders()); const headersBase64 = Base64Utils.stringToBase64(headers); await this._post('user/confirm/email/request', { headers: headersBase64 }); } openLoginWithRedirect() { location.href = this.loginUrl + '&redirect=' + encodeURIComponent(location.href); } openChangePasswordWithRedirect() { location.href = this.changePasswordUrl + '&redirect=' + encodeURIComponent(location.href); } openViewProfileWithRedirect(id: number) { location.href = this.getViewProfileUrl(id) + '&redirect=' + encodeURIComponent(location.href); } openRemoveAccountWithRedirect() { location.href = this.removeAccountUrl + '&redirect=' + encodeURIComponent(location.href); } async openChangePasswordWindow() { return await this.__openWindowAndWaitForResult(this.changePasswordUrl, 'Change Password'); } async openViewProfileWindow(id: number) { const url = this.getViewProfileUrl(id); const wdow = this._openWindow(url, 'User Profile'); if (wdow === null) { throw new Error('Your browser has blocked the creation of windows. Please enable it.'); } await AsyncUtils.waitForWithoutTimeout(() => wdow.closed); } async openRemoveAccountWindow() { return await this.__openWindowAndWaitForResult(this.removeAccountUrl, 'Remove Account'); } private async __openWindowAndWaitForResult(url, password) { return new Promise((resolve, reject) => { const wdow = this._openWindow(url, password); if (wdow === null) { return reject('Your browser has blocked the creation of windows. Please enable it.'); } window.addEventListener('message', e => { this.__waitForResult(resolve, reject, e); }); AsyncUtils.waitForWithoutTimeout(() => wdow.closed) .finally(() => setTimeout(() => reject('Cancelled'), 500)); }); } private __waitForResult(resolve, reject, e) { if (e.data) { let data; try { const parsedData = (typeof e.data === 'string') ? JSON.parse(e.data) : e.data; data = parsedData; } catch (err) { console.error('Error parsing window message', err); return; } const isMetamaskMessage = !!e.data.target; if (typeof data.data !== 'undefined' && !isMetamaskMessage) { if (data.success) { resolve(data.data); } else { reject(data.data.error); } } } } openLoginWindow() { return new Promise((resolve, reject) => { this._window = this._openWindow(this.loginUrl, 'Login'); window.addEventListener('message', e => { this.__waitForResult(resolve, reject, e); }); }); } getLoginUrl(cache = true, redirectUrl: string | null = null, preloginCode: string | null = null, httpEncode = false) { let url = this.identityPublicUrl + '?'; const args: string[] = []; const encode = x => { return (httpEncode ? encodeURI(x) : x); }; if (redirectUrl) { args.push(`redirect=${encode(redirectUrl)}`); } if (preloginCode) { args.push(`sid=${encode(preloginCode)}`); } if (!cache) { args.push('cache=false'); } args.push(`api-authorization=${this._tokenForURL}`); url += args.join('&'); return url; } isAccount(question: string): Promise { return this._get(`user/is/${question}`); } isAccountBanned(): Promise { return this.isAccount('banned'); } isAccountGuest(): Promise { return this.isAccount('guest'); } isAccountConfirmed() { return this.isAccount('confirmed'); } getLoggedProfile(scopes: string[]): Promise { return this.getUserProfile('me', scopes); } getUserProfile(id = 'me', scopes?: string[]): Promise { const query: any = {}; if (scopes) { query.scope = scopes.join(','); } return this._get(`user/account/${id}`, query); } updateUserProfile(data): Promise { return this._patch('user/account', data); } changePassword(oldPassword: string, newPassword: string): Promise { return this._patch('user/password', { oldPassword, newPassword }); } logout(): Promise { return this._post('session/logout', {}); } private _openWindow(url, title) { const w = window.open(url, title, 'width=800,height=600'); return w; } /*_listenToWindow(w, waitForData, handleWindow) { return new Promise((resolve, _reject) => { w.onmessage = e => { if (waitForData) { if (e.data) { if (typeof waitForData === 'function') { if (!waitForData(e)) { return; } } resolve(e); } } else { resolve(e); } }; if (handleWindow) { handleWindow(w); } }); }*/ }