Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Automated cherry pick of #9897 #9900

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions components/preparing_workspace/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import {ActionCreatorsMapObject, bindActionCreators, Dispatch} from 'redux';

import {Action} from 'mattermost-redux/types/actions';
import {checkIfTeamExists, createTeam} from 'mattermost-redux/actions/teams';
import {getProfiles} from 'mattermost-redux/actions/users';

import PreparingWorkspace, {Actions} from './preparing_workspace';

function mapDispatchToProps(dispatch: Dispatch) {
return {
actions: bindActionCreators<ActionCreatorsMapObject<Action>, Actions>({
createTeam,
getProfiles,
checkIfTeamExists,
}, dispatch),
};
Expand Down
3 changes: 3 additions & 0 deletions components/preparing_workspace/preparing_workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {RouterProps} from 'react-router-dom';
import {FormattedMessage, useIntl} from 'react-intl';

import {GeneralTypes} from 'mattermost-redux/action_types';
import {General} from 'mattermost-redux/constants';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {createChannel} from 'mattermost-redux/actions/channels';
import {getFirstAdminSetupComplete as getFirstAdminSetupCompleteAction} from 'mattermost-redux/actions/general';
Expand Down Expand Up @@ -81,6 +82,7 @@ const WAIT_FOR_REDIRECT_TIME = 2000 - START_TRANSITIONING_OUT;
export type Actions = {
createTeam: (team: Team) => ActionResult;
checkIfTeamExists: (teamName: string) => ActionResult;
getProfiles: (page: number, perPage: number, options: Record<string, any>) => ActionResult;
}

type Props = RouterProps & {
Expand Down Expand Up @@ -168,6 +170,7 @@ export default function PreparingWorkspace(props: Props) {
const [submitError, setSubmitError] = useState<string | null>(null);
useEffect(() => {
showOnMountTimeout.current = setTimeout(() => setShowFirstPage(true), 40);
props.actions.getProfiles(0, General.PROFILE_CHUNK_SIZE, {roles: General.SYSTEM_ADMIN_ROLE});
dispatch(getFirstAdminSetupCompleteAction());
document.body.classList.add('admin-onboarding');
return () => {
Expand Down
2 changes: 2 additions & 0 deletions components/root/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {shouldShowTermsOfService, getCurrentUserId, isFirstAdmin} from 'mattermo
import {getTeam} from 'mattermost-redux/selectors/entities/teams';
import {getFirstAdminSetupComplete} from 'mattermost-redux/actions/general';
import {getTheme, getBool} from 'mattermost-redux/selectors/entities/preferences';
import {getProfiles} from 'mattermost-redux/actions/users';

import {loadMeAndConfig} from 'actions/views/root';
import {emitBrowserWindowResized} from 'actions/views/browser';
Expand Down Expand Up @@ -52,6 +53,7 @@ function mapDispatchToProps(dispatch) {
loadMeAndConfig,
emitBrowserWindowResized,
getFirstAdminSetupComplete,
getProfiles,
}, dispatch),
};
}
Expand Down
24 changes: 22 additions & 2 deletions components/root/root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import classNames from 'classnames';
import {rudderAnalytics, RudderTelemetryHandler} from 'mattermost-redux/client/rudder';
import {Client4} from 'mattermost-redux/client';
import {setUrl} from 'mattermost-redux/actions/general';
import {General} from 'mattermost-redux/constants';
import {setSystemEmojis} from 'mattermost-redux/actions/emojis';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUser, isCurrentUserSystemAdmin, checkIsFirstAdmin} from 'mattermost-redux/selectors/entities/users';
import {getUseCaseOnboarding} from 'mattermost-redux/selectors/entities/preferences';

import {loadRecentlyUsedCustomEmojis} from 'actions/emoji_actions';
Expand Down Expand Up @@ -119,6 +120,7 @@ export default class Root extends React.PureComponent {
loadMeAndConfig: PropTypes.func.isRequired,
emitBrowserWindowResized: PropTypes.func.isRequired,
getFirstAdminSetupComplete: PropTypes.func.isRequired,
getProfiles: PropTypes.func.isRequired,
}).isRequired,
plugins: PropTypes.array,
products: PropTypes.array,
Expand Down Expand Up @@ -300,7 +302,25 @@ export default class Root extends React.PureComponent {
}

const firstAdminSetupComplete = await this.props.actions.getFirstAdminSetupComplete();
if (!firstAdminSetupComplete?.data) {
if (firstAdminSetupComplete?.data) {
GlobalActions.redirectUserToDefaultTeam();
return;
}

const profilesResult = await this.props.actions.getProfiles(0, General.PROFILE_CHUNK_SIZE, {roles: General.SYSTEM_ADMIN_ROLE});
if (profilesResult.error) {
GlobalActions.redirectUserToDefaultTeam();
return;
}
const currentUser = getCurrentUser(store.getState());
const adminProfiles = profilesResult.data.reduce(
(acc, curr) => {
acc[curr.id] = curr;
return acc;
},
{},
);
if (checkIsFirstAdmin(currentUser, adminProfiles)) {
this.props.history.push('/preparing-workspace');
return;
}
Expand Down
1 change: 1 addition & 0 deletions components/root/root.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ describe('components/Root', () => {
type: GeneralTypes.FIRST_ADMIN_COMPLETE_SETUP_RECEIVED,
data: true,
})),
getProfiles: jest.fn(),
},
location: {
pathname: '/',
Expand Down
3 changes: 2 additions & 1 deletion components/root/root_redirect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {ActionCreatorsMapObject, bindActionCreators, Dispatch} from 'redux';
import {connect} from 'react-redux';

import {getFirstAdminSetupComplete} from 'mattermost-redux/actions/general';
import {getCurrentUserId, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUserId, isCurrentUserSystemAdmin, isFirstAdmin} from 'mattermost-redux/selectors/entities/users';
import {getUseCaseOnboarding} from 'mattermost-redux/selectors/entities/preferences';
import {GenericAction} from 'mattermost-redux/types/actions';

Expand All @@ -22,6 +22,7 @@ function mapStateToProps(state: GlobalState) {
return {
currentUserId: getCurrentUserId(state),
isElegibleForFirstAdmingOnboarding,
isFirstAdmin: isFirstAdmin(state),
};
}

Expand Down
4 changes: 3 additions & 1 deletion components/root/root_redirect/root_redirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type Props = {
isElegibleForFirstAdmingOnboarding: boolean;
currentUserId: string;
location: Location;
isFirstAdmin: boolean;
actions: {
getFirstAdminSetupComplete: () => Promise<{data: boolean; error: any}>;
};
Expand All @@ -21,7 +22,8 @@ export default function RootRedirect(props: Props) {
if (props.currentUserId) {
if (props.isElegibleForFirstAdmingOnboarding) {
props.actions.getFirstAdminSetupComplete().then((firstAdminCompletedSignup) => {
if (firstAdminCompletedSignup.data === false) {
// root.jsx ensures admin profiles are eventually loaded
if (firstAdminCompletedSignup.data === false && props.isFirstAdmin) {
browserHistory.push('/preparing-workspace');
} else {
GlobalActions.redirectUserToDefaultTeam();
Expand Down
34 changes: 17 additions & 17 deletions packages/mattermost-redux/src/selectors/entities/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -692,25 +692,25 @@ export function searchProfilesInGroup(state: GlobalState, groupId: Group['id'],
return profiles;
}

export function checkIsFirstAdmin(currentUser: UserProfile, users: IDMappedObjects<UserProfile>): boolean {
if (!currentUser) {
return false;
}
if (!currentUser.roles.includes('system_admin')) {
return false;
}
for (const user of Object.values(users)) {
if (user.roles.includes('system_admin') && user.create_at < currentUser.create_at) {
// If the user in the list is an admin with create_at less than our user, than that user is older than the current one, so it can't be the first admin.
return false;
}
}
return true;
}

export const isFirstAdmin = createSelector(
'isFirstAdmin',
(state: GlobalState) => getCurrentUser(state),
(state: GlobalState) => getUsers(state),
(currentUser, users) => {
if (!currentUser) {
return false;
}
if (!currentUser.roles.includes('system_admin')) {
return false;
}
const userIds = Object.keys(users);
for (const userId of userIds) {
const user = users[userId];
if (user.roles.includes('system_admin') && user.create_at < currentUser.create_at) {
// If the user in the list is an admin with create_at less than our user, than that user is older than the current one, so it can't be the first admin.
return false;
}
}
return true;
},
checkIsFirstAdmin,
);