Skip to content

Commit 8bc3c36

Browse files
committed
Add ListLogs Panel module
1 parent e4aa243 commit 8bc3c36

File tree

9 files changed

+110
-3
lines changed

9 files changed

+110
-3
lines changed
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React from "react";
2+
import { LogResults, ListLogsPageProps } from "../interfaces";
3+
import { getAppHelper } from "../Utils";
4+
5+
export const ListLogs: React.FC<ListLogsPageProps> = (props) => {
6+
const { pageName = "", csrfToken = "" } = props;
7+
const { setProps } = getAppHelper(pageName);
8+
const [results, setResults] = React.useState<LogResults[]>([]);
9+
10+
const onSubmit = () => {
11+
const data = {} as { logId: string };
12+
13+
Array.from(document.querySelectorAll("input")).forEach(input => {
14+
const key = input.getAttribute("id") as string;
15+
data[key] = input.value;
16+
});
17+
18+
if (!data.logId) {
19+
setProps({
20+
...props,
21+
dialog: { className: "alert-danger", message: "You must provide a log id" }
22+
});
23+
}
24+
25+
fetch(`/admp/logs?logId=${data.logId}`, {
26+
method: 'get',
27+
headers: { "X-Apiker-Csrf": csrfToken }
28+
})
29+
.then(r => r.json().then(res => ({ status: r.status, body: res })))
30+
.then(data => {
31+
const { status, body = {} } = data;
32+
const { entries = [] } = body;
33+
const isSucessful = status === 200;
34+
35+
const message = isSucessful ? "Action performed successfully" : "Failure returned by the endpoint.";
36+
37+
setProps({
38+
...props,
39+
dialog: { className: isSucessful ? "alert-primary" : "alert-danger", message }
40+
});
41+
42+
setResults(entries);
43+
})
44+
.catch(error => {
45+
setProps({
46+
...props,
47+
dialog: { className: "alert-danger", message: error?.message }
48+
});
49+
})
50+
};
51+
52+
return (
53+
<div className="action-wrapper">
54+
<form className="login-form" onSubmit={onSubmit}>
55+
<input className="form-control form-control-lg mt-2" id="logId" type="text" placeholder="Log ID" />
56+
<button className="btn btn-primary mt-2 action-btn" type="submit">Submit</button>
57+
</form>
58+
{(results && results.length) ? results.map((result) => (
59+
<div className="results-container">
60+
<div className="results-item">
61+
<ul>
62+
{Object.keys(result).map((key) => (
63+
<li><span className="title">{key}</span> <span className="text" title={key === "time" ? new Date(result[key] as string).toLocaleString() : result[key]}>
64+
{key === "time" ? new Date(result[key] as string).toLocaleString() : result[key]}
65+
</span></li>
66+
))}
67+
</ul>
68+
</div>
69+
</div>
70+
)) : null}
71+
</div>
72+
);
73+
}

src/components/Admin/Admin.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Handler, RequestParams } from "../Request";
22
import { resRaw } from "../Response";
33
import { apikerPagesStatic } from "../Static";
4-
import { bansEndpoint, loginEndpoint, searchBansEndpoint, sendEmailEndpoint, updateUserEndpoint } from "./Api";
4+
import { searchLogsEndpoint, bansEndpoint, loginEndpoint, searchBansEndpoint, sendEmailEndpoint, updateUserEndpoint } from "./Api";
55
import { adminPanelPage } from "./Panel";
66
import { adminCsrfCheckMiddleware, adminMiddleware } from "./middleware";
77

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

1919
// Check for admin logged in and CSRF
20+
"/admp/logs": (params: RequestParams) => adminMiddleware(params, searchLogsEndpoint),
2021
"/admp/bans": (params: RequestParams) => adminMiddleware(params, bansEndpoint),
2122
"/admp/bans/:userId": (params: RequestParams) => adminMiddleware(params, searchBansEndpoint),
2223
"/admp/email": (params: RequestParams) => adminMiddleware(params, sendEmailEndpoint),

src/components/Admin/Api/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from "./logsEndpoint";
12
export * from "./bansEndpoint";
23
export * from "./loginEndpoint";
34
export * from "./sendEmailEndpoint";
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { getLogEntries } from '../../Logging';
2+
import { Handler } from '../../Request';
3+
import { res, res_400 } from '../../Response';
4+
5+
export const searchLogsEndpoint: Handler = async (params) => {
6+
const { request } = params;
7+
const url = new URL(request.url);
8+
const search = new URLSearchParams(url.search);
9+
const logId = search.get("logId") || "";
10+
11+
if(!logId){
12+
return res_400();
13+
}
14+
15+
const entries = await getLogEntries(logId, 100);
16+
return res({ entries });
17+
}

src/components/Admin/Api/updateUserEndpoint.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,18 @@ export const updateUserEndpoint: Handler = async ({ state, body, request }) => {
4444
}
4545

4646
/** Do not allow user update of admin, unless same user */
47-
if(request.method === "PUT" || request.method === "DELETE"){
47+
if(request.method === "PUT"){
4848
if(user?.email !== userEmail && user?.role === "admin"){
4949
return res_401();
5050
}
5151
}
5252

53+
if(request.method === "DELETE"){
54+
if(user?.role === "admin"){
55+
return res_401();
56+
}
57+
}
58+
5359
let updatedFields: { email?: string } = {};
5460
if(request.method === "PUT"){
5561
const { email } = body?.updatedUser ? JSON.parse(body.updatedUser) : {} as User;

src/components/Admin/Panel.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { SearchBans } from "./Actions/SearchBans";
1919
import { SendEmail } from "./Actions/SendEmail";
2020
import { UpdateUser } from "./Actions/UpdateUser";
2121
import { DeleteUser } from "./Actions/DeleteUser";
22+
import { ListLogs } from "./Actions/ListLogs";
2223

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

5355
if(isAdminLoggedIn){
5456
actions = authActions;
57+
} else {
58+
actions = defaultActions;
5559
}
5660

5761
const onDropdownItemClick = (action: Action) => {

src/components/Admin/constants.ts

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export const authActions: Actions = [
2222
id: "searchBans",
2323
displayName: "Search Bans"
2424
},
25+
{
26+
id: "listLogs",
27+
displayName: "List Logs"
28+
},
2529
{
2630
id: "sendEmail",
2731
displayName: "Send Email"

src/components/Admin/interfaces.ts

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface LoginPageProps extends AdminPanelPageProps {}
5050
export interface BanUserPageProps extends AdminPanelPageProps {}
5151
export interface UnbanUserPageProps extends AdminPanelPageProps {}
5252
export interface SearchBansPageProps extends AdminPanelPageProps {}
53+
export interface ListLogsPageProps extends AdminPanelPageProps {}
5354
export interface SendEmailPageProps extends AdminPanelPageProps {}
5455
export interface UpdateUserPageProps extends AdminPanelPageProps {}
5556
export interface DeleteUserPageProps extends AdminPanelPageProps {}

src/components/Static/staticPages.ts

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)