Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

View user details #679

Merged
merged 29 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
14f03e1
View user details (#673)
KjartanE Dec 10, 2021
017da4b
added delete functionality and error handling.
KjartanE Dec 10, 2021
ecad61c
Delete user button added and errors handled.
KjartanE Dec 13, 2021
af1f603
Handled selected User reload.
KjartanE Dec 13, 2021
38a0ff7
merge dev
KjartanE Dec 16, 2021
b353d46
code cleaned up and api end point moved.
KjartanE Dec 16, 2021
d3e984d
fixed code smeels and formatting
KjartanE Dec 16, 2021
cb8c66b
reduce duplication, and remove local storage
KjartanE Dec 17, 2021
ab0deec
integrate re-fetch user from api and loading icon
KjartanE Dec 17, 2021
6c00230
Update app/src/hooks/api/useUserApi.ts
KjartanE Dec 17, 2021
d5c6fe7
Merge branch 'dev' of https://github.com/bcgov/biohubbc into view_use…
KjartanE Dec 20, 2021
38ee4b1
Detail edits and refactor
KjartanE Dec 20, 2021
9494b55
Merge branch 'view_user_details' of https://github.com/bcgov/biohubbc…
KjartanE Dec 20, 2021
ee49021
Added api tests and fixed frontend tests
KjartanE Dec 20, 2021
2692037
removed .only
KjartanE Dec 20, 2021
2d55d4f
fixed bad actual return.
KjartanE Dec 20, 2021
fccf29b
Added no projects handler.
KjartanE Dec 20, 2021
8642856
small UI changes
KjartanE Dec 20, 2021
00a9c5f
Large refactor
KjartanE Dec 21, 2021
b9bc083
Working verison of checkProjectLead refactor
KjartanE Dec 21, 2021
1220949
Final fixes to error messages and delete user.
KjartanE Dec 22, 2021
39820fb
front end testing
KjartanE Dec 22, 2021
8dce481
- Update tests
NickPhura Dec 22, 2021
2e75244
Merge branch 'view_user_details' of https://github.com/bcgov/biohubbc…
NickPhura Dec 22, 2021
86298d0
Merge branch 'dev' of https://github.com/bcgov/biohubbc into view_use…
KjartanE Dec 22, 2021
4b6513a
Merge branch 'dev' into view_user_details
NickPhura Dec 22, 2021
69e95b6
Merge branch 'view_user_details' of https://github.com/bcgov/biohubbc…
KjartanE Dec 22, 2021
ab4f045
format-fix
KjartanE Dec 22, 2021
7d4cf20
Tweaks
NickPhura Dec 23, 2021
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
11,789 changes: 11,775 additions & 14 deletions api/package-lock.json

Large diffs are not rendered by default.

145 changes: 145 additions & 0 deletions api/src/paths/user/{userId}/get-projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { RequestHandler } from 'express';
KjartanE marked this conversation as resolved.
Show resolved Hide resolved
import { Operation } from 'express-openapi';
import { getDBConnection } from '../../../database/db';
import { HTTP400 } from '../../../errors/CustomError';
import { projectIdResponseObject } from '../../../openapi/schemas/project';
import { getAllUserProjectsSQL } from '../../../queries/project-participation/project-participation-queries';
import { getLogger } from '../../../utils/logger';

const defaultLog = getLogger('paths/projects');
export const POST: Operation = [getAllUserProjects()];

POST.apiDoc = {
description: 'Gets a list of projects based on user Id.',
tags: ['projects'],
security: [
{
Bearer: []
}
],
requestBody: {
description: 'Project list user ID.',
content: {
'application/json': {
schema: {
title: 'Project Response Object',
required: ['userId'],
properties: {
userId: {
type: 'number',
nullable: false
}
}
}
}
}
},
responses: {
200: {
description: 'Project response object.',
content: {
'application/json': {
schema: {
type: 'array',
items: {
...(projectIdResponseObject as object)
}
}
}
}
},
400: {
$ref: '#/components/responses/400'
},
401: {
$ref: '#/components/responses/401'
},
403: {
$ref: '#/components/responses/401'
},
500: {
$ref: '#/components/responses/500'
},
default: {
$ref: '#/components/responses/default'
}
}
};

/**
* Get all projects (potentially based on filter criteria).
*
* @returns {RequestHandler}
*/
function getAllUserProjects(): RequestHandler {
return async (req, res) => {
const connection = getDBConnection(req['keycloak_token']);

const userId = Number(req?.body?.userId);

if (!userId) {
throw new HTTP400('Missing required body param: userId');
}

try {
await connection.open();

const getAllUserProjectsSQLStatement = getAllUserProjectsSQL(userId);

if (!getAllUserProjectsSQLStatement) {
throw new HTTP400('Failed to build SQL get statement');
}

const getUserProjectsListResponse = await connection.query(
getAllUserProjectsSQLStatement.text,
getAllUserProjectsSQLStatement.values
);

await connection.commit();

let rows: any[] = [];

if (getUserProjectsListResponse && getUserProjectsListResponse.rows) {
rows = getUserProjectsListResponse.rows;
}

const result: any[] = _extractProjects(rows);

return res.status(200).json(result);
} catch (error) {
defaultLog.error({ label: 'getAllUserProjects', message: 'error', error });
throw error;
} finally {
connection.release();
}
};
}

/**
* Extract an array of project data from DB query.
*
* @export
* @param {any[]} rows DB query result rows
* @return {any[]} An array of project data
*/
export function _extractProjects(rows: any[]): any[] {
if (!rows || !rows.length) {
return [];
}

const projects: any[] = [];

rows.forEach((row) => {
const project: any = {
project_id: row.project_id,
name: row.name,
system_user_id: row.system_user_id,
project_role_id: row.project_role_id,
project_participation_id: row.project_participation_id
};

projects.push(project);
});

return projects;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,51 @@ import { getLogger } from '../../utils/logger';

const defaultLog = getLogger('queries/permit/permit-create-queries');

/**
* SQL query to get all projects from user Id.
*
* @param {userId} userId
* @returns {SQLStatement} sql query object
*/
export const getAllUserProjectsSQL = (userId: number): SQLStatement | null => {
defaultLog.debug({
label: 'getAllUserProjectsSQL',
message: 'params',
userId
});

if (!userId) {
return null;
}
console.log('INSIDE THE SQL CREATION ');
KjartanE marked this conversation as resolved.
Show resolved Hide resolved

const sqlStatement: SQLStatement = SQL`
SELECT
p.project_id,
p.name,
pp.system_user_id,
pp.project_role_id,
pp.project_participation_id
FROM
project_participation pp
LEFT JOIN
project p
ON
pp.project_id = p.project_id
WHERE
pp.system_user_id = ${userId};
`;

defaultLog.debug({
label: 'getAllUserProjectsSQL',
message: 'sql',
'sqlStatement.text': sqlStatement.text,
'sqlStatement.values': sqlStatement.values
});

return sqlStatement;
};

/**
* SQL query to add a single project role to a user.
*
Expand Down
13 changes: 13 additions & 0 deletions app/src/constants/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,16 @@ export const ProjectParticipantsI18N = {
updateParticipantRoleErrorText:
"An error has occurred while attempting to update the user's project role, please try again. If the error persists, please contact your system administrator."
};

export const SystemUserI18N = {
deleteProjectLeadErrorTitle: 'Error Deleting Project Lead',
deleteProjectLeadErrorText:
'An error has occurred while attempting to delete the project lead, please assign a different project lead before removing. Please try again, if the error persists please contact your system administrator.',
updateProjectLeadRoleErrorTitle: 'Error Updating Project Lead Role',
updateProjectLeadRoleErrorText:
"An error has occurred while attempting to update the user's project lead role, please assign a different project lead before changing. Please try again, if the error persists please contact your system administrator.",
removeSystemUserTitle: 'Remove System User ',
removeUserErrorTitle: 'Error Removing User From Team',
removeUserErrorText:
'An error has occurred while attempting to remove the user from the team, please try again. If the error persists, please contact your system administrator.'
};
8 changes: 8 additions & 0 deletions app/src/features/admin/AdminUsersRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Redirect, Switch } from 'react-router';
import AppRoute from 'utils/AppRoute';
import PrivateRoute from 'utils/PrivateRoute';
import ManageUsersPage from './users/ManageUsersPage';
import UsersDetailPage from './users/UsersDetailPage';

interface IAdminUsersRouterProps {
classes: any;
Expand All @@ -25,6 +26,13 @@ const AdminUsersRouter: React.FC<IAdminUsersRouterProps> = (props) => {
component={ManageUsersPage}
componentProps={props}
/>
<PrivateRoute
exact
layout={AdminUsersLayout}
path="/admin/users/details"
component={UsersDetailPage}
componentProps={props}
/>
{/* Catch any unknown routes, and re-direct to the not found page */}
<AppRoute title="*" path="/admin/users/*" component={() => <Redirect to="/page-not-found" />} />
</Switch>
Expand Down
16 changes: 13 additions & 3 deletions app/src/features/admin/users/ActiveUsersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import TableHead from '@material-ui/core/TableHead';
import TablePagination from '@material-ui/core/TablePagination';
import TableRow from '@material-ui/core/TableRow';
import Typography from '@material-ui/core/Typography';
import { mdiDotsVertical, mdiMenuDown, mdiTrashCanOutline, mdiPlus } from '@mdi/js';
import { mdiDotsVertical, mdiMenuDown, mdiTrashCanOutline, mdiPlus, mdiInformationOutline } from '@mdi/js';
import Icon from '@mdi/react';
import { IErrorDialogProps } from 'components/dialog/ErrorDialog';
import { CustomMenuButton, CustomMenuIconButton } from 'components/toolbar/ActionToolbars';
Expand All @@ -23,10 +23,10 @@ import { APIError } from 'hooks/api/useAxios';
import { useBiohubApi } from 'hooks/useBioHubApi';
import { IGetAllCodeSetsResponse } from 'interfaces/useCodesApi.interface';
import { IGetUserResponse } from 'interfaces/useUserApi.interface';
import { useHistory } from 'react-router';
import React, { useContext, useState } from 'react';
import { handleChangePage, handleChangeRowsPerPage } from 'utils/tablePaginationUtils';
import EditDialog from 'components/dialog/EditDialog';

import AddSystemUsersForm, {
AddSystemUsersFormInitialValues,
AddSystemUsersFormYupSchema,
Expand Down Expand Up @@ -58,6 +58,7 @@ const ActiveUsersList: React.FC<IActiveUsersListProps> = (props) => {
const classes = useStyles();
const biohubApi = useBiohubApi();
const { activeUsers, codes } = props;
const history = useHistory();

const [rowsPerPage, setRowsPerPage] = useState(20);
const [page, setPage] = useState(0);
Expand Down Expand Up @@ -87,7 +88,7 @@ const ActiveUsersList: React.FC<IActiveUsersListProps> = (props) => {

const handleRemoveUserClick = (row: IGetUserResponse) => {
dialogContext.setYesNoDialog({
dialogTitle: 'Remove user?',
dialogTitle: 'Remove User?',
dialogContent: (
<Typography variant="body1" component="div" color="textSecondary">
Removing user <strong>{row.user_identifier}</strong> will revoke their access to this application and all
Expand Down Expand Up @@ -301,6 +302,15 @@ const ActiveUsersList: React.FC<IActiveUsersListProps> = (props) => {
buttonTitle="Actions"
buttonIcon={<Icon path={mdiDotsVertical} size={1} />}
menuItems={[
{
menuIcon: <Icon path={mdiInformationOutline} size={0.875} />,
menuLabel: 'View Users Details',
menuOnClick: () =>
history.push({
pathname: `/admin/users/details`,
state: row
})
},
{
menuIcon: <Icon path={mdiTrashCanOutline} size={0.875} />,
menuLabel: 'Remove User',
Expand Down
Loading