UNPKG

passbolt-styleguide

Version:

Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.

240 lines (215 loc) 8.44 kB
/** * Passbolt ~ Open source password manager for teams * Copyright (c) 2020 Passbolt SA (https://www.passbolt.com) * * Licensed under GNU Affero General Public License version 3 of the or any later version. * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) 2020 Passbolt SA (https://www.passbolt.com) * @license https://opensource.org/licenses/AGPL-3.0 AGPL License * @link https://www.passbolt.com Passbolt(tm) * @since 3.0.0 */ import React from "react"; import PropTypes from "prop-types"; import { withAppContext } from "../../shared/context/AppContext/AppContext"; import { ApiClient } from "../../shared/lib/apiClient/apiClient"; import { BROWSER_NAMES, detectBrowserName } from "../../shared/lib/Browser/detectBrowserName"; import PassboltApiFetchError from "../../shared/lib/Error/PassboltApiFetchError"; import PassboltServiceUnavailableError from "../../shared/lib/Error/PassboltServiceUnavailableError"; import AuthLogoutService from "../../shared/services/api/auth/AuthLogoutService"; /** * The Api recover context. * @type {React.Context<object>} */ export const ApiRecoverContext = React.createContext({ userId: null, // The recover user id token: null, // The recover token state: null, // The current recover workflow state unexpectedError: null, // The unexpected error obejct if any // Whenever the initialization of the recover is requested. onInitializeRecoverRequested: () => {}, // Callback to be used when a user is unexpectedly logged in. logoutUserAndRefresh: () => {}, }); /** * The related context provider */ class ApiRecoverContextProvider extends React.Component { /** * Default constructor * @param props The component props */ constructor(props) { super(props); this.state = Object.assign(this.defaultState, props.value); this.authLogoutService = new AuthLogoutService(props.context.getApiClientOptions()); } /** * Returns the default component state */ get defaultState() { return { userId: null, // The recover user id token: null, // The recover token state: ApiRecoverContextState.INITIAL_STATE, // The current recover workflow state unexpectedError: null, // The unexpected error obejct if any onInitializeRecoverRequested: this.onInitializeRecoverRequested.bind(this), // Whenever the initialization of the recover is requested. logoutUserAndRefresh: this.logoutUserAndRefresh.bind(this), // Callback to be used when a user is unexpectedly logged in. handleSafariExtensionDownloading: this.handleSafariExtensionDownloading.bind(this), // callback when user clicked on the Safari extension download button handleSafariExtensionNotDownloaded: this.handleSafariExtensionNotDownloaded.bind(this), // callback when user clicked on the "I didn't download the Safari extension" button handleExtensionAlreadyInstalled: this.handleExtensionAlreadyInstalled.bind(this), // callback when user clicked on "already installed extension" button }; } /** * Initialize the recover * @return {Promise<void>} */ async onInitializeRecoverRequested() { if (!this.state.userId || !this.state.token) { return this.setState({ state: ApiRecoverContextState.REQUEST_INVITATION_ERROR }); } if (!this.isBrowserSupported()) { return this.setState({ state: ApiRecoverContextState.DOWNLOAD_SUPPORTED_BROWSER_STATE }); } await this.startRecover() .then(this.handleStartRecoverSuccess.bind(this)) .catch(this.handleStartRecoverError.bind(this)); } /** * When the recover started with success. * @return {void} */ handleStartRecoverSuccess() { const currentBrowser = detectBrowserName(); const state = currentBrowser === BROWSER_NAMES.SAFARI ? ApiRecoverContextState.INSTALL_SAFARI_EXTENSION_STATE : ApiRecoverContextState.INSTALL_EXTENSION_STATE; this.setState({ state }); } /** * When the user click on the Safari extension link for downloading. * @return {void} */ handleSafariExtensionDownloading() { const state = ApiRecoverContextState.CONFIGURE_SAFARI_EXTENSION_STATE; this.setState({ state }); } /** * When the user click on "I didn't download the extension". * @return {void} */ handleSafariExtensionNotDownloaded() { const state = ApiRecoverContextState.INSTALL_SAFARI_EXTENSION_STATE; this.setState({ state }); } /** * When the user click on "Already installed extension" button. * @return {void} */ handleExtensionAlreadyInstalled() { const state = ApiRecoverContextState.CONFIGURE_SAFARI_EXTENSION_STATE; this.setState({ state }); } /** * When the recover didn't start with success. * @return {void} */ handleStartRecoverError(error) { if (error instanceof PassboltApiFetchError) { const isUserLoggedIn = error.data.code === 403; if (isUserLoggedIn) { return this.setState({ state: ApiRecoverContextState.ERROR_ALREADY_SIGNED_IN_STATE }); } const isTokenExpired = Boolean(error.data.body?.token?.expired); const isTokenConsumed = Boolean(error.data.body?.token?.isActive); if (isTokenExpired || isTokenConsumed) { return this.setState({ state: ApiRecoverContextState.TOKEN_EXPIRED_STATE }); } if (error?.data?.code === 400) { return this.setState({ state: ApiRecoverContextState.REQUEST_INVITATION_ERROR }); } } return this.setState({ state: ApiRecoverContextState.UNEXPECTED_ERROR_STATE }); } /** * When the user asks for logging out before going on with the desired process. * @returns {Promise<void>} */ async logoutUserAndRefresh() { try { await this.authLogoutService.logout(); } catch (e) { const error = new PassboltServiceUnavailableError(e.message); return this.setState({ unexpectedError: error, state: ApiRecoverContextState.UNEXPECTED_ERROR_STATE }); } window.location.reload(); } /** * Check if the browser is supported. * @returns {boolean} */ isBrowserSupported() { const browserName = detectBrowserName(); const supportedBrowserNames = [BROWSER_NAMES.CHROME, BROWSER_NAMES.FIREFOX, BROWSER_NAMES.EDGE]; const isSafariEnabled = this.props.context.siteSettings.canIUse("safari"); if (isSafariEnabled) { supportedBrowserNames.push(BROWSER_NAMES.SAFARI); } return supportedBrowserNames.includes(browserName); } /** * Start the recover. * @returns {Promise<void>} */ async startRecover() { const apiClientOptions = this.props.context.getApiClientOptions(); apiClientOptions.setResourceName("setup"); const apiClient = new ApiClient(apiClientOptions); await apiClient.get(`recover/${this.state.userId}/${this.state.token}`); } /** * Render the component * @returns {JSX} */ render() { return <ApiRecoverContext.Provider value={this.state}>{this.props.children}</ApiRecoverContext.Provider>; } } ApiRecoverContextProvider.propTypes = { context: PropTypes.any, // The application context value: PropTypes.any, // The initial value of the context children: PropTypes.any, // The children components }; export default withAppContext(ApiRecoverContextProvider); /** * API Recover Context Consumer HOC * @param WrappedComponent */ export function withApiRecoverContext(WrappedComponent) { return class withApiRecoverContext extends React.Component { render() { return ( <ApiRecoverContext.Consumer> {(context) => <WrappedComponent apiRecoverContext={context} {...this.props} />} </ApiRecoverContext.Consumer> ); } }; } /** * The recover types of state */ export const ApiRecoverContextState = { INITIAL_STATE: "Initial state", DOWNLOAD_SUPPORTED_BROWSER_STATE: "Download supported browser state", INSTALL_EXTENSION_STATE: "Install extension state", INSTALL_SAFARI_EXTENSION_STATE: "Install Safari extension state", CONFIGURE_SAFARI_EXTENSION_STATE: "Configure Safari extension state", TOKEN_EXPIRED_STATE: "Token expired state", ERROR_ALREADY_SIGNED_IN_STATE: "Error, already signed in state", REQUEST_INVITATION_ERROR: "Request inviration error state", UNEXPECTED_ERROR_STATE: "Unexpected error state", };