Skip to content

Commit

Permalink
Add ListLogs Panel module
Browse files Browse the repository at this point in the history
  • Loading branch information
hodgef committed Nov 8, 2024
1 parent e4aa243 commit 8bc3c36
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 3 deletions.
73 changes: 73 additions & 0 deletions src/components/Admin/Actions/ListLogs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from "react";
import { LogResults, ListLogsPageProps } from "../interfaces";
import { getAppHelper } from "../Utils";

export const ListLogs: React.FC<ListLogsPageProps> = (props) => {
const { pageName = "", csrfToken = "" } = props;
const { setProps } = getAppHelper(pageName);
const [results, setResults] = React.useState<LogResults[]>([]);

const onSubmit = () => {
const data = {} as { logId: string };

Array.from(document.querySelectorAll("input")).forEach(input => {
const key = input.getAttribute("id") as string;
data[key] = input.value;
});

if (!data.logId) {
setProps({
...props,
dialog: { className: "alert-danger", message: "You must provide a log id" }
});
}

fetch(`/admp/logs?logId=${data.logId}`, {
method: 'get',
headers: { "X-Apiker-Csrf": csrfToken }
})
.then(r => r.json().then(res => ({ status: r.status, body: res })))
.then(data => {
const { status, body = {} } = data;
const { entries = [] } = body;
const isSucessful = status === 200;

const message = isSucessful ? "Action performed successfully" : "Failure returned by the endpoint.";

setProps({
...props,
dialog: { className: isSucessful ? "alert-primary" : "alert-danger", message }
});

setResults(entries);
})
.catch(error => {
setProps({
...props,
dialog: { className: "alert-danger", message: error?.message }
});
})
};

return (
<div className="action-wrapper">
<form className="login-form" onSubmit={onSubmit}>
<input className="form-control form-control-lg mt-2" id="logId" type="text" placeholder="Log ID" />
<button className="btn btn-primary mt-2 action-btn" type="submit">Submit</button>
</form>
{(results && results.length) ? results.map((result) => (
<div className="results-container">
<div className="results-item">
<ul>
{Object.keys(result).map((key) => (
<li><span className="title">{key}</span> <span className="text" title={key === "time" ? new Date(result[key] as string).toLocaleString() : result[key]}>
{key === "time" ? new Date(result[key] as string).toLocaleString() : result[key]}
</span></li>
))}
</ul>
</div>
</div>
)) : null}
</div>
);
}
3 changes: 2 additions & 1 deletion src/components/Admin/Admin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Handler, RequestParams } from "../Request";
import { resRaw } from "../Response";
import { apikerPagesStatic } from "../Static";
import { bansEndpoint, loginEndpoint, searchBansEndpoint, sendEmailEndpoint, updateUserEndpoint } from "./Api";
import { searchLogsEndpoint, bansEndpoint, loginEndpoint, searchBansEndpoint, sendEmailEndpoint, updateUserEndpoint } from "./Api";
import { adminPanelPage } from "./Panel";
import { adminCsrfCheckMiddleware, adminMiddleware } from "./middleware";

Expand All @@ -17,6 +17,7 @@ export const getAdminRoutes = () => ({
"/admp/login": (params: RequestParams) => adminCsrfCheckMiddleware(params, loginEndpoint),

// Check for admin logged in and CSRF
"/admp/logs": (params: RequestParams) => adminMiddleware(params, searchLogsEndpoint),
"/admp/bans": (params: RequestParams) => adminMiddleware(params, bansEndpoint),
"/admp/bans/:userId": (params: RequestParams) => adminMiddleware(params, searchBansEndpoint),
"/admp/email": (params: RequestParams) => adminMiddleware(params, sendEmailEndpoint),
Expand Down
1 change: 1 addition & 0 deletions src/components/Admin/Api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./logsEndpoint";
export * from "./bansEndpoint";
export * from "./loginEndpoint";
export * from "./sendEmailEndpoint";
Expand Down
17 changes: 17 additions & 0 deletions src/components/Admin/Api/logsEndpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getLogEntries } from '../../Logging';
import { Handler } from '../../Request';
import { res, res_400 } from '../../Response';

export const searchLogsEndpoint: Handler = async (params) => {
const { request } = params;
const url = new URL(request.url);
const search = new URLSearchParams(url.search);
const logId = search.get("logId") || "";

if(!logId){
return res_400();
}

const entries = await getLogEntries(logId, 100);
return res({ entries });
}
8 changes: 7 additions & 1 deletion src/components/Admin/Api/updateUserEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,18 @@ export const updateUserEndpoint: Handler = async ({ state, body, request }) => {
}

/** Do not allow user update of admin, unless same user */
if(request.method === "PUT" || request.method === "DELETE"){
if(request.method === "PUT"){
if(user?.email !== userEmail && user?.role === "admin"){
return res_401();
}
}

if(request.method === "DELETE"){
if(user?.role === "admin"){
return res_401();
}
}

let updatedFields: { email?: string } = {};
if(request.method === "PUT"){
const { email } = body?.updatedUser ? JSON.parse(body.updatedUser) : {} as User;
Expand Down
4 changes: 4 additions & 0 deletions src/components/Admin/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { SearchBans } from "./Actions/SearchBans";
import { SendEmail } from "./Actions/SendEmail";
import { UpdateUser } from "./Actions/UpdateUser";
import { DeleteUser } from "./Actions/DeleteUser";
import { ListLogs } from "./Actions/ListLogs";

export const adminPanelPage: Handler = async ({ state }) => {
const pageName = "AdminPanelPage";
Expand All @@ -40,6 +41,7 @@ const actionsComponent = {
banUser: BanUser,
unbanUser: UnbanUser,
searchBans: SearchBans,
listLogs: ListLogs,
sendEmail: SendEmail,
updateUser: UpdateUser,
deleteUser: DeleteUser
Expand All @@ -52,6 +54,8 @@ export const AdminPanelPage: React.FC<AdminPanelPageProps> = (props) => {

if(isAdminLoggedIn){
actions = authActions;
} else {
actions = defaultActions;
}

const onDropdownItemClick = (action: Action) => {
Expand Down
4 changes: 4 additions & 0 deletions src/components/Admin/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const authActions: Actions = [
id: "searchBans",
displayName: "Search Bans"
},
{
id: "listLogs",
displayName: "List Logs"
},
{
id: "sendEmail",
displayName: "Send Email"
Expand Down
1 change: 1 addition & 0 deletions src/components/Admin/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface LoginPageProps extends AdminPanelPageProps {}
export interface BanUserPageProps extends AdminPanelPageProps {}
export interface UnbanUserPageProps extends AdminPanelPageProps {}
export interface SearchBansPageProps extends AdminPanelPageProps {}
export interface ListLogsPageProps extends AdminPanelPageProps {}
export interface SendEmailPageProps extends AdminPanelPageProps {}
export interface UpdateUserPageProps extends AdminPanelPageProps {}
export interface DeleteUserPageProps extends AdminPanelPageProps {}
2 changes: 1 addition & 1 deletion src/components/Static/staticPages.ts

Large diffs are not rendered by default.

0 comments on commit 8bc3c36

Please sign in to comment.