Skip to content

Commit

Permalink
admin page now works as intended
Browse files Browse the repository at this point in the history
  • Loading branch information
mgtennant committed May 21, 2024
1 parent 8d3d9e9 commit b9ad9c9
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 97 deletions.
2 changes: 1 addition & 1 deletion backend/src/admin/admin.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export class AdminController {
}

@Post('remove-admin')
removeAdmin(@Body() input: { idirUsername: string }): Promise<{ message: string }> {
removeAdmin(@Body() input: { idirUsername: string }): Promise<{ error: string | null }> {
return this.adminService.removeAdmin(input.idirUsername);
}

Expand Down
37 changes: 23 additions & 14 deletions backend/src/admin/admin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ export class AdminService {
return this.documentTemplateService.remove(document_type_id, id);
}

updateTemplate(data: { id: number; documentNo: number; documentName: string; document_type_id: number }): Promise<any> {
updateTemplate(data: {
id: number;
documentNo: number;
documentName: string;
document_type_id: number;
}): Promise<any> {
return this.documentTemplateService.updateTemplate(data);
}

Expand Down Expand Up @@ -248,22 +253,26 @@ export class AdminService {
* @param username
* @returns null
*/
async removeAdmin(username: string) {
async removeAdmin(username: string): Promise<{ error: string | null }> {
const ticdiAdminRole = 'ticdi_admin';
const bearerToken = await this.getToken();
const url = `${process.env.users_api_base_url}/integrations/${process.env.integration_id}/${process.env.css_environment}/users/${username}@idir/roles/${ticdiAdminRole}`;
const res = await axios
.delete(url, {
headers: { Authorization: 'Bearer ' + bearerToken },
})
.then((res) => {
return res;
})
.catch((err) => {
console.log(err.response.data);
return { message: 'Failed to remove admin privileges' };
});
return { message: 'error' };
try {
await axios
.delete(url, {
headers: { Authorization: 'Bearer ' + bearerToken },
})

Check failure

Code scanning / CodeQL

Server-side request forgery Critical

The
URL
of this request depends on a
user-provided value
.
.then((res) => {
return res;
})
.catch((err) => {
throw err;
});
} catch (err) {
console.log(err.response.data);
return { error: 'Failed to remove admin privileges' };
}
return { error: null };
}

async getDocumentTemplates(document_type_id: number): Promise<any> {
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/app/common/manage-admins.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import config from '../../config';
import { IdirUserObject } from '../components/modal/manage-admins/AddAdmin';
import { AdminData } from '../components/table/manage-admins/AdminDataTable';
import { UserObject } from '../types/types';
import * as api from './api';

/**
Expand Down Expand Up @@ -48,14 +49,16 @@ export const findIdirUser = async (
return { foundUserObject: response.userObject || null, error: response.error || null };
};

export const addAdmin = async (idirUsername: string): Promise<void> => {
export const addAdmin = async (idirUsername: string): Promise<{ userObject: UserObject; error: string }> => {
const url = `${config.API_BASE_URL}/admin/add-admin`;
const data = { idirUsername };
const postParameters = api.generateApiParameters(url, data);
await api.post(postParameters);
console.log('addAdmin posting');
const response: { userObject: UserObject; error: string } = await api.post(postParameters);
return response;
};

export const removeAdmin = async (idirUsername: string): Promise<{ message: string }> => {
export const removeAdmin = async (idirUsername: string): Promise<{ error: string | null }> => {
const url = `${config.API_BASE_URL}/admin/remove-admin`;
const data = { idirUsername };
const postParameters = api.generateApiParameters(url, data);
Expand Down
46 changes: 22 additions & 24 deletions frontend/src/app/components/modal/manage-admins/AddAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { Col, Row, Spinner } from 'react-bootstrap';
import { findIdirUser } from '../../../common/manage-admins';
import { addAdmin, findIdirUser } from '../../../common/manage-admins';

type AddAdminProps = {
show: boolean;
onHide: () => void;
refreshTable: () => void;
};

export type IdirUserObject = {
Expand All @@ -17,14 +18,15 @@ export type IdirUserObject = {
idirUsername: string;
};

const AddAdmin: FC<AddAdminProps> = ({ show, onHide }) => {
const AddAdmin: FC<AddAdminProps> = ({ show, onHide, refreshTable }) => {
const [email, setEmail] = useState('');
const [loading, setLoading] = useState(false);
const [userObject, setUserObject] = useState<IdirUserObject | null>(null);
const [error, setError] = useState('');
const [showError, setShowError] = useState(false);

const searchUsers = async () => {
setShowError(false);
setLoading(true);
try {
const { foundUserObject, error } = await findIdirUser(email);
Expand All @@ -43,28 +45,24 @@ const AddAdmin: FC<AddAdminProps> = ({ show, onHide }) => {
}
};

const addAdmin = async () => {
setLoading(true);
const addParams = {
idirUsername: userObject?.idirUsername,
};
try {
const response = await fetch(`/admin/add-admin`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(addParams),
});
const resJson = await response.json();
if (!resJson.error) {
onHide();
} else {
setError(resJson.error);
const addAdminHandler = async () => {
if (userObject) {
setShowError(false);
setLoading(true);
try {
const response = await addAdmin(userObject.idirUsername);
if (!response.error || response.error === '') {
refreshTable();
onHide();
} else {
setError(response.error);
}
} catch (err) {
console.log(err);
setError('An error occurred while adding an administrator.');
} finally {
setLoading(false);
}
} catch (err) {
console.log(err);
setError('An error occurred while adding an administrator.');
} finally {
setLoading(false);
}
};

Expand Down Expand Up @@ -152,7 +150,7 @@ const AddAdmin: FC<AddAdminProps> = ({ show, onHide }) => {
Cancel
</Button>

<Button variant="primary" onClick={addAdmin} disabled={loading || !userObject}>
<Button variant="primary" onClick={addAdminHandler} disabled={loading || !userObject}>
{loading ? (
<Spinner as="span" animation="border" size="sm" role="status" aria-hidden="true" />
) : (
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/app/components/modal/manage-admins/RemoveAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ type RemoveAdminProps = {
admin: AdminData;
show: boolean;
onHide: () => void;
refreshTable: () => void;
};

const RemoveAdmin: FC<RemoveAdminProps> = ({ admin, show, onHide }) => {
const RemoveAdmin: FC<RemoveAdminProps> = ({ admin, show, onHide, refreshTable }) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [showError, setShowError] = useState(false);

const removeHandler = async () => {
setLoading(true);
try {
const { message } = await removeAdmin(admin.idirUsername);
if (message === 'success') {
const response = await removeAdmin(admin.idirUsername);
if (!response.error) {
refreshTable();
onHide();
} else {
setError(message);
setError(response.error);
setShowError(true);
}
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ export type AdminData = {
interface AdminDataTableProps {
searchTerm: string;
removeAdminModalHandler: (admin: AdminData) => void;
refreshTable: number;
}

const AdminDataTable: React.FC<AdminDataTableProps> = ({ searchTerm, removeAdminModalHandler }) => {
const AdminDataTable: React.FC<AdminDataTableProps> = ({ searchTerm, removeAdminModalHandler, refreshTable }) => {
const [adminData, setAdminData] = useState<AdminData[]>([]);
const [filteredAdminData, setFilteredAdminData] = useState<AdminData[]>([]);

Expand All @@ -31,7 +32,7 @@ const AdminDataTable: React.FC<AdminDataTableProps> = ({ searchTerm, removeAdmin
};

fetchData();
}, []);
}, [refreshTable]);

useEffect(() => {
const filterData = () => {
Expand Down
69 changes: 20 additions & 49 deletions frontend/src/app/content/pages/AdminPage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { FC, useState } from 'react';
// import { REPORT_TYPES } from '../../util/constants';
import AddAdmin from '../../components/modal/manage-admins/AddAdmin';
import RemoveAdmin from '../../components/modal/manage-admins/RemoveAdmin';
// import { useNavigate } from 'react-router-dom';
import { exportUsers } from '../../common/manage-admins';
import AdminDataTable, { AdminData } from '../../components/table/manage-admins/AdminDataTable';

const AdminPage: FC = () => {
// const navigate = useNavigate();
const [selectedAdmin, setSelectedAdmin] = useState<AdminData | null>(null);
const [showAddAdminModal, setShowAddAdminModal] = useState(false);
const [showRemoveAdminModal, setShowRemoveAdminModal] = useState(false);
// const [selectedReport, setSelectedReport] = useState('0');
const [searchTerm, setSearchTerm] = useState('');
const [refreshTable, setRefreshTable] = useState(0);

const showAddAdminModalHandler = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
Expand All @@ -29,23 +26,19 @@ const AdminPage: FC = () => {
setShowRemoveAdminModal(false);
};

// const selectedReportHandler = (event: React.ChangeEvent<HTMLSelectElement>) => {
// setSelectedReport(event.target.value);
// };

const exportUserListHandler = async (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
await exportUsers();
};

// const manageReportsHandler = () => {
// navigate(`/manage-templates/${selectedReport}`);
// };

const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearchTerm(e.target.value);
};

const refreshTableHandler = () => {
setRefreshTable((prev) => prev + 1);
};

return (
<>
<h1>Manage Administrators</h1>
Expand All @@ -64,7 +57,11 @@ const AdminPage: FC = () => {

<div className="form-group row">
<div className="col-md-12">
<AdminDataTable searchTerm={searchTerm} removeAdminModalHandler={showRemoveAdminModalHandler} />
<AdminDataTable
searchTerm={searchTerm}
removeAdminModalHandler={showRemoveAdminModalHandler}
refreshTable={refreshTable}
/>
</div>
</div>
<div className="form-group row">
Expand All @@ -85,43 +82,17 @@ const AdminPage: FC = () => {
</button>
</div>
</div>
{/* <hr />
<div className="col-md-3">
<h3>Manage Templates</h3>
</div>
<div className="col-md-3">
<h4>Select a Template:</h4>
</div>
<div className="form-group row">
<div className="col-md-4">
<select
id="reportTypes"
style={{ minWidth: '200px' }}
className="border border-1 rounded pl-2 ml-4"
value={selectedReport}
onChange={selectedReportHandler}
>
{REPORT_TYPES.map((report) => (
<option key={report.reportIndex} value={report.reportIndex}>
{report.reportType}
</option>
))}
</select>
</div>
<div className="col-md-3">
<button
id="manageButton"
className="btn"
onClick={manageReportsHandler}
style={{ backgroundColor: 'purple', color: 'white' }}
>
Manage
</button>
</div>
</div> */}
{showAddAdminModal && <AddAdmin show={showAddAdminModal} onHide={closeAddAdminModalHandler} />}

{showAddAdminModal && (
<AddAdmin show={showAddAdminModal} onHide={closeAddAdminModalHandler} refreshTable={refreshTableHandler} />
)}
{selectedAdmin && showRemoveAdminModal && (
<RemoveAdmin admin={selectedAdmin} show={showRemoveAdminModal} onHide={closeRemoveAdminModalHandler} />
<RemoveAdmin
admin={selectedAdmin}
show={showRemoveAdminModal}
onHide={closeRemoveAdminModalHandler}
refreshTable={refreshTableHandler}
/>
)}
</>
);
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/app/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,11 @@ export type VariableData = {
update_timestamp: string;
provision: Provision;
};

export type UserObject = {
name: string;
username: string;
email: string;
remove: string;
idirUsername: string;
};

0 comments on commit b9ad9c9

Please sign in to comment.