changes for group-sync

This commit is contained in:
kriks7iitk 2024-06-18 12:06:10 +05:30
parent 2fa84b0ab1
commit 88e02bdfd3
31 changed files with 646 additions and 216 deletions

View file

@ -4,7 +4,7 @@ export const groupsText = {
tableHeader: "Name",
allUsers: "All users",
admin: "Admin",
cardTitle: "Add new group",
cardTitle: "Create new group",
cancelButton: "Cancel",
createGroupButton: "Create Group",
groupNameExistToast: "Group name already exist",

View file

@ -268,7 +268,7 @@
"userGroups": "User Groups",
"createNewGroup": "Create new group",
"updateGroup": "Update group",
"addNewGroup": "Add new group",
"addNewGroup": "Create new group",
"enterName": "Enter group name",
"createGroup": "Create Group",
"name": "Name"

View file

@ -307,14 +307,6 @@ class AppComponent extends React.Component {
/>
<Route
path="groups"
element={
<AdminRoute>
<ManageGroupPermissions switchDarkMode={this.switchDarkMode} darkMode={darkMode} />
</AdminRoute>
}
/>
<Route
path="groups-v2"
element={
<AdminRoute>
<ManageGroupPermissionsV2 switchDarkMode={this.switchDarkMode} darkMode={darkMode} />

View file

@ -11,6 +11,7 @@ import { toast } from 'react-hot-toast';
import GroupChipTD from '@/ManageGroupPermissionsV2/ResourceChip';
import '../ManageGroupPermissionsV2/groupPermissions.theme.scss';
import { Action } from 'rxjs/internal/scheduler/Action';
import ChangeRoleModal from '@/ManageGroupPermissionResourcesV2/ChangeRoleModal';
class ManageGranularAccessComponent extends React.Component {
constructor(props) {
@ -37,6 +38,13 @@ class ManageGranularAccessComponent extends React.Component {
addableApps: [],
modalType: 'add',
modalTitle: 'Add app permissions',
showAutoRoleChangeModal: false,
autoRoleChangeModalMessage: '',
autoRoleChangeModalList: [],
autoRoleChangeMessageType: '',
updateParam: {},
updatingPermission: {},
updateType: '',
};
}
@ -119,9 +127,15 @@ class ManageGranularAccessComponent extends React.Component {
this.fetchGranularPermissions(this.props.groupPermissionId);
this.closeAddPermissionModal();
})
.catch((error) => {
toast.error(error.error);
console.log(error);
.catch(({ error }) => {
this.closeAddPermissionModal();
this.props.updateParentState({
showEditRoleErrorModal: true,
errorTitle: error?.title ? error?.title : 'Cannot remove last admin',
errorMessage: error.error,
errorIconName: 'usergear',
errorListItems: error.data,
});
});
// .then(())
};
@ -160,10 +174,11 @@ class ManageGranularAccessComponent extends React.Component {
console.log(granularPermission);
};
updateOnlyGranularPermissions = (permission, actions = {}) => {
updateOnlyGranularPermissions = (permission, actions = {}, allowRoleChange) => {
console.log(actions);
const body = {
actions: actions,
allowRoleChange,
};
groupPermissionV2Service
.updateGranularPermission(permission.id, body)
@ -173,6 +188,20 @@ class ManageGranularAccessComponent extends React.Component {
toast.success('Permission updated successfully');
})
.catch(({ error }) => {
console.log('error is');
console.log(error);
if (error?.type) {
this.setState({
showAutoRoleChangeModal: true,
autoRoleChangeModalMessage: error?.error,
autoRoleChangeModalList: error?.data,
autoRoleChangeMessageType: error?.type,
updateParam: actions,
updatingPermission: permission,
updateType: 'ONLY_PERMISSIONS',
});
return;
}
this.props.updateParentState({
showEditRoleErrorModal: true,
errorTitle: error?.title ? error?.title : 'Cannot remove last admin',
@ -183,7 +212,7 @@ class ManageGranularAccessComponent extends React.Component {
});
};
updateGranularPermissions = () => {
updateGranularPermissions = (allowRoleChange) => {
const { currentEditingPermissions, selectedApps, newPermissionName, isAll, initialPermissionState } = this.state;
const currentResource = currentEditingPermissions?.appsGroupPermissions?.groupApps?.map((app) => {
return app.app.id;
@ -207,17 +236,17 @@ class ManageGranularAccessComponent extends React.Component {
id: id,
};
});
console.log('resource to add');
console.log(resourcesToAdd);
console.log(resourcesToDelete);
const body = {
name: newPermissionName,
isAll: isAll,
actions: initialPermissionState,
resourcesToAdd,
resourcesToDelete,
allowRoleChange,
};
console.log(body);
groupPermissionV2Service
.updateGranularPermission(currentEditingPermissions.id, body)
.then(() => {
@ -225,8 +254,19 @@ class ManageGranularAccessComponent extends React.Component {
this.closeAddPermissionModal();
toast.success('Permission updated successfully');
})
.catch((err) => {
toast.error(err.error);
.catch(({ error }) => {
if (error?.type) {
this.setState({
showAutoRoleChangeModal: true,
autoRoleChangeModalMessage: error?.error,
autoRoleChangeModalList: error?.data,
autoRoleChangeMessageType: error?.type,
updateType: '',
showAddPermissionModal: false,
});
return;
}
toast.error(error.error);
this.closeAddPermissionModal();
});
};
@ -282,6 +322,30 @@ class ManageGranularAccessComponent extends React.Component {
this.setState({ selectedApps: values });
};
handleAutoRoleChangeModalClose = () => {
this.setState({
showAutoRoleChangeModal: false,
autoRoleChangeModalMessage: '',
autoRoleChangeModalList: [],
autoRoleChangeMessageType: '',
updateParam: {},
isLoading: false,
updatingPermission: {},
updateType: '',
});
};
handleConfirmAutoRoleChangeGroupUpdate = () => {
console.log('this is running');
this.updateGranularPermissions(true);
this.handleAutoRoleChangeModalClose();
};
handleConfirmAutoRoleChangeOnlyGroupUpdate = () => {
const { updateParam, updatingPermission } = this.state;
this.updateOnlyGranularPermissions(updatingPermission, updateParam, true);
this.handleAutoRoleChangeModalClose();
};
render() {
const {
isEmpty,
@ -297,32 +361,45 @@ class ManageGranularAccessComponent extends React.Component {
modalTitle,
modalType,
newPermissionName,
showAutoRoleChangeModal,
autoRoleChangeModalMessage,
autoRoleChangeModalList,
autoRoleChangeMessageType,
updateParam,
updatingPermission,
updateType,
} = this.state;
const apps = [
{ name: 'App 1', value: 'App1', label: 'app 1' },
{ name: 'App Long name 1', value: 'App2', label: 'app long name 1' },
{ name: 'App very long name', value: 'App3', label: 'app very long name' },
{ name: 'App 4', value: 'App4', label: 'app 4' },
{ name: 'App5veryverylongname', value: 'App5veryverylongname', label: 'App5veryverylongname' },
{ name: 'App 6', value: 'App6', label: '6' },
{ name: 'App 7', value: 'App 7', label: 'app 7' },
{ name: 'App 8', value: 'App 8', label: 'app 8' },
{ name: 'App 9', value: 'App 9', label: 'app 9' },
{ name: 'App 10', value: 'App 10', label: 'app 10' },
{ name: 'App 11', value: 'App 11', label: 'app 11' },
{ name: 'App 12', value: 'App 12', label: 'app 12' },
];
const currentGroupPermission = this.props?.groupPermission;
const isRoleGroup = currentGroupPermission.name == 'admin';
const showPermissionInfo = currentGroupPermission.name == 'admin' || currentGroupPermission.name == 'end-user';
const disableEditUpdate = currentGroupPermission.name == 'end-user';
return (
<div className="row granular-access-container justify-content-center">
<ChangeRoleModal
showAutoRoleChangeModal={showAutoRoleChangeModal}
autoRoleChangeModalList={autoRoleChangeModalList}
autoRoleChangeMessageType={autoRoleChangeMessageType}
handleAutoRoleChangeModalClose={this.handleAutoRoleChangeModalClose}
handleConfirmation={
updateType === 'ONLY_PERMISSIONS'
? this.handleConfirmAutoRoleChangeOnlyGroupUpdate
: this.handleConfirmAutoRoleChangeGroupUpdate
}
darkMode={this.props.darkMode}
isLoading={isLoading}
/>
<ModalBase
size="md"
show={showAddPermissionModal}
handleClose={this.closeAddPermissionModal}
handleConfirm={modalType === 'add' ? this.createGranularPermissions : this.updateGranularPermissions}
handleConfirm={
modalType === 'add'
? this.createGranularPermissions
: () => {
this.updateGranularPermissions();
}
}
className="permission-manager-modal"
title={
<div className="my-3 permission-manager-title" data-cy="modal-title">

View file

@ -0,0 +1,63 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import ModalBase from '@/_ui/Modal';
import '../ManageGroupPermissionsV2/groupPermissions.theme.scss';
function ChangeRoleModal({
showAutoRoleChangeModal,
autoRoleChangeModalList,
autoRoleChangeMessageType,
handleAutoRoleChangeModalClose,
handleConfirmation,
darkMode,
isLoading,
}) {
const { t } = useTranslation();
const renderUserChangeMessage = (type) => {
const changePermissionMessage = (
<p className="tj-text-sm">
Granting this permission to the user group will result in a role change for the following user(s) from{' '}
<b>end-users</b> to <b>builders</b>. Are you sure you want to continue?
</p>
);
const addUserMessage = (
<p className="tj-text-sm">
Adding the following user(s) to this group will change their default group from <b>end-users</b> to{' '}
<b>builders</b>. Are you sure you want to continue?
</p>
);
const message = type === 'USER_ROLE_CHANGE_ADD_USERS' ? addUserMessage : changePermissionMessage;
return message;
};
return (
<ModalBase
title={
<div className="my-3" data-cy="modal-title">
<span className="tj-text-md font-weight-500">Change in user role</span>
</div>
}
handleConfirm={handleConfirmation}
confirmBtnProps={{ title: 'Continue' }}
show={showAutoRoleChangeModal}
handleClose={handleAutoRoleChangeModalClose}
darkMode={darkMode}
isLoading={isLoading}
>
<>
{renderUserChangeMessage(autoRoleChangeMessageType)}
<p></p>
<div className="item-list">
{autoRoleChangeModalList.map((item, index) => (
<div key={index}>
<span className="tj-text-sm">{`${index + 1}. ${item}`}</span>
</div>
))}
</div>
</>
</ModalBase>
);
}
export default ChangeRoleModal;

View file

@ -18,6 +18,7 @@ import './grpPermissionResc.theme.scss';
import { EDIT_ROLE_MESSAGE } from './constant';
import { SearchBox } from '@/_components/SearchBox';
import EditRoleErrorModal from '@/ManageGroupPermissionsV2/ErrorModal/ErrorModal';
import ChangeRoleModal from '@/ManageGroupPermissionResourcesV2/ChangeRoleModal';
class ManageGroupPermissionResourcesComponent extends React.Component {
constructor(props) {
super(props);
@ -50,6 +51,11 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
errorTitle: '',
showEditRoleErrorModal: false,
errorIconName: '',
showAutoRoleChangeModal: false,
autoRoleChangeModalMessage: '',
autoRoleChangeModalList: [],
autoRoleChangeMessageType: '',
updateParam: {},
};
}
@ -64,13 +70,14 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
}
fetchGroupPermission = (groupPermissionId) => {
groupPermissionV2Service.getGroup(groupPermissionId).then((data) => {
groupPermissionV2Service.getGroup(groupPermissionId).then(({ group, isBuilderLevel }) => {
this.setState((prevState) => {
return {
isRoleGroup: data.type === 'default',
groupPermission: data,
isRoleGroup: group.type === 'default',
groupPermission: group,
currentTab: prevState.currentTab,
isLoadingGroup: false,
isBuilderLevel: isBuilderLevel,
};
});
});
@ -93,6 +100,8 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
groupPermissionV2Service
.getUsersNotInGroup(query, groupPermissionId)
.then((users) => {
console.log('loggimgusers');
console.log(users);
resolve(
users.map((user) => {
return {
@ -101,6 +110,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
first_name: user.firstName,
last_name: user.lastName,
email: user.email,
role: user?.userGroups?.group?.name,
};
})
);
@ -148,15 +158,24 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
});
};
updateGroupPermission = (groupPermissionId, params) => {
updateGroupPermission = (groupPermissionId, params, allowRoleChange) => {
groupPermissionV2Service
.update(groupPermissionId, params)
.update(groupPermissionId, { ...params, allowRoleChange })
.then(() => {
toast.success('Group permissions updated');
this.fetchGroupPermission(groupPermissionId);
})
.catch(({ error }) => {
console.log(error);
if (error?.type) {
this.setState({
showAutoRoleChangeModal: true,
autoRoleChangeModalMessage: error?.error,
autoRoleChangeModalList: error?.data,
autoRoleChangeMessageType: error?.type,
});
return;
}
this.setState({
errorMessage: error?.error,
showEditRoleErrorModal: true,
@ -274,11 +293,14 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
});
};
addSelectedUsersToGroup = (groupPermissionId, selectedUsers) => {
addSelectedUsersToGroup = (groupPermissionId, selectedUsers, allowRoleChange) => {
console.log('selected users');
console.log(selectedUsers);
this.setState({ isAddingUsers: true });
const body = {
userIds: selectedUsers.map((user) => user.value),
groupId: groupPermissionId,
allowRoleChange,
};
groupPermissionV2Service
.addUsersInGroups(body)
@ -293,6 +315,16 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.fetchUsersInGroup(groupPermissionId);
})
.catch(({ error }) => {
if (error?.type) {
this.setState({
isLoadingUsers: false,
showAutoRoleChangeModal: true,
autoRoleChangeModalMessage: error?.error,
autoRoleChangeModalList: error?.data,
autoRoleChangeMessageType: error?.type,
});
return;
}
this.setState({
showEditRoleErrorModal: true,
errorTitle: error?.title,
@ -366,6 +398,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
.then(() => {
this.fetchUsersInGroup(groupPermission.id);
toast.success('Role updated successfully');
if (groupPermission?.name === 'admin') window.location.reload();
})
.catch(({ error }) => {
this.setState({
@ -422,8 +455,58 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
}));
};
toggleAutoRoleChangeModal = () => {
this.setState((prevState) => ({
showAutoRoleChangeModal: !prevState.showAutoRoleChangeModal,
}));
};
handleAutoRoleChangeModalClose = () => {
this.setState({
showAutoRoleChangeModal: false,
autoRoleChangeModalMessage: '',
autoRoleChangeModalList: [],
autoRoleChangeMessageType: '',
updateParam: {},
isLoadingGroup: false,
isLoadingUsers: false,
});
};
renderUserChangeMessage = (type) => {
const changePermissionMessage = (
<p className="tj-text-sm">
Granting this permission to the user group will result in a role change for the following user(s) from{' '}
<b>end-users</b> to <b>builders</b>. Are you sure you want to continue?
</p>
);
const addUserMessage = (
<p className="tj-text-sm">
Adding the following user(s) to this group will change their default group from <b>end-users</b> to{' '}
<b>builders</b>. Are you sure you want to continue?
</p>
);
const message = type === 'USER_ROLE_CHANGE_ADD_USERS' ? addUserMessage : changePermissionMessage;
return message;
};
toggleAddUsersToRoleModal = () => this.setState({ isAddUsersToRoleModalOpen: !this.state.isAddUsersToRoleModalOpen });
handleConfirmAutoRoleChangeGroupUpdate = () => {
console.log('this is running');
const { updateParam, groupPermission } = this.state;
this.updateGroupPermission(groupPermission.id, updateParam, true);
this.setState({
updateParam: {},
});
this.handleAutoRoleChangeModalClose();
};
handleConfirmAutoRoleChangeAddUser = () => {
const { groupPermission, selectedUsers } = this.state;
this.addSelectedUsersToGroup(groupPermission?.id, selectedUsers, true);
this.handleAutoRoleChangeModalClose();
};
render() {
if (!this.props.groupPermissionId) return null;
@ -448,8 +531,10 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
errorTitle,
showEditRoleErrorModal,
errorIconName,
addableApps,
granularPermissions,
showAutoRoleChangeModal,
autoRoleChangeModalMessage,
autoRoleChangeModalList,
autoRoleChangeMessageType,
} = this.state;
const isBasicPlan = false;
@ -526,28 +611,19 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
</div>
)}
</ModalBase>
<ModalBase
title={
<div className="my-3" data-cy="modal-title">
<span className="tj-text-md font-weight-500">Edit user role</span>
<div className="tj-text-sm text-muted" data-cy="user-email">
{updatingUserRole?.email}
</div>
</div>
<ChangeRoleModal
showAutoRoleChangeModal={showAutoRoleChangeModal}
autoRoleChangeModalList={autoRoleChangeModalList}
autoRoleChangeMessageType={autoRoleChangeMessageType}
handleAutoRoleChangeModalClose={this.handleAutoRoleChangeModalClose}
handleConfirmation={
autoRoleChangeMessageType === 'USER_ROLE_CHANGE_ADD_USERS'
? this.handleConfirmAutoRoleChangeAddUser
: this.handleConfirmAutoRoleChangeGroupUpdate
}
show={isAddUsersToRoleModalOpen}
handleClose={this.toggleAddUsersToRoleModal}
darkMode={this.props.darkMode}
>
<p className="tj-text-sm">
Changing user default group from builder to end-user will affect the count of users covered by your plan.
</p>
<br />
<p className="tj-text-sm">
This will also remove the user from any custom groups with builder-like permissions. Are you sure you want
to continue?
</p>
</ModalBase>
isLoading={isLoadingGroup || isLoadingUsers}
/>
<div className="org-users-page animation-fade">
{isLoadingGroup ? (
<Loader />
@ -869,6 +945,9 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.updateGroupPermission(groupPermission.id, {
appCreate: !groupPermission.appCreate,
});
this.setState({
updateParam: { appCreate: !groupPermission.appCreate },
});
}}
checked={groupPermission.appCreate}
disabled={disablePermissionUpdate}
@ -893,6 +972,9 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.updateGroupPermission(groupPermission.id, {
appDelete: !groupPermission.appDelete,
});
this.setState({
updateParam: { appDelete: !groupPermission.appDelete },
});
}}
checked={groupPermission.appDelete}
disabled={disablePermissionUpdate}
@ -930,6 +1012,9 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.updateGroupPermission(groupPermission.id, {
folderCRUD: !groupPermission.folderCRUD,
});
this.setState({
updateParam: { folderCRUD: !groupPermission.folderCRUD },
});
}}
checked={groupPermission.folderCRUD}
disabled={disablePermissionUpdate}
@ -966,6 +1051,9 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.updateGroupPermission(groupPermission.id, {
orgConstantCRUD: !groupPermission.orgConstantCRUD,
});
this.setState({
updateParam: { orgConstantCRUD: !groupPermission.orgConstantCRUD },
});
}}
checked={groupPermission.orgConstantCRUD}
disabled={disablePermissionUpdate}
@ -1003,6 +1091,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
groupPermission={groupPermission}
setErrorState={this.setErrorState}
updateParentState={this.changeThisComponentState}
fetchGroup={this.fetchGroupPermission}
/>
</aside>
</div>

View file

@ -455,7 +455,7 @@ class ManageGroupPermissionsComponent extends React.Component {
title={
showGroupNameUpdateForm
? this.props.t('header.organization.menus.manageGroups.permissions.updateGroup', 'Update group')
: this.props.t('header.organization.menus.manageGroups.permissions.addNewGroup', 'Add new group')
: this.props.t('header.organization.menus.manageGroups.permissions.addNewGroup', 'Create new group')
}
>
<form

View file

@ -26,7 +26,7 @@ class ManageGroupPermissionsComponent extends React.Component {
defaultGroups: [],
creatingGroup: false,
showNewGroupForm: false,
newGroupName: null,
newGroupName: '',
isDeletingGroup: false,
isUpdatingGroupName: false,
showGroupDeletionConfirmation: false,
@ -229,6 +229,7 @@ class ManageGroupPermissionsComponent extends React.Component {
};
changeNewGroupName = (value) => {
if (value.length > 50) return;
this.setState({
newGroupName: value,
isSaveBtnDisabled: false,
@ -477,7 +478,7 @@ class ManageGroupPermissionsComponent extends React.Component {
className="btn btn-primary create-new-group-button"
onClick={(e) => {
e.preventDefault();
this.setState({ newGroupName: null, showNewGroupForm: true, isSaveBtnDisabled: true });
this.setState({ newGroupName: '', showNewGroupForm: true, isSaveBtnDisabled: true });
}}
data-cy="create-new-group-button"
leftIcon="plus"
@ -505,7 +506,7 @@ class ManageGroupPermissionsComponent extends React.Component {
title={
showGroupNameUpdateForm
? this.props.t('header.organization.menus.manageGroups.permissions.updateGroup', 'Update group')
: this.props.t('header.organization.menus.manageGroups.permissions.addNewGroup', 'Add new group')
: this.props.t('header.organization.menus.manageGroups.permissions.addNewGroup', 'Create new group')
}
>
<form
@ -537,6 +538,7 @@ class ManageGroupPermissionsComponent extends React.Component {
data-cy="group-name-input"
autoFocus
/>
<span className="tj-text-xxsm">Group name must be unique and max 50 characters</span>
</div>
</div>
</div>

View file

@ -106,7 +106,8 @@ function InviteUsersForm({
let role = null;
if (currentEditingUser)
role = selectedGroups.find(
(group) => group.groupType === 'default' && !currentEditingUser.role_group.includes(group.value)
(group) =>
group.groupType === 'default' && !currentEditingUser.role_group.map((role) => role.name).includes(group.value)
)?.value;
const selectedGroupsIds = selectedGroups.filter((group) => group.groupType !== 'default').map((group) => group.id);
const newGroupsToAdd = selectedGroupsIds.filter((selectedGroupId) => !existingGroups.includes(selectedGroupId));
@ -115,11 +116,12 @@ function InviteUsersForm({
};
const isEdited = () => {
const { newGroupsToAdd, groupsToRemove } = getEditedGroups();
const { newGroupsToAdd, groupsToRemove, role } = getEditedGroups();
const { first_name, last_name } = currentEditingUser || {};
return isEditing
? fields['fullName'] !== `${first_name}${last_name && ` ${last_name}`}` ||
groupsToRemove.length ||
role !== undefined ||
newGroupsToAdd.length
: true;
};
@ -301,7 +303,7 @@ function InviteUsersForm({
form={activeTab == 1 ? 'inviteByEmail' : 'inviteBulkUsers'}
type="submit"
variant="primary"
disabled={uploadingUsers || creatingUser || !isEdited() || !containRoleGroup}
disabled={uploadingUsers || creatingUser || !isEdited() || (!isEditing && !containRoleGroup)}
data-cy={activeTab == 1 ? 'button-invite-users' : 'button-upload-users'}
leftIcon={activeTab == 1 ? 'sent' : 'fileupload'}
width="20"

View file

@ -11,6 +11,7 @@ import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import ManageOrgUsersDrawer from './ManageOrgUsersDrawer';
import { USER_DRAWER_MODES } from '@/_helpers/utils';
import { getQueryParams } from '@/_helpers/routes';
import EditRoleErrorModal from '@/ManageGroupPermissionsV2/ErrorModal/ErrorModal';
class ManageOrgUsersComponent extends React.Component {
constructor(props) {
@ -36,6 +37,11 @@ class ManageOrgUsersComponent extends React.Component {
userDrawerMode: USER_DRAWER_MODES.CREATE,
newSelectedGroups: [],
existingGroupsToRemove: [],
showErrorModal: false,
errorModalMessage: '',
errorItemList: [],
errorTitle: '',
errorIconName: 'usergear',
};
}
@ -223,7 +229,13 @@ class ManageOrgUsersComponent extends React.Component {
});
})
.catch(({ error }) => {
toast.error(error.error);
this.setState({
showErrorModal: true,
errorModalMessage: error.error,
errorTitle: error?.title || 'Conflicting Permissions',
errorItemList: error?.data,
errorIconName: 'usergear',
});
this.setState({ creatingUser: false });
});
} else {
@ -254,6 +266,16 @@ class ManageOrgUsersComponent extends React.Component {
toast.success('Invitation URL copied');
};
clearErrorState = () => {
this.setState({
showErrorModal: false,
errorModalMessage: '',
errorItemList: [],
errorTitle: '',
errorIconName: '',
});
};
pageChanged = (page) => {
this.fetchUsers(page, this.state.options);
};
@ -293,10 +315,24 @@ class ManageOrgUsersComponent extends React.Component {
meta,
currentEditingUser,
userDrawerMode,
showErrorModal,
errorModalMessage,
errorItemList,
errorTitle,
errorIconName,
} = this.state;
return (
<ErrorBoundary showFallback={true}>
<div className="wrapper org-users-page animation-fade">
<EditRoleErrorModal
darkMode={this.props.darkMode}
show={showErrorModal}
errorMessage={errorModalMessage}
errorTitle={errorTitle}
listItems={errorItemList}
iconName={errorIconName}
onClose={this.clearErrorState}
/>
{this.state.isInviteUsersDrawerOpen && (
<ManageOrgUsersDrawer
isInviteUsersDrawerOpen={this.state.isInviteUsersDrawerOpen}

View file

@ -18,15 +18,13 @@ export function OrganizationSettings(props) {
const { updateSidebarNAV } = useContext(BreadCrumbContext);
const { workspaceId } = useParams();
const sideBarNavs = ['Users', 'Groups', 'Groups V2', 'Workspace login', 'Workspace variables'];
const sideBarNavs = ['Users', 'Groups', 'Workspace login', 'Workspace variables'];
const defaultOrgName = (groupName) => {
switch (groupName) {
case 'users':
return 'Users';
case 'groups':
return 'Groups';
case 'groups2':
return 'Groups V2';
case 'workspace-login':
return 'Workspace login';
case 'workspace-variables':

View file

@ -68,7 +68,6 @@ export class OauthService {
organization.id,
//Adding user as END-USER on workspace signup
USER_ROLE.END_USER,
[],
user,
true,
defaultOrganization?.id,
@ -240,7 +239,6 @@ export class OauthService {
defaultOrganization.id,
//Adding as admin since this is instance login
USER_ROLE.ADMIN,
[],
null,
true,
null,

View file

@ -14,7 +14,7 @@ export class AddGroupPermissionsTable1714015513342 implements MigrationInterface
CREATE TABLE IF NOT EXISTS permission_groups (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID,
name VARCHAR NOT NULL,
name VARCHAR(50) NOT NULL,
type group_permissions_type NOT NULL DEFAULT 'custom',
app_create BOOLEAN DEFAULT false,
app_delete BOOLEAN DEFAULT false,

View file

@ -7,8 +7,8 @@ export class AddGroupUsersTable1714015541245 implements MigrationInterface {
`
CREATE TABLE IF NOT EXISTS group_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID,
group_id UUID,
user_id UUID NOT NULL,
group_id UUID NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,

View file

@ -101,7 +101,10 @@ export class GroupPermissionsControllerV2 {
@CheckPolicies((ability: AppAbility) => ability.can(ORGANIZATION_RESOURCE_ACTIONS.ACCESS_PERMISSIONS, UserEntity))
@Get(':groupId/group-user')
async getAllGroupUser(@User() user, @Param('groupId') groupId: string, @Query('input') searchInput: string) {
return await this.groupPermissionsService.getAllGroupUsers(groupId, searchInput);
return await this.groupPermissionsService.getAllGroupUsers(
{ groupId, organizationId: user.organizationId },
searchInput
);
}
@UseGuards(JwtAuthGuard, PoliciesGuard)
@ -151,7 +154,7 @@ export class GroupPermissionsControllerV2 {
//Check for license validation first here
// What are license validation for this
const { groupId, createAppsPermissionsObject } = createGranularPermissionsDto;
const group = await this.groupPermissionsService.getGroup(groupId);
const { group } = await this.groupPermissionsService.getGroup(groupId);
validateGranularPermissionCreateOperation(group);
return await this.granularPermissionsService.create(
{

View file

@ -28,6 +28,10 @@ export class CreateGranularPermissionDto {
@IsOptional()
createAppsPermissionsObject: CreateAppsPermissionsObject;
// @IsBoolean()
// @IsOptional()
// allowRoleChange: boolean;
}
export class UpdateGranularPermissionDto {
@ -47,4 +51,8 @@ export class UpdateGranularPermissionDto {
@IsOptional()
resourcesToDelete: GranularPermissionDeleteResourceItems;
@IsBoolean()
@IsOptional()
allowRoleChange: boolean;
}

View file

@ -38,6 +38,10 @@ export class UpdateGroupPermissionDto {
@IsBoolean()
@IsOptional()
dataSourceDelete: boolean;
@IsBoolean()
@IsOptional()
allowRoleChange: boolean;
}
export class EditUserRoleDto {
@ -59,4 +63,8 @@ export class AddGroupUserDto {
@IsString()
@IsNotEmpty()
groupId: string;
@IsBoolean()
@IsOptional()
allowRoleChange: boolean;
}

View file

@ -16,10 +16,10 @@ export class GroupUsers extends BaseEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'user_id' })
@Column({ name: 'user_id', nullable: false })
userId: string;
@Column({ name: 'group_id' })
@Column({ name: 'group_id', nullable: false })
groupId: string;
@CreateDateColumn({ default: () => 'now()', name: 'created_at' })

View file

@ -40,4 +40,6 @@ export const ERROR_HANDLER = {
EDITOR_LEVEL_PERMISSIONS_NOT_ALLOWED:
'End-users can only be granted permission to view apps. If you wish to add this permission, kindly change the following users role from end-user to builder',
EDITOR_LEVEL_PERMISSION_NOT_ALLOWED_END_USER: 'Cannot assign builder level permission to end users',
UPDATE_EDITABLE_PERMISSION_END_USER_GROUP:
'End-users can only be granted permission to view apps. If you wish to add this permission, kindly change the following users role from end-user to builder- ',
};

View file

@ -40,6 +40,7 @@ export const DEFAULT_GROUP_PERMISSIONS = {
orgConstantCRUD: true,
dataSourceCreate: true,
dataSourceDelete: true,
isBuilderLevel: true,
},
BUILDER: {
name: USER_ROLE.BUILDER,
@ -52,6 +53,7 @@ export const DEFAULT_GROUP_PERMISSIONS = {
orgConstantCRUD: true,
dataSourceCreate: true,
dataSourceDelete: true,
isBuilderLevel: true,
},
END_USER: {
name: USER_ROLE.END_USER,
@ -64,6 +66,7 @@ export const DEFAULT_GROUP_PERMISSIONS = {
orgConstantCRUD: false,
dataSourceCreate: false,
dataSourceDelete: false,
isBuilderLevel: false,
},
} as Record<string, CreateDefaultGroupObject>;

View file

@ -30,11 +30,12 @@ export type GranularPermissionAddResourceItems = AppsPermissionAddResourceItem[]
export type GranularPermissionDeleteResourceItems = AppsPermissionDeleteResourceItem[];
export interface UpdateResourceGroupPermissionsObject {
group?: GroupPermissions;
group: GroupPermissions;
granularPermissions: GranularPermissions;
actions: ResourceGroupActions;
resourcesToAdd: GranularPermissionAddResourceItems;
resourcesToDelete: GranularPermissionDeleteResourceItems;
allowRoleChange?: boolean;
}
export interface GranularPermissionQuerySearchParam {

View file

@ -15,6 +15,17 @@ export interface CreateDefaultGroupObject {
dataSourceDelete: boolean;
}
export interface ValidateEditUserGroupAdditionObject {
userId: string;
groupsToAddIds: string[];
organizationId: string;
}
export interface GetGroupUsersObject {
groupId: string;
organizationId: string;
}
export interface GroupQuerySearchParamObject {
[key: string]: SearchParamItem | boolean | string | number;
name?: SearchParamItem;

View file

@ -1,7 +1,10 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, Injectable } from '@nestjs/common';
import { GroupPermissions } from 'src/entities/group_permissions.entity';
import { User } from 'src/entities/user.entity';
import { USER_ROLE } from '@module/user_resource_permissions/constants/group-permissions.constant';
import {
GROUP_PERMISSIONS_TYPE,
USER_ROLE,
} from '@module/user_resource_permissions/constants/group-permissions.constant';
import {
addableUsersToGroupQuery,
getRoleUsersListQuery,
@ -10,6 +13,9 @@ import {
import { EntityManager } from 'typeorm';
import { dbTransactionWrap } from '@helpers/utils.helper';
import { App } from 'src/entities/app.entity';
import { getAllGranularPermissionQuery } from '../utility/granular-permissios.utility';
import { ResourceType } from '../constants/granular-permissions.constant';
import { ValidateEditUserGroupAdditionObject } from '../interface/group-permissions.interface';
@Injectable()
export class GroupPermissionsUtilityService {
@ -26,6 +32,13 @@ export class GroupPermissionsUtilityService {
return await query.getMany();
}, manager);
}
async getRoleGroup(role: USER_ROLE, organizationId: string, manager?: EntityManager): Promise<GroupPermissions> {
return await dbTransactionWrap(async (manager) => {
return await manager.findOne(GroupPermissions, {
where: { name: role, organizationId, type: GROUP_PERMISSIONS_TYPE.DEFAULT },
});
}, manager);
}
async getUserRole(userId: string, organizationId: string, manager?: EntityManager): Promise<GroupPermissions> {
return await dbTransactionWrap(async (manager: EntityManager) => {
@ -56,4 +69,59 @@ export class GroupPermissionsUtilityService {
});
}, manager);
}
async checkIfBuilderLevelResourcesPermissions(groupId: string, manager?: EntityManager): Promise<boolean> {
return await dbTransactionWrap(async (manager: EntityManager) => {
const allPermission = await getAllGranularPermissionQuery({ groupId }, manager).getMany();
if (!allPermission) return false;
const isBuilderLevelAppsPermission = allPermission
.filter((permissions) => permissions.type === ResourceType.APP)
.some((permissions) => {
const appPermission = permissions.appsGroupPermissions;
return appPermission.canEdit === true;
});
//Add for other permissions here
return isBuilderLevelAppsPermission;
}, manager);
}
async isEditableGroup(group: GroupPermissions, manager?: EntityManager): Promise<boolean> {
return await dbTransactionWrap(async (manager: EntityManager) => {
const editPermissionsPresent =
Object.values(group).some((value) => typeof value === 'boolean' && value === true) ||
(await this.checkIfBuilderLevelResourcesPermissions(group.id, manager));
return editPermissionsPresent;
}, manager);
}
async validateEditUserGroupPermissionsAddition(
functionParam: ValidateEditUserGroupAdditionObject,
manager?: EntityManager
) {
const { organizationId, userId, groupsToAddIds } = functionParam;
console.log('validating permissions');
console.log(groupsToAddIds);
return await dbTransactionWrap(async (manager: EntityManager) => {
const userRole = await this.getUserRole(userId, organizationId, manager);
console.log(userRole);
if (userRole.name === USER_ROLE.END_USER) {
return await Promise.all(
groupsToAddIds.map(async (id) => {
const group = await manager.findOne(GroupPermissions, id);
const isEditableGroup = await this.isEditableGroup(group, manager);
if (!isEditableGroup) {
throw new BadRequestException({
message: {
error:
'End-users can only be granted permission to view apps. Kindly change the user role or custom group to continue.',
title: 'Conflicting Permissions',
},
});
}
})
);
}
}, manager);
}
}

View file

@ -6,6 +6,7 @@ import { BadRequestException, MethodNotAllowedException } from '@nestjs/common';
import { CreateGroupPermissionDto, UpdateGroupPermissionDto } from '@dto/group_permissions.dto';
import { ERROR_HANDLER } from '@module/user_resource_permissions/constants/group-permissions.constant';
import { GroupUsers } from 'src/entities/group_users.entity';
import { GetGroupUsersObject } from '../interface/group-permissions.interface';
export function getRoleUsersListQuery(
role: USER_ROLE,
@ -38,6 +39,7 @@ export function getRoleUsersListQuery(
'user.lastName',
'user.email',
'userGroups.groupId',
'userGroups.id',
'group.name',
'group.type',
]);
@ -145,6 +147,13 @@ export function addableUsersToGroupQuery(
.innerJoin('users.organizationUsers', 'organization_users', 'organization_users.organizationId = :organizationId', {
organizationId: organizationId,
})
.innerJoinAndSelect('users.userGroups', 'userGroups')
.innerJoinAndSelect('userGroups.group', 'group', 'group.organizationId = :organizationId', {
organizationId,
})
.where('group.type = :type', {
type: GROUP_PERMISSIONS_TYPE.DEFAULT,
})
.where((qb) => {
const subQuery = qb
.subQuery()
@ -158,6 +167,7 @@ export function addableUsersToGroupQuery(
return 'users.id NOT IN ' + subQuery;
})
.andWhere(addableUserGetOrConditions(searchInput))
.select(['users.id', 'users.firstName', 'users.lastName', 'users.email', 'userGroups.id', 'group.name'])
.orderBy('users.createdAt', 'DESC');
return query;
@ -180,14 +190,35 @@ const addableUserGetOrConditions = (searchInput) => {
};
export function getUserInGroupQuery(
groupId: string,
getGroupUsersObject: GetGroupUsersObject,
manager: EntityManager,
searchInput: string
): SelectQueryBuilder<GroupUsers> {
const { groupId, organizationId } = getGroupUsersObject;
const query = manager
.createQueryBuilder(GroupUsers, 'groupUsers')
.innerJoinAndSelect('groupUsers.user', 'users', 'groupUsers.groupId = :groupId', { groupId })
.select(['groupUsers.id', 'groupUsers.groupId', 'users.id', 'users.firstName', 'users.lastName', 'users.email'])
.innerJoinAndSelect('groupUsers.user', 'users', 'groupUsers.groupId = :groupId', {
groupId,
})
.innerJoinAndSelect('users.userGroups', 'userRole')
.innerJoinAndSelect('userRole.group', 'role', 'role.organizationId = :organizationId', {
organizationId,
})
.andWhere('role.type = :type', {
type: GROUP_PERMISSIONS_TYPE.DEFAULT,
})
.select([
'groupUsers.id',
'groupUsers.groupId',
'users.id',
'users.firstName',
'users.lastName',
'users.email',
'userRole.id',
'role.name',
])
.addSelect('role.name', 'userRole')
.andWhere(addableUserGetOrConditions(searchInput));
return query;
}

View file

@ -360,7 +360,6 @@ export class AuthService {
},
personalWorkspace.id,
USER_ROLE.ADMIN,
[],
existingUser,
true,
null,
@ -719,7 +718,6 @@ export class AuthService {
},
organization.id,
USER_ROLE.ADMIN,
[],
null,
false,
null,

View file

@ -1,4 +1,4 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { BadRequestException, Injectable, MethodNotAllowedException } from '@nestjs/common';
import { ResourceType } from '@module/user_resource_permissions/constants/granular-permissions.constant';
import {
GranularResourcePermissions,
@ -28,7 +28,7 @@ import {
} from '@module/user_resource_permissions/utility/granular-permissios.utility';
import { GroupPermissionsUtilityService } from '@module/user_resource_permissions/services/group-permissions.utility.service';
import { GroupApps } from 'src/entities/group_apps.entity';
import { GroupPermissions } from 'src/entities/group_permissions.entity';
import { GroupUsers } from 'src/entities/group_users.entity';
@Injectable()
export class GranularPermissionsService {
@ -75,7 +75,7 @@ export class GranularPermissionsService {
return await dbTransactionWrap(async (manager: EntityManager) => {
const granularPermissions = await this.get(id, manager);
const { organizationId, updateGranularPermissionDto, group } = updateGranularPermissionsObj;
const { isAll, name, resourcesToAdd, resourcesToDelete, actions } = updateGranularPermissionDto;
const { isAll, name, resourcesToAdd, resourcesToDelete, actions, allowRoleChange } = updateGranularPermissionDto;
const updateGranularPermission = {
isAll: isAll == true ? true : false,
...(name && { name }),
@ -86,6 +86,7 @@ export class GranularPermissionsService {
actions,
resourcesToDelete,
resourcesToAdd,
allowRoleChange,
};
await catchDbException(async () => {
await manager.update(GranularPermissions, id, updateGranularPermission);
@ -186,41 +187,43 @@ export class GranularPermissionsService {
manager?: EntityManager
) {
return await dbTransactionWrap(async (manager: EntityManager) => {
const {
granularPermissions,
actions,
resourcesToDelete,
resourcesToAdd,
group: permissionGroup,
} = UpdateResourceGroupPermissionsObject;
let group: GroupPermissions;
if (permissionGroup) {
group = permissionGroup;
} else {
group = await manager.findOne(GroupPermissions, granularPermissions.groupId);
}
const { granularPermissions, actions, resourcesToDelete, resourcesToAdd, group, allowRoleChange } =
UpdateResourceGroupPermissionsObject;
validateAppResourcePermissionUpdateOperation(group, actions);
const { canEdit } = actions;
const groupEditors = await this.groupPermissionsUtilityService.getRoleUsersList(
const groupEndUsers = await this.groupPermissionsUtilityService.getRoleUsersList(
USER_ROLE.END_USER,
organizationId,
granularPermissions.groupId,
manager
);
console.log('logging resource object');
if (groupEndUsers.length && canEdit) {
if (!allowRoleChange) {
throw new MethodNotAllowedException({
message: {
error: ERROR_HANDLER.UPDATE_EDITABLE_PERMISSION_END_USER_GROUP,
data: groupEndUsers?.map((user) => user.email),
title: 'Cannot add this permissions to the group',
type: 'USER_ROLE_CHANGE',
},
});
}
await Promise.all(
groupEndUsers.map(async (userItem) => {
const currentRoleUser = userItem.userGroups[0].id;
const roleGroup = await this.groupPermissionsUtilityService.getRoleGroup(
USER_ROLE.BUILDER,
group.organizationId,
manager
);
await manager.delete(GroupUsers, currentRoleUser);
const newUserRole = manager.create(GroupUsers, { groupId: roleGroup.id, userId: userItem.id });
await manager.save(newUserRole);
})
);
}
console.log(UpdateResourceGroupPermissionsObject);
//Resource update level
if (groupEditors.length && canEdit)
throw new BadRequestException({
message: {
error: ERROR_HANDLER.EDITOR_LEVEL_PERMISSIONS_NOT_ALLOWED,
data: groupEditors.map((user) => user.email),
title: 'Cannot update permissions',
},
});
const appsGroupPermissions = await manager.findOne(AppsGroupPermissions, {
where: {
granularPermissionId: granularPermissions.id,

View file

@ -12,6 +12,7 @@ import { dbTransactionWrap, catchDbException } from 'src/helpers/utils.helper';
import { EntityManager, getManager } from 'typeorm';
import {
CreateDefaultGroupObject,
GetGroupUsersObject,
GetUsersResponse,
} from '@module/user_resource_permissions/interface/group-permissions.interface';
import { GroupUsers } from 'src/entities/group_users.entity';
@ -24,7 +25,6 @@ import {
validateUpdateGroupOperation,
} from '@module/user_resource_permissions/utility/group-permissions.utility';
import { GroupPermissionsUtilityService } from '@module/user_resource_permissions/services/group-permissions.utility.service';
import { ResourceType } from '@module/user_resource_permissions/constants/granular-permissions.constant';
@Injectable()
export class GroupPermissionsServiceV2 {
@ -67,47 +67,70 @@ export class GroupPermissionsServiceV2 {
return response;
}
async getGroup(id: string, manager?: EntityManager): Promise<GroupPermissions> {
async getGroup(id: string, manager?: EntityManager): Promise<{ group: GroupPermissions; isBuilderLevel: boolean }> {
return await dbTransactionWrap(async (manager: EntityManager) => {
return await manager.findOne(GroupPermissions, {
where: { id },
});
const [group, isBuilderLevelResourcePermissions] = await Promise.all([
manager.findOne(GroupPermissions, {
where: { id },
}),
await this.groupPermissionsUtilityService.checkIfBuilderLevelResourcesPermissions(id, manager),
]);
const isBuilderLevelMainPermissions = Object.values(group).some(
(value) => typeof value === 'boolean' && value === true
);
const isBuilderLevel = isBuilderLevelResourcePermissions || isBuilderLevelMainPermissions;
return { group, isBuilderLevel };
}, manager);
}
async updateGroup(id: string, updateGroupPermissionDto: UpdateGroupPermissionDto, manager?: EntityManager) {
//License level validation at controller level
const group = await this.getGroup(id);
if (!group) throw new BadRequestException(ERROR_HANDLER.GROUP_NOT_EXIST);
validateUpdateGroupOperation(group, updateGroupPermissionDto);
const keys = Object.keys(updateGroupPermissionDto);
const validatePermissionsUpdate = !(keys.length === 1 && keys.includes('name'));
const editPermissionsPresent = Object.values(updateGroupPermissionDto).some(
(value) => typeof value === 'boolean' && value === true
);
console.log('running till here');
if (validatePermissionsUpdate) {
const getEndUsersList = await this.groupPermissionsUtilityService.getRoleUsersList(
USER_ROLE.END_USER,
group.organizationId,
group.id
);
if (getEndUsersList.length && editPermissionsPresent) {
throw new MethodNotAllowedException({
message: {
error: ERROR_HANDLER.UPDATE_EDITABLE_PERMISSION_END_USER_GROUP,
data: getEndUsersList?.map((user) => user.email),
title: 'Cannot add this permissions to the group',
},
});
}
}
return await dbTransactionWrap(async (manager: EntityManager) => {
const { group } = await this.getGroup(id);
if (!group) throw new BadRequestException(ERROR_HANDLER.GROUP_NOT_EXIST);
validateUpdateGroupOperation(group, updateGroupPermissionDto);
const { allowRoleChange } = updateGroupPermissionDto;
delete updateGroupPermissionDto.allowRoleChange;
const keys = Object.keys(updateGroupPermissionDto);
const validatePermissionsUpdate = !(keys.length === 1 && keys.includes('name'));
const editPermissionsPresent = Object.keys(updateGroupPermissionDto).some(
(value) => typeof updateGroupPermissionDto?.[value] === 'boolean' && updateGroupPermissionDto?.[value] === true
);
if (validatePermissionsUpdate) {
const getEndUsersList = await this.groupPermissionsUtilityService.getRoleUsersList(
USER_ROLE.END_USER,
group.organizationId,
group.id
);
if (getEndUsersList.length && editPermissionsPresent) {
if (!allowRoleChange) {
throw new MethodNotAllowedException({
message: {
error: ERROR_HANDLER.UPDATE_EDITABLE_PERMISSION_END_USER_GROUP,
data: getEndUsersList?.map((user) => user.email),
title: 'Cannot add this permissions to the group',
type: 'USER_ROLE_CHANGE',
},
});
}
await Promise.all(
getEndUsersList.map(async (userItem) => {
const currentRoleUser = userItem.userGroups[0].id;
const roleGroup = await this.groupPermissionsUtilityService.getRoleGroup(
USER_ROLE.BUILDER,
group.organizationId,
manager
);
await this.deleteGroupUser(currentRoleUser, manager);
const newUserRole = manager.create(GroupUsers, { groupId: roleGroup.id, userId: userItem.id });
await manager.save(newUserRole);
})
);
}
}
return await catchDbException(async () => {
await manager.update(GroupPermissions, id, updateGroupPermissionDto);
}, [DATA_BASE_CONSTRAINTS.GROUP_NAME_UNIQUE]);
@ -116,7 +139,7 @@ export class GroupPermissionsServiceV2 {
async deleteGroup(id: string): Promise<void> {
return await dbTransactionWrap(async (manager: EntityManager) => {
const group = await this.getGroup(id, manager);
const { group } = await this.getGroup(id, manager);
if (group.type == GROUP_PERMISSIONS_TYPE.DEFAULT)
throw new BadRequestException(ERROR_HANDLER.DEFAULT_GROUP_UPDATE_NOT_ALLOWED);
return await manager.delete(GroupPermissions, id);
@ -124,17 +147,31 @@ export class GroupPermissionsServiceV2 {
}
private async createGroupUser(user: User, group: GroupPermissions, manager?: EntityManager): Promise<GroupUsers> {
console.log(group);
console.log('logging group');
const createObjec = {
userId: user.id,
groupId: group.id,
};
console.log(createObjec);
return await dbTransactionWrap(async (manager: EntityManager) => {
return await catchDbException(async () => {
const groupUser = manager.create(GroupUsers, { groupId: group.id, userId: user.id });
const groupUser = manager.create(GroupUsers, createObjec);
console.log(groupUser);
return await manager.save(groupUser);
}, [DATA_BASE_CONSTRAINTS.GROUP_USER_UNIQUE]);
}, manager);
}
async getAllGroupUsers(groupId: string, searchInput?: string, manager?: EntityManager): Promise<GroupUsers[]> {
async getAllGroupUsers(
getGroupUsersObject: GetGroupUsersObject,
searchInput?: string,
manager?: EntityManager
): Promise<GroupUsers[]> {
return await dbTransactionWrap(async (manager: EntityManager) => {
return await getUserInGroupQuery(groupId, manager, searchInput).getMany();
return await getUserInGroupQuery(getGroupUsersObject, manager, searchInput).getMany();
}, manager);
}
@ -159,33 +196,44 @@ export class GroupPermissionsServiceV2 {
}
async addGroupUsers(addGroupUserDto: AddGroupUserDto, organizationId: string, manager?: EntityManager) {
const { userIds, groupId } = addGroupUserDto;
const { userIds, groupId, allowRoleChange } = addGroupUserDto;
return await dbTransactionWrap(async (manager: EntityManager) => {
const group = await this.getGroup(groupId, manager);
const granularPermission = await this.granularPermissionsService.getAll({ groupId: group.id }, manager);
const { group, isBuilderLevel } = await this.getGroup(groupId, manager);
validateAddGroupUserOperation(group);
const editorRoleUsers = await this.groupPermissionsUtilityService.getRoleUsersList(
USER_ROLE.END_USER,
organizationId
);
const editorUsersToBeAdded = editorRoleUsers.filter((user) => userIds.includes(user.id));
if (isBuilderLevel && editorUsersToBeAdded.length) {
if (!allowRoleChange) {
throw new MethodNotAllowedException({
message: {
error: ERROR_HANDLER.UPDATE_EDITABLE_PERMISSION_END_USER_GROUP,
data: editorUsersToBeAdded?.map((user) => user.email),
title: 'Cannot add this permissions to the group',
type: 'USER_ROLE_CHANGE_ADD_USERS',
},
});
}
await Promise.all(
editorUsersToBeAdded.map(async (userItem) => {
const currentRoleUser = userItem.userGroups[0].id;
const roleGroup = await this.groupPermissionsUtilityService.getRoleGroup(
USER_ROLE.BUILDER,
organizationId,
manager
);
await this.deleteGroupUser(currentRoleUser, manager);
const newUserRole = manager.create(GroupUsers, { groupId: roleGroup.id, userId: userItem.id });
await manager.save(newUserRole);
})
);
}
return await Promise.all(
userIds.map(async (userId) => {
const user = await getUserDetailQuery(userId, organizationId, manager).getOne();
if (!user) throw new BadRequestException(ERROR_HANDLER.ADD_GROUP_USER_NON_EXISTING_USER);
const role = await this.groupPermissionsUtilityService.getUserRole(userId, organizationId, manager);
const editPermissionsPresent =
Object.values(group).some((value) => typeof value === 'boolean' && value === true) ||
granularPermission.some((value) => {
return value.type === ResourceType.APP && value.appsGroupPermissions.canEdit;
});
if (editPermissionsPresent && role.name == USER_ROLE.END_USER) {
throw new MethodNotAllowedException({
message: {
error: ERROR_HANDLER.GROUP_USERS_EDITABLE_GROUP_ADDITION(user.email),
title: 'Can not add end user to this group',
},
});
}
return await this.createGroupUser(user, group, manager);
})
);

View file

@ -100,6 +100,9 @@ export class OrganizationUsersService {
}
async updateOrgUser(organizationUserId: string, updateUserDto) {
console.log(updateUserDto);
console.log('logging this');
const organizationUser = await this.organizationUsersRepository.findOne({ where: { id: organizationUserId } });
return await this.usersService.update(
organizationUser.userId,

View file

@ -619,7 +619,6 @@ export class OrganizationsService {
userParams,
currentUser.organizationId,
role,
groups,
user,
true,
defaultOrganization?.id,
@ -649,6 +648,8 @@ export class OrganizationsService {
manager
);
await this.usersService.attachUserGroup(groups, currentOrganization.id, user.id, manager);
const name = fullName(currentUser.firstName, currentUser.lastName);
if (shouldSendWelcomeMail) {
this.emailService

View file

@ -6,7 +6,6 @@ import {
USER_ROLE,
ERROR_HANDLER,
DEFAULT_GROUP_PERMISSIONS,
GROUP_PERMISSIONS_TYPE,
} from '@module/user_resource_permissions/constants/group-permissions.constant';
import { dbTransactionWrap } from 'src/helpers/utils.helper';
import { EntityManager } from 'typeorm';
@ -72,9 +71,7 @@ export class UserRoleService {
async getRoleGroup(role: USER_ROLE, organizationId: string, manager?: EntityManager) {
return await dbTransactionWrap(async (manager) => {
return await manager.findOne(GroupPermissions, {
where: { name: role, organizationId, type: GROUP_PERMISSIONS_TYPE.DEFAULT },
});
return await this.groupPermissionsUtilityService.getRoleGroup(role, organizationId, manager);
}, manager);
}
@ -94,7 +91,11 @@ export class UserRoleService {
throw new BadRequestException(ERROR_HANDLER.DEFAULT_GROUP_ADD_USER_ROLE_EXIST(newRole));
if (userRole.name == USER_ROLE.ADMIN) {
const groupUsers = await this.groupPermissionsService.getAllGroupUsers(userRole.id, null, manager);
const groupUsers = await this.groupPermissionsService.getAllGroupUsers(
{ groupId: userRole.id, organizationId },
null,
manager
);
if (groupUsers.length < 2)
throw new BadRequestException({
message: {
@ -143,9 +144,6 @@ export class UserRoleService {
const { role, userId } = addUserRoleObject;
return await dbTransactionWrap(async (manager: EntityManager) => {
const roleGroup = await this.getRoleGroup(role, organizationId, manager);
console.log('role group is');
console.log(roleGroup);
const newUserRole = manager.create(GroupUsers, { groupId: roleGroup.id, userId });
await manager.save(newUserRole);
}, manager);

View file

@ -98,7 +98,6 @@ export class UsersService {
userParams: Partial<User>,
organizationId: string,
role: USER_ROLE,
groups?: string[],
existingUser?: User,
isInvite?: boolean,
defaultOrganizationId?: string,
@ -136,8 +135,6 @@ export class UsersService {
);
}
await this.userRoleService.addUserRole({ role, userId: user.id }, organizationId, manager);
await this.attachUserGroup(groups, organizationId, user.id, manager);
}, manager);
return user;
@ -150,10 +147,21 @@ export class UsersService {
manager?: EntityManager
): Promise<void> {
if (!groups) return;
console.log('Adding groups');
console.log(groups);
await dbTransactionWrap(async (manager: EntityManager) => {
if (groups?.length)
await this.groupPermissionsUtilityService.validateEditUserGroupPermissionsAddition(
{ userId, groupsToAddIds: groups, organizationId },
manager
);
await Promise.all(
groups.map(async (groupId) => {
await this.groupPermissionsService.addGroupUsers({ userIds: [userId], groupId }, organizationId, manager);
await this.groupPermissionsService.addGroupUsers(
{ userIds: [userId], groupId, allowRoleChange: false },
organizationId,
manager
);
})
);
}, manager);
@ -181,6 +189,8 @@ export class UsersService {
await this.removeUserGroupPermissionsIfExists(manager, user, removeGroups, organizationId);
if (role) await this.userRoleService.editDefaultGroupUserRole({ userId, newRole: role }, organizationId, manager);
console.log('working till here');
await this.attachUserGroup(addGroups, organizationId, userId, manager);
return user;
}, manager);
@ -195,29 +205,6 @@ export class UsersService {
}, manager);
}
//TODO: Remove this function if not needed
// async addUserGroupPermissions(manager: EntityManager, user: User, addGroups: string[], organizationId?: string) {
// const orgId = organizationId || user.defaultOrganizationId;
// if (addGroups) {
// const orgGroupPermissions = await this.groupPermissionsForOrganization(orgId);
// for (const group of addGroups) {
// const orgGroupPermission = orgGroupPermissions.find((permission) => permission.group == group);
// if (!orgGroupPermission) {
// throw new BadRequestException(`${group} group does not exist for current organization`);
// }
// await dbTransactionWrap(async (manager: EntityManager) => {
// const userGroupPermission = manager.create(UserGroupPermission, {
// groupPermissionId: orgGroupPermission.id,
// userId: user.id,
// });
// await manager.save(userGroupPermission);
// }, manager);
// }
// }
// }
async removeUserGroupPermissionsIfExists(
manager: EntityManager,
user: User,