From fe430173140a20b0d133081694cff5779b2beee8 Mon Sep 17 00:00:00 2001 From: Francisco Hodge Date: Thu, 21 Dec 2023 23:35:13 -0500 Subject: [PATCH] Perf: Multi-object support --- .github/workflows/main.yml | 2 +- .github/workflows/publish.yml | 8 +- .github/workflows/pull_request.yml | 2 +- .github/workflows/pull_request_dependabot.yml | 2 +- package-lock.json | 44 +- package.json | 2 +- src/components/Admin/Dashboard.tsx | 7 +- src/components/Admin/Login.tsx | 12 +- src/components/Admin/Setup.tsx | 13 +- src/components/Apiker/Apiker.ts | 2 + src/components/Apiker/index.ts | 3 +- src/components/Apiker/utils.ts | 19 + src/components/Auth/constants.ts | 7 +- src/components/Auth/registerUser.ts | 19 +- src/components/Auth/utils.ts | 12 + src/components/Logging/Logging.ts | 5 +- src/components/Request/Request.ts | 3 +- src/components/Static/staticPages.ts | 492 +++++++++--------- tsconfig.json | 2 +- 19 files changed, 374 insertions(+), 282 deletions(-) create mode 100644 src/components/Apiker/utils.ts diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 691cf95..76f7136 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [12.x] + node-version: [20.x] os: [ubuntu-latest] steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ef2b8e2..1a68ab1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,12 +11,16 @@ on: jobs: publish: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + node-version: [20.x] + os: [ubuntu-latest] steps: - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: - node-version: 12 + node-version: ${{ matrix.node_version }} - run: npm install - run: npm run test diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 31ad8c9..0ab0216 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -8,7 +8,7 @@ jobs: if: ${{ github.actor != 'dependabot[bot]' }} strategy: matrix: - node-version: [12.x] + node-version: [20.x] os: [ubuntu-latest] steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/pull_request_dependabot.yml b/.github/workflows/pull_request_dependabot.yml index 91dc078..c933117 100644 --- a/.github/workflows/pull_request_dependabot.yml +++ b/.github/workflows/pull_request_dependabot.yml @@ -8,7 +8,7 @@ jobs: if: ${{ github.actor == 'dependabot[bot]' }} strategy: matrix: - node-version: [12.x] + node-version: [20.x] os: [ubuntu-latest] steps: - uses: actions/checkout@v2 diff --git a/package-lock.json b/package-lock.json index 511bbf2..bb81230 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "apiker", - "version": "1.6.6", + "version": "1.6.7", "license": "MIT", "bin": { "apiker": "bin/index.js" @@ -35,7 +35,7 @@ "react-dom": "^17.0.2", "react-is": "^18.0.0", "rimraf": "^3.0.2", - "rollup": "^2.70.1", + "rollup": "^2.74.0", "rollup-plugin-copy": "^3.4.0", "rollup-plugin-dts": "^4.2.1", "rollup-plugin-node-polyfills": "^0.2.1", @@ -2481,6 +2481,13 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/bluebird": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.38.tgz", + "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", + "dev": true, + "peer": true + }, "node_modules/@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -6565,9 +6572,9 @@ } }, "node_modules/rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -7336,6 +7343,13 @@ } } }, + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true, + "peer": true + }, "node_modules/ts-type": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-2.1.4.tgz", @@ -9577,6 +9591,13 @@ "@babel/types": "^7.3.0" } }, + "@types/bluebird": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.38.tgz", + "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", + "dev": true, + "peer": true + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -12674,9 +12695,9 @@ } }, "rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -13251,6 +13272,13 @@ "yargs-parser": "20.x" } }, + "ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", + "dev": true, + "peer": true + }, "ts-type": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-2.1.4.tgz", diff --git a/package.json b/package.json index 93b443f..fffb985 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "react-dom": "^17.0.2", "react-is": "^18.0.0", "rimraf": "^3.0.2", - "rollup": "^2.70.1", + "rollup": "^2.74.0", "rollup-plugin-copy": "^3.4.0", "rollup-plugin-dts": "^4.2.1", "rollup-plugin-node-polyfills": "^0.2.1", diff --git a/src/components/Admin/Dashboard.tsx b/src/components/Admin/Dashboard.tsx index ce7f13d..3dbb98a 100644 --- a/src/components/Admin/Dashboard.tsx +++ b/src/components/Admin/Dashboard.tsx @@ -1,7 +1,7 @@ import { Handler } from '../Request'; import React from "react"; import { getFlagEmoji, wrapReactPage } from '../Page'; -import { getCurrentUser, getSignedIp } from '../Auth'; +import { getCurrentUser, getSignedIp, isUserAdmin } from '../Auth'; import { adminPanelLogin } from './Login'; import { PanelHeader } from './Header'; import { getAllLogEntries, getLogEntries, LogObject } from '../Logging'; @@ -9,6 +9,7 @@ import { getBannedSignedIPs } from '../Bans'; import { FIREWALL_RATELIMIT_PREFIX } from '../Firewall'; import { OBN } from '../ObjectBase'; import { apiker } from '../Apiker'; +import { res_401 } from '../Response'; export const adminPanelDashboard: Handler = async (params) => { const user = await getCurrentUser(); @@ -17,6 +18,10 @@ export const adminPanelDashboard: Handler = async (params) => { return adminPanelLogin(params); } + if(!isUserAdmin(user.id)){ + return res_401(); + } + const latestBans = (await getBannedSignedIPs()).sort((a, b) => b.time - a.time); const latestVisitors = (await getLogEntries(FIREWALL_RATELIMIT_PREFIX, 5, OBN.RATELIMIT)).sort((a, b) => b.time - a.time); const allVisitorsCount = (await getAllLogEntries(OBN.RATELIMIT)).length; diff --git a/src/components/Admin/Login.tsx b/src/components/Admin/Login.tsx index 12ffffb..1e8819d 100644 --- a/src/components/Admin/Login.tsx +++ b/src/components/Admin/Login.tsx @@ -1,22 +1,20 @@ import { Handler } from '../Request'; import React from "react"; import { wrapReactPage } from '../Page'; -import { User } from '../Auth'; import { OBN } from '../ObjectBase'; export const adminPanelLogin: Handler = async ({ state }) => { - const latestRequests = await state(OBN.USERS).list({ limit: 1 }); - const firstUser = Object.values(latestRequests)[0] as User; - const hasUsers = !!firstUser?.id; - const props = { hasUsers }; + const adminIds = await state(OBN.COMMON).get("adminIds"); + const hasAdmins = !!adminIds?.length; + const props = { hasAdmins }; return wrapReactPage('AdminPanelLogin', AdminPanelLogin, props); } -export const AdminPanelLogin: React.FC = ({ hasUsers }) => { +export const AdminPanelLogin: React.FC = ({ hasAdmins }) => { return (
- {hasUsers ? ( + {hasAdmins ? (

Login

diff --git a/src/components/Admin/Setup.tsx b/src/components/Admin/Setup.tsx index 5abd8e6..6584bda 100644 --- a/src/components/Admin/Setup.tsx +++ b/src/components/Admin/Setup.tsx @@ -1,7 +1,7 @@ import { Handler } from '../Request'; import React from "react"; import { getFlagEmoji, wrapReactPage } from '../Page'; -import { checkUser, getCurrentUser, getSignedIp, getTokens, registerUserAction, User } from '../Auth'; +import { checkUser, getCurrentUser, getSignedIp, getTokens, isUserAdmin, registerUserAction, User } from '../Auth'; import { OBN } from '../ObjectBase'; import cookie from "cookie" import { adminPanelLogin } from './Login'; @@ -19,17 +19,16 @@ export const adminPanelSetup: Handler = async (params) => { * If there's an user, it's a login, otherwise it's a registration */ if(email && password){ - const latestRequests = await state(OBN.USERS).list({ limit: 1 }); - const firstUser = Object.values(latestRequests)[0] as User; - const hasUsers = !!firstUser?.id; + const adminIds = await state(OBN.COMMON).get("adminIds"); + const hasAdmins = !!adminIds?.length; - if(hasUsers) { + if(hasAdmins) { user = await checkUser(email, password); } else { user = await registerUserAction(email, password, { role: "admin" }); } - if(user){ + if(user && await isUserAdmin(user.id)){ const { token } = getTokens(user?.id, 60); apiker.responseHeaders.set('Set-Cookie', cookie.serialize('apikerToken', `Bearer ${token}`, { sameSite: true, @@ -51,7 +50,7 @@ export const adminPanelSetup: Handler = async (params) => { return adminPanelLogin(params); } - if(user?.role !== "admin"){ + if(!await isUserAdmin(user.id)){ return res_401(); } diff --git a/src/components/Apiker/Apiker.ts b/src/components/Apiker/Apiker.ts index 5e0c355..83c550a 100644 --- a/src/components/Apiker/Apiker.ts +++ b/src/components/Apiker/Apiker.ts @@ -4,6 +4,7 @@ import { OBMT } from "../ObjectBase"; import ObjectBase from "../ObjectBase/ObjectBase"; import { handleEntryRequest, RequestParams } from "../Request"; import type { Controllers, EmailOptions, Firewall, ObjectStateMapping, Options, Routes, Timings } from "./interfaces"; +import { ResponseParams } from "./utils"; class Apiker { name = "Apiker"; @@ -16,6 +17,7 @@ class Apiker { authRoutes!: boolean; env: any; requestParams!: RequestParams; + responseParams = new ResponseParams(); responseHeaders!: Headers; firewall!: Firewall | boolean; adminPanel!: boolean; diff --git a/src/components/Apiker/index.ts b/src/components/Apiker/index.ts index 080581b..1c5456f 100644 --- a/src/components/Apiker/index.ts +++ b/src/components/Apiker/index.ts @@ -1,2 +1,3 @@ export * from "./Apiker"; -export * from "./interfaces"; \ No newline at end of file +export * from "./interfaces"; +export * from "./utils"; \ No newline at end of file diff --git a/src/components/Apiker/utils.ts b/src/components/Apiker/utils.ts new file mode 100644 index 0000000..71db38b --- /dev/null +++ b/src/components/Apiker/utils.ts @@ -0,0 +1,19 @@ +export class ResponseParams { + errors: string[] = []; + + /** + * Sets an error response + */ + setError = (errorMessage: string) => { + this.errors.push(errorMessage); + } + + /** + * Gets the last error response + */ + getLastError = (): string | null => { + return this.errors.length ? + [...this.errors].pop() as string + : null; + } +} \ No newline at end of file diff --git a/src/components/Auth/constants.ts b/src/components/Auth/constants.ts index 47e5863..fd95370 100644 --- a/src/components/Auth/constants.ts +++ b/src/components/Auth/constants.ts @@ -1,4 +1,9 @@ export const AUTH_TOKEN_DURATION_MINS_DEFAULT = 30; export const REGISTER_REQUEST_LIMIT_AMOUNT_PER_HOUR = 3; export const AUTH_PREFIX = "auth"; -export const AUTH_REGISTER_PREFIX = "auth-register"; \ No newline at end of file +export const AUTH_REGISTER_PREFIX = "auth-register"; + +export const AUTH_ERRORS = { + USER_EXISTS: "User already exists", + ID_GEN_ERROR: "Error generating an user Id" +}; \ No newline at end of file diff --git a/src/components/Auth/registerUser.ts b/src/components/Auth/registerUser.ts index 603e46b..91563f8 100644 --- a/src/components/Auth/registerUser.ts +++ b/src/components/Auth/registerUser.ts @@ -3,6 +3,7 @@ import { OBN } from "../ObjectBase"; import { Handler } from "../Request"; import { res, res_400 } from "../Response"; import { isEmail, isRequiredLength } from "../Validation"; +import { AUTH_ERRORS } from "./constants"; import { User } from "./interfaces"; import { getTokens, hash_bcrypt, randomHash_SHA1 } from "./utils"; @@ -25,7 +26,7 @@ export const registerUser: Handler = async ({ body }) => { }; -export const registerUserAction = async (email: string, password: string, extraParams = {}) => { +export const registerUserAction = async (email: string, password: string, extraParams = {} as any): Promise => { const { state } = apiker.requestParams; if(!isEmail(email) || !isRequiredLength(password)) { return; @@ -37,10 +38,17 @@ export const registerUserAction = async (email: string, password: string, extraP const currentUserId = await state(OBN.EMAILTOUUID, email).get(email); if(currentUserId) { + apiker.responseParams.setError(AUTH_ERRORS.USER_EXISTS); return; } const id = randomHash_SHA1(); + + if(!id){ + apiker.responseParams.setError(AUTH_ERRORS.ID_GEN_ERROR); + return; + } + const signedPassword = hash_bcrypt(password); const user: User = { id, @@ -59,5 +67,14 @@ export const registerUserAction = async (email: string, password: string, extraP * Create EmailToUUID entry */ await state(OBN.EMAILTOUUID, email).put({ [email]: id }); + + /** + * If it's an admin, create an entry in admin table + */ + if(extraParams.role === "admin"){ + const adminIds = await state(OBN.COMMON).get("adminIds") || []; + adminIds.push(id); + await state(OBN.COMMON).put({ adminIds }); + } return user; } \ No newline at end of file diff --git a/src/components/Auth/utils.ts b/src/components/Auth/utils.ts index 83f31e0..adaca03 100644 --- a/src/components/Auth/utils.ts +++ b/src/components/Auth/utils.ts @@ -157,6 +157,18 @@ export const getCurrentUser = async (): Promise => { } } +export const isUserAdmin = async (userId = ""): Promise => { + if(!userId) return false; + const { state } = apiker.requestParams; + const adminIds = await state(OBN.COMMON).get("adminIds"); + return adminIds.includes(userId); +} + +export const isCurrentUserAdmin = async (): Promise => { + const user = await getCurrentUser(); + return await isUserAdmin(user?.id); +} + export const getTokens = (userId: string, expirationInMinutes = AUTH_TOKEN_DURATION_MINS_DEFAULT) => { const clientId = getClientId(); const token = createJWT({ sub: userId, clientId }, expirationInMinutes); diff --git a/src/components/Logging/Logging.ts b/src/components/Logging/Logging.ts index a457af7..47277d6 100644 --- a/src/components/Logging/Logging.ts +++ b/src/components/Logging/Logging.ts @@ -12,11 +12,12 @@ export const addUniqueLogEntry = async (prefix: string, additionalParams = {}, o await addLogEntry(prefix, additionalParams, objectName, signedIp, clientId); }; -export const addLogEntry = async (prefix: string, additionalParams = {}, objectName = OBN.LOGS, signedIp: string | undefined = undefined, clientId: string | undefined = undefined) => { +export const addLogEntry = async (prefix: string, additionalParams = {} as any, objectName = OBN.LOGS, signedIp: string | undefined = undefined, clientId: string | undefined = undefined) => { if(apiker.objects.includes(objectName)){ const { state } = apiker.requestParams; + const { objectId = null } = additionalParams; const propertyName = getUserLogPropertyName(prefix, signedIp) + Date.now(); - state(objectName).put({ [propertyName]: getLogParams(propertyName, signedIp, clientId, additionalParams) }); + state(objectName, objectId).put({ [propertyName]: getLogParams(propertyName, signedIp, clientId, additionalParams) }); } }; diff --git a/src/components/Request/Request.ts b/src/components/Request/Request.ts index e01c167..33854ec 100644 --- a/src/components/Request/Request.ts +++ b/src/components/Request/Request.ts @@ -1,4 +1,4 @@ -import { apiker } from "../Apiker"; +import { apiker, ResponseParams } from "../Apiker"; import { match } from "path-to-regexp"; import { RESPONSE_HEADERS_DEFAULT, res_404 } from "../Response"; import { getStateMethods } from "../State"; @@ -17,6 +17,7 @@ export const handleEntryRequest = async (request: Request, env: any) => { try { apiker.setProps({ env }); apiker.responseHeaders = new Headers(RESPONSE_HEADERS_DEFAULT); + apiker.responseParams = new ResponseParams(); const url = new URL(request.url); const { pathname } = url; diff --git a/src/components/Static/staticPages.ts b/src/components/Static/staticPages.ts index 9dd829e..7675ad6 100644 --- a/src/components/Static/staticPages.ts +++ b/src/components/Static/staticPages.ts @@ -33,270 +33,270 @@ export const apikerPagesStatic = `var pages = (function (React, ReactDOMServer, return __assign.apply(this, arguments); }; - cryptojs__default["default"](); + cryptojs__default["default"](); bcrypt__default["default"](); - var getFlagEmoji = function (countryCode) { - var codePoints = countryCode - .toUpperCase() - .split('') - .map(function (char) { return 127397 + char.charCodeAt(); }); - return String.fromCodePoint.apply(String, codePoints); + var getFlagEmoji = function (countryCode) { + var codePoints = countryCode + .toUpperCase() + .split('') + .map(function (char) { return 127397 + char.charCodeAt(); }); + return String.fromCodePoint.apply(String, codePoints); }; - var PanelHeader = function (_a) { - var _b = _a.currentSection, currentSection = _b === void 0 ? "home" : _b, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; - var sections = [ - { - name: "home", - title: "Home", - link: "/admp/dashboard" - }, - { - name: "visitors", - title: "Visitors", - link: "/admp/visitors" - }, - { - name: "bans", - title: "Bans", - link: "/admp/bans" - } - ]; - var renderSection = function (_a) { - var name = _a.name, title = _a.title, _b = _a.children, children = _b === void 0 ? [] : _b, _c = _a.link, link = _c === void 0 ? "#" : _c; - return (React__default["default"].createElement("li", { className: "nav-item ".concat(children.length ? "dropdown" : "") }, - React__default["default"].createElement("a", __assign({ className: "nav-link ".concat(currentSection === name ? "active" : "", " ").concat(children.length ? "dropdown-toggle" : ""), href: link }, (children.length ? { "data-bs-toggle": "dropdown" } : {})), title), - children.length ? React__default["default"].createElement("ul", { className: "dropdown-menu" }, children.map(renderSection)) : null)); - }; - return (React__default["default"].createElement("nav", { className: "navbar mb-4 navbar-expand-lg navbar-light bg-light" }, - React__default["default"].createElement("div", { className: "container-fluid" }, - React__default["default"].createElement("a", { className: "navbar-brand", href: "/admp" }, "Apiker"), - React__default["default"].createElement("button", { className: "navbar-toggler", type: "button", "data-bs-toggle": "collapse", "data-bs-target": "#navbarNavDropdown", "aria-controls": "navbarNavDropdown", "aria-expanded": "false", "aria-label": "Toggle navigation" }, - React__default["default"].createElement("span", { className: "navbar-toggler-icon" })), - React__default["default"].createElement("div", { className: "collapse navbar-collapse", id: "navbarNavDropdown" }, - React__default["default"].createElement("ul", { className: "navbar-nav" }, sections.map(renderSection))), - rateLimitMax && React__default["default"].createElement("span", { className: "text-muted", title: "Firewall RateLimit remaining/max" }, - rateLimitRemaining, - "/", - rateLimitMax)))); + var PanelHeader = function (_a) { + var _b = _a.currentSection, currentSection = _b === void 0 ? "home" : _b, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; + var sections = [ + { + name: "home", + title: "Home", + link: "/admp/dashboard" + }, + { + name: "visitors", + title: "Visitors", + link: "/admp/visitors" + }, + { + name: "bans", + title: "Bans", + link: "/admp/bans" + } + ]; + var renderSection = function (_a) { + var name = _a.name, title = _a.title, _b = _a.children, children = _b === void 0 ? [] : _b, _c = _a.link, link = _c === void 0 ? "#" : _c; + return (React__default["default"].createElement("li", { className: "nav-item ".concat(children.length ? "dropdown" : "") }, + React__default["default"].createElement("a", __assign({ className: "nav-link ".concat(currentSection === name ? "active" : "", " ").concat(children.length ? "dropdown-toggle" : ""), href: link }, (children.length ? { "data-bs-toggle": "dropdown" } : {})), title), + children.length ? React__default["default"].createElement("ul", { className: "dropdown-menu" }, children.map(renderSection)) : null)); + }; + return (React__default["default"].createElement("nav", { className: "navbar mb-4 navbar-expand-lg navbar-light bg-light" }, + React__default["default"].createElement("div", { className: "container-fluid" }, + React__default["default"].createElement("a", { className: "navbar-brand", href: "/admp" }, "Apiker"), + React__default["default"].createElement("button", { className: "navbar-toggler", type: "button", "data-bs-toggle": "collapse", "data-bs-target": "#navbarNavDropdown", "aria-controls": "navbarNavDropdown", "aria-expanded": "false", "aria-label": "Toggle navigation" }, + React__default["default"].createElement("span", { className: "navbar-toggler-icon" })), + React__default["default"].createElement("div", { className: "collapse navbar-collapse", id: "navbarNavDropdown" }, + React__default["default"].createElement("ul", { className: "navbar-nav" }, sections.map(renderSection))), + rateLimitMax && React__default["default"].createElement("span", { className: "text-muted", title: "Firewall RateLimit remaining/max" }, + rateLimitRemaining, + "/", + rateLimitMax)))); }; - var AdminPanelBanId = function (_a) { - var currentSection = _a.currentSection, operatingId = _a.operatingId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; - setTimeout(function () { - window.location.href = '/admp/bans'; - }, 2000); - return (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), - React__default["default"].createElement("div", { className: "container" }, - React__default["default"].createElement("div", { className: "row" }, - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("p", { className: "lead d-flex justify-content-center" }, - "Operation completed on id ", - operatingId)))))); + var AdminPanelBanId = function (_a) { + var currentSection = _a.currentSection, operatingId = _a.operatingId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; + setTimeout(function () { + window.location.href = '/admp/bans'; + }, 2000); + return (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), + React__default["default"].createElement("div", { className: "container" }, + React__default["default"].createElement("div", { className: "row" }, + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("p", { className: "lead d-flex justify-content-center" }, + "Operation completed on id ", + operatingId)))))); }; - var AdminPanelBans = function (_a) { - var currentSection = _a.currentSection, latestBans = _a.latestBans, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; - return (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), - React__default["default"].createElement("div", { className: "container" }, - React__default["default"].createElement("div", { className: "row row-cols-1 row-cols-md-3 g-4 mb-4" }, - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "card text-dark bg-light mb-3", style: { maxWidth: "18rem" } }, - React__default["default"].createElement("div", { className: "card-header" }, "Ban user"), - React__default["default"].createElement("div", { className: "card-body" }, - React__default["default"].createElement("form", { className: "row d-grid gap-2", method: "post", action: "/admp/banid" }, - React__default["default"].createElement("div", { class: "col-auto" }, - React__default["default"].createElement("input", { type: "text", readonly: true, class: "form-control", name: "id", placeholder: "id" })), - React__default["default"].createElement("div", { class: "col-auto d-grid gap-2" }, - React__default["default"].createElement("button", { type: "submit", class: "btn btn-primary mb-3" }, "Ban")))))), - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "card text-dark bg-light mb-3", style: { maxWidth: "18rem" } }, - React__default["default"].createElement("div", { className: "card-header" }, "Unban user"), - React__default["default"].createElement("div", { className: "card-body" }, - React__default["default"].createElement("form", { className: "row d-grid gap-2", method: "post", action: "/admp/banid" }, - React__default["default"].createElement("div", { class: "col-auto" }, - React__default["default"].createElement("input", { type: "text", readonly: true, class: "form-control", name: "unbanid", placeholder: "id" })), - React__default["default"].createElement("div", { class: "col-auto d-grid gap-2" }, - React__default["default"].createElement("button", { type: "submit", class: "btn btn-primary mb-3" }, "Unban"))))))), - React__default["default"].createElement("div", { className: "row" }, - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Bans"), - React__default["default"].createElement("table", { className: "table" }, - React__default["default"].createElement("thead", null, - React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "col" }, "Time"), - React__default["default"].createElement("th", { scope: "col" }, "ClientId"), - React__default["default"].createElement("th", { scope: "col" }, "Country"), - React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), - React__default["default"].createElement("tbody", null, latestBans.map(function (_a) { - var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; - return (React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), - React__default["default"].createElement("td", null, - React__default["default"].createElement("div", { className: "d-flex" }, - React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), - " ", - currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), - React__default["default"].createElement("td", null, - React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), - React__default["default"].createElement("td", null, pathname))); - })))))))); + var AdminPanelBans = function (_a) { + var currentSection = _a.currentSection, latestBans = _a.latestBans, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; + return (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), + React__default["default"].createElement("div", { className: "container" }, + React__default["default"].createElement("div", { className: "row row-cols-1 row-cols-md-3 g-4 mb-4" }, + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "card text-dark bg-light mb-3", style: { maxWidth: "18rem" } }, + React__default["default"].createElement("div", { className: "card-header" }, "Ban user"), + React__default["default"].createElement("div", { className: "card-body" }, + React__default["default"].createElement("form", { className: "row d-grid gap-2", method: "post", action: "/admp/banid" }, + React__default["default"].createElement("div", { class: "col-auto" }, + React__default["default"].createElement("input", { type: "text", readonly: true, class: "form-control", name: "id", placeholder: "id" })), + React__default["default"].createElement("div", { class: "col-auto d-grid gap-2" }, + React__default["default"].createElement("button", { type: "submit", class: "btn btn-primary mb-3" }, "Ban")))))), + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "card text-dark bg-light mb-3", style: { maxWidth: "18rem" } }, + React__default["default"].createElement("div", { className: "card-header" }, "Unban user"), + React__default["default"].createElement("div", { className: "card-body" }, + React__default["default"].createElement("form", { className: "row d-grid gap-2", method: "post", action: "/admp/banid" }, + React__default["default"].createElement("div", { class: "col-auto" }, + React__default["default"].createElement("input", { type: "text", readonly: true, class: "form-control", name: "unbanid", placeholder: "id" })), + React__default["default"].createElement("div", { class: "col-auto d-grid gap-2" }, + React__default["default"].createElement("button", { type: "submit", class: "btn btn-primary mb-3" }, "Unban"))))))), + React__default["default"].createElement("div", { className: "row" }, + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Bans"), + React__default["default"].createElement("table", { className: "table" }, + React__default["default"].createElement("thead", null, + React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "col" }, "Time"), + React__default["default"].createElement("th", { scope: "col" }, "ClientId"), + React__default["default"].createElement("th", { scope: "col" }, "Country"), + React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), + React__default["default"].createElement("tbody", null, latestBans.map(function (_a) { + var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; + return (React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), + React__default["default"].createElement("td", null, + React__default["default"].createElement("div", { className: "d-flex" }, + React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), + " ", + currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), + React__default["default"].createElement("td", null, + React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), + React__default["default"].createElement("td", null, pathname))); + })))))))); }; - var AdminPanelLogin = function (_a) { - var hasUsers = _a.hasUsers; - return (React__default["default"].createElement("div", { className: "m-3" }, hasUsers ? (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement("h1", { className: "display-6 mb-3" }, "Login"), - React__default["default"].createElement("form", { className: "row g-3", method: "post", action: "/admp" }, - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("label", { for: "staticEmail2", className: "visually-hidden" }, "Email"), - React__default["default"].createElement("input", { type: "text", className: "form-control", name: "email", placeholder: "Email" })), - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("label", { for: "inputPassword2", className: "visually-hidden" }, "Password"), - React__default["default"].createElement("input", { type: "password", className: "form-control", name: "password", placeholder: "Password" })), - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("button", { type: "submit", className: "btn btn-primary mb-3" }, "Confirm identity"))))) : (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement("h1", { className: "display-6 mb-3" }, "Welcome to Apiker"), - React__default["default"].createElement("p", { className: "lead" }, "Setup your admin account in order to manage your Apiker installation."), - React__default["default"].createElement("form", { className: "row g-3", method: "post", action: "/admp" }, - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("label", { for: "staticEmail2", className: "visually-hidden" }, "Email"), - React__default["default"].createElement("input", { type: "text", className: "form-control", name: "email", placeholder: "Email" })), - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("label", { for: "inputPassword2", className: "visually-hidden" }, "Password"), - React__default["default"].createElement("input", { type: "password", className: "form-control", name: "password", placeholder: "Password" })), - React__default["default"].createElement("div", { className: "col-auto" }, - React__default["default"].createElement("button", { type: "submit", className: "btn btn-primary mb-3" }, "Create account"))))))); + var AdminPanelLogin = function (_a) { + var hasAdmins = _a.hasAdmins; + return (React__default["default"].createElement("div", { className: "m-3" }, hasAdmins ? (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement("h1", { className: "display-6 mb-3" }, "Login"), + React__default["default"].createElement("form", { className: "row g-3", method: "post", action: "/admp" }, + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("label", { for: "staticEmail2", className: "visually-hidden" }, "Email"), + React__default["default"].createElement("input", { type: "text", className: "form-control", name: "email", placeholder: "Email" })), + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("label", { for: "inputPassword2", className: "visually-hidden" }, "Password"), + React__default["default"].createElement("input", { type: "password", className: "form-control", name: "password", placeholder: "Password" })), + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("button", { type: "submit", className: "btn btn-primary mb-3" }, "Confirm identity"))))) : (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement("h1", { className: "display-6 mb-3" }, "Welcome to Apiker"), + React__default["default"].createElement("p", { className: "lead" }, "Setup your admin account in order to manage your Apiker installation."), + React__default["default"].createElement("form", { className: "row g-3", method: "post", action: "/admp" }, + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("label", { for: "staticEmail2", className: "visually-hidden" }, "Email"), + React__default["default"].createElement("input", { type: "text", className: "form-control", name: "email", placeholder: "Email" })), + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("label", { for: "inputPassword2", className: "visually-hidden" }, "Password"), + React__default["default"].createElement("input", { type: "password", className: "form-control", name: "password", placeholder: "Password" })), + React__default["default"].createElement("div", { className: "col-auto" }, + React__default["default"].createElement("button", { type: "submit", className: "btn btn-primary mb-3" }, "Create account"))))))); }; - var AdminPanelDashboard = function (_a) { - var latestBans = _a.latestBans, latestVisitors = _a.latestVisitors, allVisitorsCount = _a.allVisitorsCount, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; - return (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement(PanelHeader, { rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), - React__default["default"].createElement("div", { className: "container" }, - React__default["default"].createElement("div", { className: "row" }, - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, - "Latest Visitors (", - allVisitorsCount, - ")"), - React__default["default"].createElement("table", { className: "table" }, - React__default["default"].createElement("thead", null, - React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "col" }, "Time"), - React__default["default"].createElement("th", { scope: "col" }, "ClientId"), - React__default["default"].createElement("th", { scope: "col" }, "Country"), - React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), - React__default["default"].createElement("tbody", null, latestVisitors.map(function (_a) { - var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; - return (React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), - React__default["default"].createElement("td", null, - React__default["default"].createElement("div", { class: "d-flex" }, - React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), - " ", - currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), - React__default["default"].createElement("td", null, - React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), - React__default["default"].createElement("td", null, pathname))); - }))), - React__default["default"].createElement("div", { className: "d-flex justify-content-center" }, - React__default["default"].createElement("a", { href: "/admp/visitors", class: "btn btn-link" }, "View All"))), - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Bans"), - React__default["default"].createElement("table", { className: "table" }, - React__default["default"].createElement("thead", null, - React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "col" }, "Time"), - React__default["default"].createElement("th", { scope: "col" }, "ClientId"), - React__default["default"].createElement("th", { scope: "col" }, "Country"), - React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), - React__default["default"].createElement("tbody", null, latestBans.map(function (_a) { - var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; - return (React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), - React__default["default"].createElement("td", null, - React__default["default"].createElement("div", { class: "d-flex" }, - React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), - " ", - currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), - React__default["default"].createElement("td", null, - React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), - React__default["default"].createElement("td", null, pathname))); - }))), - React__default["default"].createElement("div", { className: "d-flex justify-content-center" }, - React__default["default"].createElement("a", { href: "/admp/bans", class: "btn btn-link" }, "View All"))))))); + var AdminPanelDashboard = function (_a) { + var latestBans = _a.latestBans, latestVisitors = _a.latestVisitors, allVisitorsCount = _a.allVisitorsCount, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; + return (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement(PanelHeader, { rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), + React__default["default"].createElement("div", { className: "container" }, + React__default["default"].createElement("div", { className: "row" }, + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, + "Latest Visitors (", + allVisitorsCount, + ")"), + React__default["default"].createElement("table", { className: "table" }, + React__default["default"].createElement("thead", null, + React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "col" }, "Time"), + React__default["default"].createElement("th", { scope: "col" }, "ClientId"), + React__default["default"].createElement("th", { scope: "col" }, "Country"), + React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), + React__default["default"].createElement("tbody", null, latestVisitors.map(function (_a) { + var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; + return (React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), + React__default["default"].createElement("td", null, + React__default["default"].createElement("div", { class: "d-flex" }, + React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), + " ", + currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), + React__default["default"].createElement("td", null, + React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), + React__default["default"].createElement("td", null, pathname))); + }))), + React__default["default"].createElement("div", { className: "d-flex justify-content-center" }, + React__default["default"].createElement("a", { href: "/admp/visitors", class: "btn btn-link" }, "View All"))), + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Bans"), + React__default["default"].createElement("table", { className: "table" }, + React__default["default"].createElement("thead", null, + React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "col" }, "Time"), + React__default["default"].createElement("th", { scope: "col" }, "ClientId"), + React__default["default"].createElement("th", { scope: "col" }, "Country"), + React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), + React__default["default"].createElement("tbody", null, latestBans.map(function (_a) { + var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; + return (React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), + React__default["default"].createElement("td", null, + React__default["default"].createElement("div", { class: "d-flex" }, + React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), + " ", + currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), + React__default["default"].createElement("td", null, + React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), + React__default["default"].createElement("td", null, pathname))); + }))), + React__default["default"].createElement("div", { className: "d-flex justify-content-center" }, + React__default["default"].createElement("a", { href: "/admp/bans", class: "btn btn-link" }, "View All"))))))); }; - var AdminPanelPage = function (_a) { - var latestLogins = _a.latestLogins, currentId = _a.currentId; - return (React__default["default"].createElement("div", { class: "m-3" }, - React__default["default"].createElement("h1", { className: "display-6 mb-3" }, latestLogins.length ? "Welcome back" : "Welcome"), - React__default["default"].createElement("p", { className: "lead" }, "Latest admin-login events:"), - React__default["default"].createElement("div", null, - React__default["default"].createElement("table", { className: "table" }, - React__default["default"].createElement("thead", null, - React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "col" }, "Time"), - React__default["default"].createElement("th", { scope: "col" }, "ClientId"), - React__default["default"].createElement("th", { scope: "col" }, "Country"), - React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), - React__default["default"].createElement("tbody", null, latestLogins.map(function (_a) { - var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; - return (React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), - React__default["default"].createElement("td", null, - React__default["default"].createElement("div", { class: "d-flex" }, - React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), - " ", - currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), - React__default["default"].createElement("td", null, - React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), - React__default["default"].createElement("td", null, pathname))); - }))), - React__default["default"].createElement("a", { href: "/admp/dashboard", class: "btn btn-primary" }, "Continue to Dashboard")))); + var AdminPanelPage = function (_a) { + var latestLogins = _a.latestLogins, currentId = _a.currentId; + return (React__default["default"].createElement("div", { class: "m-3" }, + React__default["default"].createElement("h1", { className: "display-6 mb-3" }, latestLogins.length ? "Welcome back" : "Welcome"), + React__default["default"].createElement("p", { className: "lead" }, "Latest admin-login events:"), + React__default["default"].createElement("div", null, + React__default["default"].createElement("table", { className: "table" }, + React__default["default"].createElement("thead", null, + React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "col" }, "Time"), + React__default["default"].createElement("th", { scope: "col" }, "ClientId"), + React__default["default"].createElement("th", { scope: "col" }, "Country"), + React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), + React__default["default"].createElement("tbody", null, latestLogins.map(function (_a) { + var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; + return (React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), + React__default["default"].createElement("td", null, + React__default["default"].createElement("div", { class: "d-flex" }, + React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), + " ", + currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), + React__default["default"].createElement("td", null, + React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), + React__default["default"].createElement("td", null, pathname))); + }))), + React__default["default"].createElement("a", { href: "/admp/dashboard", class: "btn btn-primary" }, "Continue to Dashboard")))); }; - var AdminPanelVisitors = function (_a) { - var currentSection = _a.currentSection, latestVisitors = _a.latestVisitors, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; - return (React__default["default"].createElement(React__default["default"].Fragment, null, - React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), - React__default["default"].createElement("div", { className: "container" }, - React__default["default"].createElement("div", { className: "row" }, - React__default["default"].createElement("div", { className: "col" }, - React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Visitors"), - React__default["default"].createElement("table", { className: "table" }, - React__default["default"].createElement("thead", null, - React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "col" }, "Time"), - React__default["default"].createElement("th", { scope: "col" }, "Id"), - React__default["default"].createElement("th", { scope: "col" }, "Country"), - React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), - React__default["default"].createElement("tbody", null, latestVisitors.map(function (_a) { - var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; - return (React__default["default"].createElement("tr", null, - React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), - React__default["default"].createElement("td", null, - React__default["default"].createElement("div", { class: "d-flex" }, - React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), - " ", - currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), - React__default["default"].createElement("td", null, - React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), - React__default["default"].createElement("td", null, pathname))); - })))))))); + var AdminPanelVisitors = function (_a) { + var currentSection = _a.currentSection, latestVisitors = _a.latestVisitors, currentId = _a.currentId, rateLimitMax = _a.rateLimitMax, rateLimitRemaining = _a.rateLimitRemaining; + return (React__default["default"].createElement(React__default["default"].Fragment, null, + React__default["default"].createElement(PanelHeader, { currentSection: currentSection, rateLimitMax: rateLimitMax, rateLimitRemaining: rateLimitRemaining }), + React__default["default"].createElement("div", { className: "container" }, + React__default["default"].createElement("div", { className: "row" }, + React__default["default"].createElement("div", { className: "col" }, + React__default["default"].createElement("div", { className: "p-2 text-light bg-secondary" }, "Latest Visitors"), + React__default["default"].createElement("table", { className: "table" }, + React__default["default"].createElement("thead", null, + React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "col" }, "Time"), + React__default["default"].createElement("th", { scope: "col" }, "Id"), + React__default["default"].createElement("th", { scope: "col" }, "Country"), + React__default["default"].createElement("th", { scope: "col" }, "Pathname"))), + React__default["default"].createElement("tbody", null, latestVisitors.map(function (_a) { + var time = _a.time, id = _a.id, countryCode = _a.countryCode, pathname = _a.pathname; + return (React__default["default"].createElement("tr", null, + React__default["default"].createElement("th", { scope: "row" }, new Date(time).toLocaleString()), + React__default["default"].createElement("td", null, + React__default["default"].createElement("div", { class: "d-flex" }, + React__default["default"].createElement("span", { className: "text-truncate", style: { maxWidth: 100, display: "inline-block" }, title: id }, id), + " ", + currentId === id && React__default["default"].createElement("span", { className: "badge bg-primary", title: "This client" }, "*"))), + React__default["default"].createElement("td", null, + React__default["default"].createElement("span", { title: countryCode }, getFlagEmoji(countryCode))), + React__default["default"].createElement("td", null, pathname))); + })))))))); }; - var pages = { - AdminPanelPage: AdminPanelPage, - AdminPanelLogin: AdminPanelLogin, - AdminPanelDashboard: AdminPanelDashboard, - AdminPanelVisitors: AdminPanelVisitors, - AdminPanelBans: AdminPanelBans, - AdminPanelBanId: AdminPanelBanId + var pages = { + AdminPanelPage: AdminPanelPage, + AdminPanelLogin: AdminPanelLogin, + AdminPanelDashboard: AdminPanelDashboard, + AdminPanelVisitors: AdminPanelVisitors, + AdminPanelBans: AdminPanelBans, + AdminPanelBanId: AdminPanelBanId }; return pages; diff --git a/tsconfig.json b/tsconfig.json index 1531445..27c99c2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "jsx": "react", "target": "es6", - "module": "esnext", + "module": "commonjs", "declaration": true, "declarationDir": "types", "sourceMap": true,