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

Commit

Permalink
only first admin sees preparing-workspace screen (#9897) (#9900)
Browse files Browse the repository at this point in the history
* only first admin sees preparing-workspace screen

(cherry picked from commit aa48d7d)

Co-authored-by: Nathaniel Allred <[email protected]>
  • Loading branch information
mattermost-build and neallred committed Feb 25, 2022
1 parent 00c2be1 commit ca03350
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 21 deletions.
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,
);

0 comments on commit ca03350

Please sign in to comment.