diff --git a/actions/admin_actions.jsx b/actions/admin_actions.jsx index 0744e94660df..5fa3e6d4bc25 100644 --- a/actions/admin_actions.jsx +++ b/actions/admin_actions.jsx @@ -7,7 +7,7 @@ import * as TeamActions from 'mattermost-redux/actions/teams'; import {Client4} from 'mattermost-redux/client'; import {bindClientFunc} from 'mattermost-redux/actions/helpers'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import {emitUserLoggedOutEvent} from 'actions/global_actions.jsx'; import {getOnNavigationConfirmed} from 'selectors/views/admin'; diff --git a/actions/channel_actions.jsx b/actions/channel_actions.jsx index eee2d979a3a2..634467c0b321 100644 --- a/actions/channel_actions.jsx +++ b/actions/channel_actions.jsx @@ -11,7 +11,7 @@ import {getChannelByName, getUnreadChannelIds, getChannel} from 'mattermost-redu import {getCurrentTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import {loadNewDMIfNeeded, loadNewGMIfNeeded, loadProfilesForSidebar} from 'actions/user_actions.jsx'; import {browserHistory} from 'utils/browser_history'; import {Constants, Preferences, NotificationLevels} from 'utils/constants'; diff --git a/actions/cloud.tsx b/actions/cloud.tsx new file mode 100644 index 000000000000..ed7b22fd619f --- /dev/null +++ b/actions/cloud.tsx @@ -0,0 +1,71 @@ + +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import {Stripe} from '@stripe/stripe-js'; +import {getCode} from 'country-list'; + +import {Client4} from 'mattermost-redux/client'; + +import {getConfirmCardSetup} from 'components/payment_form/stripe'; + +import {StripeSetupIntent, BillingDetails} from 'types/cloud/sku'; + +// Returns true for success, and false for any error +export function completeStripeAddPaymentMethod(stripe: Stripe, billingDetails: BillingDetails, isDevMode: boolean) { + return async () => { + let paymentSetupIntent: StripeSetupIntent; + try { + paymentSetupIntent = await Client4.createPaymentMethod() as StripeSetupIntent; + } catch (error) { + return error; + } + const cardSetupFunction = getConfirmCardSetup(isDevMode); + const confirmCardSetup = cardSetupFunction(stripe.confirmCardSetup); + + const result = await confirmCardSetup( + paymentSetupIntent.client_secret, + { + payment_method: { + card: billingDetails.card, + billing_details: { + name: billingDetails.name, + address: { + line1: billingDetails.address, + line2: billingDetails.address2, + city: billingDetails.city, + state: billingDetails.state, + country: getCode(billingDetails.country), + postal_code: billingDetails.postalCode, + }, + }, + }, + }, + ); + + if (!result) { + return false; + } + + const {setupIntent, error: stripeError} = result; + + if (stripeError) { + return false; + } + + if (setupIntent == null) { + return false; + } + + if (setupIntent.status !== 'succeeded') { + return false; + } + + try { + await Client4.confirmPaymentMethod(setupIntent.id); + } catch (error) { + return false; + } + + return true; + }; +} diff --git a/actions/file_actions.jsx b/actions/file_actions.jsx index d94365bcd7f9..cc5c6c89bfa8 100644 --- a/actions/file_actions.jsx +++ b/actions/file_actions.jsx @@ -17,9 +17,13 @@ export function uploadFile(file, name, channelId, rootId, clientId) { return request. post(Client4.getFilesRoute()). set(Client4.getOptions({method: 'post'}).headers). - attach('files', file, name). + + // The order here is important: + // keeping the channel_id/client_ids fields before the files contents + // allows the server to stream the uploads instead of loading them in memory. field('channel_id', channelId). field('client_ids', clientId). + attach('files', file, name). accept('application/json'); }; } diff --git a/actions/diagnostics_actions.jsx b/actions/telemetry_actions.jsx similarity index 100% rename from actions/diagnostics_actions.jsx rename to actions/telemetry_actions.jsx diff --git a/actions/user_actions.jsx b/actions/user_actions.jsx index fb0f1754f1ee..f88d93d75310 100644 --- a/actions/user_actions.jsx +++ b/actions/user_actions.jsx @@ -23,7 +23,7 @@ import {makeFilterAutoclosedDMs, makeFilterManuallyClosedDMs} from 'mattermost-r import {CategoryTypes} from 'mattermost-redux/constants/channel_categories'; import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import store from 'stores/redux_store.jsx'; import * as Utils from 'utils/utils.jsx'; import {Constants, Preferences, UserStatuses} from 'utils/constants'; diff --git a/actions/user_actions.test.js b/actions/user_actions.test.js index 8a2e6d9e3b81..0eaa445216ec 100644 --- a/actions/user_actions.test.js +++ b/actions/user_actions.test.js @@ -11,7 +11,7 @@ import {CategoryTypes} from 'mattermost-redux/constants/channel_categories'; import * as UserActions from 'actions/user_actions'; import {getState} from 'stores/redux_store'; import TestHelper from 'tests/helpers/client-test-helper'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; const mockStore = configureStore([thunk]); @@ -87,8 +87,8 @@ jest.mock('stores/redux_store', () => { }; }); -jest.mock('actions/diagnostics_actions.jsx', () => { - const original = jest.requireActual('actions/diagnostics_actions.jsx'); +jest.mock('actions/telemetry_actions.jsx', () => { + const original = jest.requireActual('actions/telemetry_actions.jsx'); return { ...original, trackEvent: jest.fn(), diff --git a/actions/views/rhs.js b/actions/views/rhs.js index 998e8a9c8845..a9007523ab1d 100644 --- a/actions/views/rhs.js +++ b/actions/views/rhs.js @@ -19,7 +19,7 @@ import {getPost} from 'mattermost-redux/selectors/entities/posts'; import {getUserTimezone} from 'mattermost-redux/selectors/entities/timezone'; import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import {getSearchTerms, getRhsState, getPluggableId} from 'selectors/rhs'; import {ActionTypes, RHSStates} from 'utils/constants'; import * as Utils from 'utils/utils'; diff --git a/actions/views/rhs.test.js b/actions/views/rhs.test.js index 86a929f3d302..8fbba8281d72 100644 --- a/actions/views/rhs.test.js +++ b/actions/views/rhs.test.js @@ -26,7 +26,7 @@ import { closeMenu, openAtPrevious, } from 'actions/views/rhs'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import {ActionTypes, RHSStates} from 'utils/constants'; import {getBrowserUtcOffset} from 'utils/timezone.jsx'; @@ -61,7 +61,7 @@ jest.mock('mattermost-redux/actions/search', () => ({ getPinnedPosts: jest.fn(), })); -jest.mock('actions/diagnostics_actions.jsx', () => ({ +jest.mock('actions/telemetry_actions.jsx', () => ({ trackEvent: jest.fn(), })); diff --git a/components/admin_console/admin_definition.jsx b/components/admin_console/admin_definition.jsx index a6893d1d0160..d6aed5c8613f 100644 --- a/components/admin_console/admin_definition.jsx +++ b/components/admin_console/admin_definition.jsx @@ -21,7 +21,7 @@ import TeamAnalytics from 'components/analytics/team_analytics'; import PluginManagement from 'components/admin_console/plugin_management'; import CustomPluginSettings from 'components/admin_console/custom_plugin_settings'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import Audits from './audits'; import CustomUrlSchemesSetting from './custom_url_schemes_setting.jsx'; @@ -184,7 +184,10 @@ const AdminDefinition = { icon: 'fa-info-circle', sectionTitle: t('admin.sidebar.about'), sectionTitleDefault: 'About', - isHidden: it.not(it.userHasReadPermissionOnResource('about')), + isHidden: it.any( + it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'), + it.not(it.userHasReadPermissionOnResource('about')), + ), license: { url: 'about/license', title: t('admin.sidebar.license'), @@ -199,10 +202,6 @@ const AdminDefinition = { 'Mattermost Enterprise Edition. Unlock enterprise features in this software through the purchase of a subscription from ', 'This software is offered under a commercial license.\n\nSee ENTERPRISE-EDITION-LICENSE.txt in your root install directory for details. See NOTICE.txt for information about open source software used in this system.', ], - isHidden: it.any( - it.not(it.enterpriseReady), - it.configIsTrue('ExperimentalSettings', 'RestrictSystemAdmin'), - ), isDisabled: it.not(it.userHasWritePermissionOnResource('about')), schema: { id: 'LicenseSettings', diff --git a/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx b/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx index bae277a73737..a730897db47b 100644 --- a/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx +++ b/components/admin_console/admin_navbar_dropdown/admin_navbar_dropdown.tsx @@ -7,7 +7,7 @@ import {FormattedMessage, injectIntl, IntlShape} from 'react-intl'; import {Team} from 'mattermost-redux/types/teams'; import * as GlobalActions from 'actions/global_actions.jsx'; -import {trackEvent} from 'actions/diagnostics_actions.jsx'; +import {trackEvent} from 'actions/telemetry_actions.jsx'; import {filterAndSortTeamsByDisplayName} from 'utils/team_utils.jsx'; import {ModalIdentifiers} from 'utils/constants'; diff --git a/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.jsx.snap b/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.jsx.snap index 4747bca02db7..c5b05b847d89 100644 --- a/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.jsx.snap +++ b/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.jsx.snap @@ -219,6 +219,33 @@ exports[`components/AdminSidebar should match snapshot 1`] = `