Modify bulk upload, inspector and design fix

This commit is contained in:
kriks7iitk 2024-07-07 13:59:29 +05:30
parent 41b0c6c1b6
commit 8426e2248e
19 changed files with 106 additions and 107 deletions

View file

@ -223,12 +223,15 @@ const EditorComponent = (props) => {
// Subscribe to changes in the current session using RxJS observable pattern
const subscription = authenticationService.currentSession.subscribe((currentSession) => {
if (currentUser && currentSession?.group_permissions) {
if (currentUser && (currentSession?.group_permissions || currentSession?.role)) {
const userVars = {
email: currentUser.email,
firstName: currentUser.first_name,
lastName: currentUser.last_name,
groups: currentSession.group_permissions?.map((group) => group.name),
groups: currentSession?.group_permissions
? ['all_users', ...currentSession.group_permissions.map((group) => group.name)]
: ['all_users'],
role: currentSession?.role?.name,
};
const appUserDetails = {

View file

@ -280,13 +280,16 @@ class ViewerComponent extends React.Component {
const currentUser = this.state.currentUser;
let userVars = {};
const currentSessionValue = authenticationService.currentSessionValue;
if (currentUser) {
userVars = {
email: currentUser.email,
firstName: currentUser.first_name,
lastName: currentUser.last_name,
groups: authenticationService.currentSessionValue?.group_permissions.map((group) => group.name),
groups: currentSessionValue?.group_permissions
? ['All Users', ...currentSessionValue.group_permissions.map((group) => group.name)]
: ['All Users'],
role: currentSessionValue?.role?.name,
};
}
@ -550,15 +553,18 @@ class ViewerComponent extends React.Component {
const versionId = this.props.versionId;
if (currentSession?.load_app && slug) {
if (currentSession?.group_permissions) {
if (currentSession?.group_permissions || currentSession?.role) {
useAppDataStore.getState().actions.setAppId(appId);
const currentUser = currentSession.current_user;
const currentSessionValue = authenticationService.currentSessionValue;
const userVars = {
email: currentUser.email,
firstName: currentUser.first_name,
lastName: currentUser.last_name,
groups: currentSession?.group_permissions?.map((group) => group.name),
groups: currentSessionValue?.group_permissions
? ['All Users', ...currentSessionValue.group_permissions.map((group) => group.name)]
: ['All Users'],
};
this.props.setCurrentState({
globals: {

View file

@ -30,7 +30,6 @@ function AppResourcePermissions({
setHover(false);
}}
onClick={() => {
if (notClickable) console.log('this is runing');
!isRoleGroup && !notClickable && openEditPermissionModal(permissions);
}}
>

View file

@ -49,7 +49,6 @@ class ManageGranularAccessComponent extends React.Component {
}
componentDidMount() {
console.log('addable apps are');
this.fetchAppsCanBeAdded();
this.fetchGranularPermissions(this.props.groupPermissionId);
}
@ -58,8 +57,6 @@ class ManageGranularAccessComponent extends React.Component {
groupPermissionV2Service
.fetchAddableApps()
.then((data) => {
console.log('fetching app');
console.log(data);
const addableApps = data.map((app) => {
return {
name: app.name,
@ -67,7 +64,6 @@ class ManageGranularAccessComponent extends React.Component {
label: app.name,
};
});
console.log(addableApps);
this.setState({
addableApps,
});
@ -232,8 +228,6 @@ class ManageGranularAccessComponent extends React.Component {
const groupAppsToDelete = currentEditingPermissions?.appsGroupPermissions?.groupApps?.filter((groupApp) =>
appsToDelete?.includes(groupApp.appId)
);
console.log('logging groups apps to delete');
console.log(groupAppsToDelete);
const resourcesToDelete = groupAppsToDelete?.map(({ id }) => {
return {
id: id,
@ -320,8 +314,6 @@ class ManageGranularAccessComponent extends React.Component {
};
setSelectedApps = (values) => {
console.log('Logging selected values');
console.log(values);
this.setState({ selectedApps: values });
};
@ -338,7 +330,6 @@ class ManageGranularAccessComponent extends React.Component {
});
};
handleConfirmAutoRoleChangeGroupUpdate = () => {
console.log('this is running');
this.updateGranularPermissions(true);
this.handleAutoRoleChangeModalClose();
};

View file

@ -73,8 +73,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
groupPermissionService
.getUsersNotInGroup(query, groupPermissionId)
.then(({ users }) => {
console.log('logging users');
console.log(users);
resolve(
users.map((user) => {
return {

View file

@ -102,8 +102,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
groupPermissionV2Service
.getUsersNotInGroup(query, groupPermissionId)
.then((users) => {
console.log('loggimgusers');
console.log(users);
resolve(
users.map((user) => {
return {
@ -152,7 +150,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
this.fetchGroupPermission(groupPermissionId);
})
.catch(({ error }) => {
console.log(error);
if (error?.type) {
this.setState({
showAutoRoleChangeModal: true,
@ -173,8 +170,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
};
setSelectedUsers = (value) => {
console.log('user value');
console.log(value);
this.setState({
selectedUsers: value,
});
@ -187,8 +182,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
};
addSelectedUsersToGroup = (groupPermissionId, selectedUsers, allowRoleChange) => {
console.log('selected users');
console.log(selectedUsers);
this.setState({ isAddingUsers: true });
const body = {
userIds: selectedUsers.map((user) => user.value),
@ -198,7 +191,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
groupPermissionV2Service
.addUsersInGroups(body)
.then(() => {
console.log('this is running');
this.setState({
selectedUsers: [],
isLoadingUsers: true,
@ -320,7 +312,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
});
changeThisComponentState = (state = {}) => {
console.log('this is changing');
this.setState(state);
};
@ -390,7 +381,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
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({
@ -703,7 +693,7 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
</div>
)}
<section>
<section className="group-users-list-container">
{isLoadingGroup || isLoadingUsers ? (
<tr>
<td className="col-auto">
@ -722,7 +712,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
usersInGroup.map((item) => {
const user = item.user;
const groupUserId = item.id;
console.log(user);
return (
<div
key={user.id}

View file

@ -189,15 +189,12 @@ class ManageGroupPermissionsComponent extends React.Component {
.then((data) => {
const groupPermissions = data.groupPermissions;
const defaultGroups = this.sortDefaultGroup(groupPermissions.filter((group) => group.type === 'default'));
console.log('logging group');
const currentGroupId =
type == 'admin'
? defaultGroups[0].id
: type == 'current'
? this.findCurrentGroupDetails(groupPermissions)
: groupPermissions.at(-1).id;
console.log(groupPermissions.find((group) => group.id === currentGroupId));
this.setState(
{
groups: groupPermissions.filter((group) => group.type === 'custom'),

View file

@ -120,8 +120,6 @@ function InviteUsersForm({
};
const handleEditUser = (e) => {
console.log(currentEditingUser);
console.log(newRole);
e.preventDefault();
if (newRole) setIsChangeRoleModalOpen(true);
else {
@ -354,7 +352,11 @@ function InviteUsersForm({
type="submit"
variant="primary"
disabled={
uploadingUsers || creatingUser || !isEdited() || (!isEditing && !containRoleGroup) || !validUserDetail
uploadingUsers ||
creatingUser ||
!isEdited() ||
(!isEditing && !containRoleGroup && uploadingUsers) ||
(!isEditing && !validUserDetail && uploadingUsers)
}
data-cy={activeTab == 1 ? 'button-invite-users' : 'button-upload-users'}
leftIcon={activeTab == 1 ? 'sent' : 'fileupload'}

View file

@ -79,7 +79,6 @@ class ManageOrgUsersComponent extends React.Component {
if (!this.state.file) {
errors['file'] = 'This field is required';
}
this.setState({ errors: errors });
return Object.keys(errors).length === 0;
}

View file

@ -38,16 +38,17 @@ export default function LogoNavDropdown({ darkMode }) {
<span>Database</span>
</Link>
)}
<Link
to={getPrivateRoute('data_sources')}
className="dropdown-item tj-text tj-text-xsm"
target="_blank"
data-cy="data-source-option"
>
<SolidIcon name="datasource" width="20" />
<span>Data sources</span>
</Link>
{admin && (
<Link
to={getPrivateRoute('data_sources')}
className="dropdown-item tj-text tj-text-xsm"
target="_blank"
data-cy="data-source-option"
>
<SolidIcon name="datasource" width="20" />
<span>Data sources</span>
</Link>
)}
<Link
to={getPrivateRoute('workspace_constants')}
className="dropdown-item tj-text tj-text-xsm"

View file

@ -20,6 +20,7 @@ const currentSessionSubject = new BehaviorSubject({
user_permissions: null,
group_permissions: null,
app_group_permissions: null,
role: null,
organizations: [],
isUserLoggingIn: false,
authentication_status: null,

View file

@ -11,7 +11,6 @@ export const organizationUserService = {
};
function create(id, body) {
console.log(body);
const requestOptions = { method: 'POST', headers: authHeader(), credentials: 'include', body: JSON.stringify(body) };
return fetch(`${config.apiUrl}/organization_users`, requestOptions).then(handleResponse);
}
@ -42,7 +41,6 @@ function unarchive(id) {
}
function updateOrgUser(id, body) {
console.log(body);
const requestOptions = { method: 'PUT', headers: authHeader(), credentials: 'include', body: JSON.stringify(body) };
return fetch(`${config.apiUrl}/organization_users/${id}`, requestOptions).then(handleResponse);
}

View file

@ -9467,6 +9467,12 @@ tbody {
// overflow-y: auto;
height: calc(100vh - 300px);
.group-users-list-container{
height: calc(100vh - 300px - 100px); /* Set a fixed height */
overflow-y: auto; /* Enable vertical scrolling */
border-bottom: 1px solid var(--slate6) !important;
}
}
.groups-sub-header-wrap {
@ -9788,6 +9794,9 @@ tbody {
text-transform: capitalize;
}
.manage-group-users-row {
display: flex;
flex-direction: row;
@ -9824,6 +9833,7 @@ tbody {
}
}
.manage-group-app-table-body {
width: 602px !important;

View file

@ -11,9 +11,6 @@ export function AppsSelect(props) {
const workspaceId = getWorkspaceId();
const darkMode = localStorage.getItem('darkMode') === 'true';
console.log('Props prinitng');
console.log(props.options);
//Will be used when workspace routing settings have been merged
const Menu = (props) => {
return (
@ -182,8 +179,6 @@ export function AppsSelect(props) {
isSelectAllPresentInSelection &&
!isCurrentSelectAll
) {
console.log('value');
console.log(props.value);
if (props.value.find((app) => app?.isAllField)?.isAllField)
props.onChange(selected.filter((app) => !app?.isAllField));
return props.onChange([...props.options, props.allOption]);

View file

@ -8,19 +8,19 @@ import { APP_RESOURCE_ACTIONS, TOOLJET_RESOURCE } from 'src/constants/global.con
type Actions =
| 'authorizeOauthForSource' //Deprecated
| APP_RESOURCE_ACTIONS.CLONE //
| APP_RESOURCE_ACTIONS.IMPORT //
| APP_RESOURCE_ACTIONS.CREATE //
| 'createDataSource' //
| 'createQuery' //
| 'createUsers' //
| APP_RESOURCE_ACTIONS.VERSIONS_CREATE //
| APP_RESOURCE_ACTIONS.VERSION_DELETE //
| 'deleteApp' //
| 'deleteDataSource' //
| 'deleteQuery' //
| 'fetchUsers' //
| APP_RESOURCE_ACTIONS.VERSION_READ //
| APP_RESOURCE_ACTIONS.CLONE
| APP_RESOURCE_ACTIONS.IMPORT
| APP_RESOURCE_ACTIONS.CREATE
| 'createDataSource'
| 'createQuery'
| 'createUsers'
| APP_RESOURCE_ACTIONS.VERSIONS_CREATE
| APP_RESOURCE_ACTIONS.VERSION_DELETE
| 'deleteApp'
| 'deleteDataSource'
| 'deleteQuery'
| 'fetchUsers'
| APP_RESOURCE_ACTIONS.VERSION_READ
| 'getDataSources'
| 'getQueries'
| 'previewQuery'
@ -71,8 +71,8 @@ export class AppsAbilityFactory {
if (userPermission.appCreate) {
can(APP_RESOURCE_ACTIONS.CREATE, App);
can(APP_RESOURCE_ACTIONS.IMPORT, App);
can(APP_RESOURCE_ACTIONS.EXPORT, App);
if (appUpdateAllowed) {
can(APP_RESOURCE_ACTIONS.EXPORT, App);
can(APP_RESOURCE_ACTIONS.CLONE, App);
}
}

View file

@ -121,9 +121,6 @@ export function getAllUserGroupsQuery(
})
.where('groupUsers.userId = :userId', {
userId,
})
.andWhere('groups.type = :type', {
type: GROUP_PERMISSIONS_TYPE.CUSTOM_GROUP,
});
return query;
}

View file

@ -46,7 +46,10 @@ import { CookieOptions, Response } from 'express';
import { SessionService } from './session.service';
import { RequestContext } from 'src/models/request-context.model';
import * as requestIp from 'request-ip';
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 { ActivateAccountWithTokenDto } from '@dto/activate-account-with-token.dto';
import { AppAuthenticationDto, AppSignupDto } from '@dto/app-authentication.dto';
import { SIGNUP_ERRORS } from 'src/helpers/errors.constants';
@ -244,11 +247,13 @@ export class AuthService {
return decamelizeKeys({
currentOrganizationId: user.organizationId,
currentOrganizationSlug: organization.slug,
//Check this for permissions.........
currentOrganizationName: organization.name,
admin: await this.usersService.hasGroup(user, USER_ROLE.ADMIN, null, manager),
userPermissions: userPermissions,
groupPermissions: permissions,
groupPermissions: permissions.filter(
(group) => group.type === GROUP_PERMISSIONS_TYPE.CUSTOM_GROUP || group.name === USER_ROLE.ADMIN
),
role: permissions.find((group) => group.type === GROUP_PERMISSIONS_TYPE.DEFAULT),
appGroupPermissions: appGroupPermissions,
currentUser: {
id: user.id,

View file

@ -16,7 +16,6 @@ import { Brackets, createQueryBuilder, DeepPartial, EntityManager, getManager, R
import { OrganizationUser } from '../entities/organization_user.entity';
import { EmailService } from './email.service';
import { EncryptionService } from './encryption.service';
import { GroupPermissionsService } from './group_permissions.service';
import { OrganizationUsersService } from './organization_users.service';
import { DataSourcesService } from './data_sources.service';
import { UsersService } from './users.service';
@ -29,7 +28,6 @@ import {
USER_STATUS,
WORKSPACE_USER_STATUS,
} from 'src/helpers/user_lifecycle';
import { decamelize } from 'humps';
import { Response } from 'express';
import { AppEnvironmentService } from './app_environments.service';
import { DataBaseConstraints } from 'src/helpers/db_constraints.constants';
@ -44,6 +42,7 @@ import { DataSource } from 'src/entities/data_source.entity';
import { AppEnvironment } from 'src/entities/app_environments.entity';
import { DataSourceOptions } from 'src/entities/data_source_options.entity';
import { ERROR_HANDLER, ERROR_HANDLER_TITLE } from '@module/organizations/constant/constants';
import { GroupPermissionsServiceV2 } from './group_permissions.service.v2';
const MAX_ROW_COUNT = 500;
@ -64,6 +63,7 @@ interface UserCsvRow {
first_name: string;
last_name: string;
email: string;
role: string;
groups?: any;
}
@ -88,7 +88,7 @@ export class OrganizationsService {
private usersService: UsersService,
private dataSourceService: DataSourcesService,
private organizationUserService: OrganizationUsersService,
private groupPermissionService: GroupPermissionsService,
private groupPermissionService: GroupPermissionsServiceV2,
private appEnvironmentService: AppEnvironmentService,
private encryptionService: EncryptionService,
private emailService: EmailService,
@ -671,14 +671,8 @@ export class OrganizationsService {
}, manager);
}
decamelizeDefaultGroupNames(groups: string) {
return groups?.length
? groups
.split('|')
.map((group: string) =>
group === 'All Users' || group === 'Admin' ? decamelize(group.replace(' ', '')) : group
)
: [];
createGroupsList(groups: string) {
return groups?.length ? groups.split('|') : [];
}
async inviteUserswrapper(users, currentUser: User): Promise<void> {
@ -689,6 +683,19 @@ export class OrganizationsService {
});
}
convertUserRolesCasing(role: string) {
switch (role) {
case 'End User':
return 'end-user';
case 'Builder':
return 'builder';
case 'Admin':
return 'admin';
default:
break;
}
}
async bulkUploadUsers(currentUser: User, fileStream, res: Response) {
const users = [];
const existingUsers = [];
@ -696,14 +703,12 @@ export class OrganizationsService {
const invalidRows = [];
const invalidFields = new Set();
const invalidGroups = [];
let isUserInOtherGroupsAndAdmin = false;
const emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
const manager = getManager();
//New group permissions change
const groupPermissions = await this.groupPermissionService.findAll(currentUser);
const existingGroups = groupPermissions.map((groupPermission) => groupPermission.group);
const invalidRoles = [];
const groupPermissions = (await this.groupPermissionService.getAllGroup(currentUser.organizationId))
.groupPermissions;
const existingGroups = groupPermissions.map((groupPermission) => groupPermission.name);
csv
.parseString(fileStream.toString(), {
headers: ['first_name', 'last_name', 'email', 'groups', 'role'],
@ -713,13 +718,18 @@ export class OrganizationsService {
.transform((row: UserCsvRow, next) => {
return next(null, {
...row,
groups: this.decamelizeDefaultGroupNames(row?.groups),
groups: this.createGroupsList(row?.groups),
role: this.convertUserRolesCasing(row?.role),
});
})
.validate(async (data: UserCsvRow, next) => {
await dbTransactionWrap(async (manager: EntityManager) => {
//Check for existing users
let isInvalidRole = false;
const user = await this.usersService.findByEmail(data?.email, undefined, undefined, manager);
console.log(data);
console.log('loggin row');
if (user?.status === USER_STATUS.ARCHIVED) {
archivedUsers.push(data?.email);
@ -734,27 +744,29 @@ export class OrganizationsService {
if (Array.isArray(receivedGroups)) {
for (const group of receivedGroups) {
if (group === 'admin' && receivedGroups.includes('all_users') && receivedGroups.length > 2) {
isUserInOtherGroupsAndAdmin = true;
break;
}
if (existingGroups.indexOf(group) === -1) {
invalidGroups.push(group);
}
}
}
if (!Object.values(USER_ROLE).includes(data?.role as USER_ROLE)) {
invalidRoles.push(data?.role);
isInvalidRole = true;
}
data.first_name = data.first_name?.trim();
data.last_name = data.last_name?.trim();
const isValidName = data.first_name !== '' || data.last_name !== '';
return next(null, isValidName && emailPattern.test(data.email) && receivedGroups?.length > 0);
return next(null, isValidName && emailPattern.test(data.email) && !isInvalidRole);
}, manager);
})
.on('data', function () {})
.on('data-invalid', (row, rowNumber) => {
console.log('invalid row');
console.log(row);
const invalidField = Object.keys(row).filter((key) => {
if (Array.isArray(row[key])) {
return row[key].length === 0;
@ -778,18 +790,16 @@ export class OrganizationsService {
throw new BadRequestException(errorMsg);
}
if (isUserInOtherGroupsAndAdmin) {
throw new BadRequestException(
'Conflicting Group Memberships: User cannot be in both the Admin group and other groups simultaneously.'
);
}
if (invalidGroups.length) {
throw new BadRequestException(
`${invalidGroups.length} group${isPlural(invalidGroups)} doesn't exist. No users were uploaded`
);
}
if (invalidRoles.length > 0) {
throw new BadRequestException('Invalid role present for the users');
}
if (archivedUsers.length) {
throw new BadRequestException(
`User${isPlural(archivedUsers)} with email ${archivedUsers.join(

View file

@ -37,11 +37,9 @@ export class AbilityService {
resourcePermissionsObject: ResourcePermissionQueryObject
): Promise<UserPermissions> {
const permissions = await this.getResourcePermission(user, resourcePermissionsObject);
console.log('loggin permissions');
const adminGroup = permissions.find((group) => group.name === USER_ROLE.ADMIN);
const appsGranularPermissions = permissions.flatMap((item) => item.groupGranularPermissions);
console.log(appsGranularPermissions);
const userPermissions: UserPermissions = permissions.reduce((acc, group) => {
return {
isAdmin: !!adminGroup,