From 0ddbc437b97bda9a63290192af491cbf6afa9158 Mon Sep 17 00:00:00 2001 From: Lightemerald Date: Mon, 26 Feb 2024 10:20:29 +0100 Subject: [PATCH] First part of backend rework - Added the base data structure for the new database - Added the new routes for the new database - Reworked the users endpoints --- .env.sample | 3 +- .eslintrc.json | 3 + .gitignore | 6 + tokensDB/000037.log => README.md | 0 bun.lockb | Bin 93943 -> 97275 bytes database.sql | 409 +++++++------- index.js | 28 +- logs/access.log | 187 ------- modules/cronManager.js | 48 ++ modules/{database.js => databaseManager.js} | 0 modules/{fetcher.js => fetchManager.js} | 10 +- modules/fileManager.js | 14 +- .../{formatHandler.js => formatManager.js} | 5 + modules/{log.js => logManager.js} | 0 modules/mailHandler.js | 65 +-- modules/permission.js | 101 ---- modules/permissionManager.js | 65 +++ modules/random.js | 17 +- modules/requestHandler.js | 3 +- modules/token.js | 101 ---- modules/tokenManager.js | 40 ++ package.json | 12 +- public/index.html | 30 +- public/scripts/app.js | 18 +- routes/airlines.js | 143 ----- routes/airplanes.js | 143 ----- routes/airports.js | 143 ----- routes/companies.js | 128 +++++ routes/doctors.js | 151 +++++ routes/flights.js | 143 ----- routes/hospitals.js | 156 ++++++ routes/patients.js | 151 +++++ routes/pilots.js | 144 ----- routes/seats.js | 155 ------ routes/users.js | 519 +++++++----------- tokensDB/CURRENT | 1 - tokensDB/LOCK | 0 tokensDB/LOG | 3 - tokensDB/LOG.old | 3 - tokensDB/MANIFEST-000036 | Bin 50 -> 0 bytes 40 files changed, 1237 insertions(+), 1911 deletions(-) rename tokensDB/000037.log => README.md (100%) delete mode 100644 logs/access.log create mode 100644 modules/cronManager.js rename modules/{database.js => databaseManager.js} (100%) rename modules/{fetcher.js => fetchManager.js} (84%) rename modules/{formatHandler.js => formatManager.js} (83%) rename modules/{log.js => logManager.js} (100%) delete mode 100644 modules/permission.js create mode 100644 modules/permissionManager.js delete mode 100644 modules/token.js create mode 100644 modules/tokenManager.js delete mode 100644 routes/airlines.js delete mode 100644 routes/airplanes.js delete mode 100644 routes/airports.js create mode 100644 routes/companies.js create mode 100644 routes/doctors.js delete mode 100644 routes/flights.js create mode 100644 routes/hospitals.js create mode 100644 routes/patients.js delete mode 100644 routes/pilots.js delete mode 100644 routes/seats.js delete mode 100644 tokensDB/CURRENT delete mode 100644 tokensDB/LOCK delete mode 100644 tokensDB/LOG delete mode 100644 tokensDB/LOG.old delete mode 100644 tokensDB/MANIFEST-000036 diff --git a/.env.sample b/.env.sample index 2b88f4e..fec9b30 100644 --- a/.env.sample +++ b/.env.sample @@ -1,9 +1,10 @@ +PORT=3000 +DOMAIN="http://localhost:3000" DATABASE_HOST="127.0.0.1" DATABASE_NAME=hsp-gdh DATABASE_USER=hsp-gdh DATABASE_PASSWORD="" JWT_SECRET="" -PORT= SMTP= MAIL= MAIL_PASS= \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 2fcbea3..3495da3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -46,5 +46,8 @@ "space-unary-ops": "error", "spaced-comment": "error", "yoda": "error" + }, + "globals": { + "Bun": false } } \ No newline at end of file diff --git a/.gitignore b/.gitignore index d7ff0f0..f0d9796 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,9 @@ dist .yarn/install-state.gz .pnp.* +# logs +logs/ +*.log + +# token +token/ \ No newline at end of file diff --git a/tokensDB/000037.log b/README.md similarity index 100% rename from tokensDB/000037.log rename to README.md diff --git a/bun.lockb b/bun.lockb index cf1eea9b22fc73e5f8a547220a0acb14fd5937c4..e0b6543d7c0f2209a3b4e64e5e11603a89727b62 100755 GIT binary patch delta 20344 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 M7&WGg=P^D201{cu9{>OV delta 18118 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 { diff --git a/logs/access.log b/logs/access.log deleted file mode 100644 index 691dca0..0000000 --- a/logs/access.log +++ /dev/null @@ -1,187 +0,0 @@ -::ffff:127.0.0.1 - - [15/Feb/2023:20:21:41 +0000] "OPTIONS /user/login HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:21:41 +0000] "POST /user/login HTTP/1.1" 200 261 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:21:41 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:21:41 +0000] "GET /user/profile HTTP/1.1" 401 27 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:22:00 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:22:00 +0000] "GET /user/profile HTTP/1.1" 200 180 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:22:55 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:22:55 +0000] "GET /user/profile HTTP/1.1" 404 29 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:23:05 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:23:06 +0000] "GET /user/profile HTTP/1.1" 401 27 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:23:39 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:23:39 +0000] "POST /user/register HTTP/1.1" 500 35 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:21 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:21 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:41 +0000] "OPTIONS /user/login HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:41 +0000] "POST /user/login HTTP/1.1" 200 261 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:41 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:24:41 +0000] "GET /user/profile HTTP/1.1" 200 190 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:27:36 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:28:16 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:28:16 +0000] "GET /user/profile HTTP/1.1" 304 - "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:08 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:08 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:18 +0000] "OPTIONS /user/login HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:18 +0000] "POST /user/login HTTP/1.1" 200 258 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:18 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:30:18 +0000] "GET /user/profile HTTP/1.1" 200 177 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:33:05 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:33:05 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:34:37 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:34:38 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:36:28 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:36:28 +0000] "POST /user/register HTTP/1.1" 401 29 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:39:25 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:39:25 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:34 +0000] "OPTIONS /user/register HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:34 +0000] "POST /user/register HTTP/1.1" 200 37 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:44 +0000] "OPTIONS /user/login HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:44 +0000] "POST /user/login HTTP/1.1" 200 275 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:44 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:40:44 +0000] "GET /user/profile HTTP/1.1" 200 194 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:44:45 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:44:45 +0000] "GET /user/profile HTTP/1.1" 304 - "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:46:02 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:46:02 +0000] "GET /user/profile HTTP/1.1" 304 - "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:46:46 +0000] "OPTIONS /user/profile HTTP/1.1" 204 0 "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [15/Feb/2023:20:46:47 +0000] "GET /user/profile HTTP/1.1" 304 - "http://127.0.0.1/" "Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:11 +0000] "GET / HTTP/1.1" 404 139 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:23 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:35 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:35 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:35 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:35 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:35 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:36 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:36 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:36 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:36 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:36 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:37 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:37 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:37 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:37 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:38 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:38 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:39 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:39 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:39 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:40 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:41 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:42 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:43 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:43 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:43 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:43 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:43 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:44 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:45 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:46 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:47 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:48 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:06:49 +0000] "GET /users HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:07:53 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:44 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:44 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:45 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:45 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:45 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:46 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:46 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:46 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:46 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:46 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:47 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:47 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:47 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:47 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:47 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:48 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:48 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:48 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:48 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:49 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:08:49 +0000] "GET /users/register HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:09:04 +0000] "GET /users/login HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:09:07 +0000] "GET /users/loginn HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:09:11 +0000] "GET /users/login HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:11:15 +0000] "GET /users/login HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:12:03 +0000] "POST /users/login HTTP/1.1" 500 35 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:14:49 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:15:14 +0000] "GET /users/login HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:15:44 +0000] "GET /users/verify HTTP/1.1" 401 31 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:16:30 +0000] "GET /users/verify HTTP/1.1" 500 35 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:16:31 +0000] "GET /users/verify HTTP/1.1" 500 35 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:16:31 +0000] "GET /users/verify HTTP/1.1" 500 35 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:18:28 +0000] "GET /users/verify HTTP/1.1" 400 25 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:18:37 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:18:55 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:19:37 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:20:01 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:42 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:51 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:52 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:52 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:53 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:53 +0000] "POST /users/login HTTP/1.1" 429 54 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:54 +0000] "POST /users/login HTTP/1.1" 429 54 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:23:55 +0000] "POST /users/login HTTP/1.1" 429 54 "-" "Wget/1.21.3" -::ffff:127.0.0.1 - - [12/Mar/2023:13:25:02 +0000] "GET /users/verify HTTP/1.1" 400 25 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:26:29 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "curl/7.84.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:28:59 +0000] "GET /test HTTP/1.1" 200 45 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:29:30 +0000] "POST /test HTTP/1.1" 200 46 "-" "curl/7.84.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:30:08 +0000] "POST /test HTTP/1.1" 200 46 "-" "curl/7.84.0" -::ffff:127.0.0.1 - - [12/Mar/2023:13:31:49 +0000] "POST /test HTTP/1.1" 200 46 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" -::ffff:127.0.0.1 - - [12/Mar/2023:13:32:12 +0000] "POST /users/login HTTP/1.1" 400 41 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" -::ffff:127.0.0.1 - - [12/Mar/2023:13:32:54 +0000] "POST /users/login HTTP/1.1" 400 41 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" -::ffff:127.0.0.1 - - [12/Mar/2023:13:33:50 +0000] "POST /users/login HTTP/1.1" 400 25 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" -::ffff:127.0.0.1 - - [12/Mar/2023:13:34:25 +0000] "POST /users/login HTTP/1.1" 400 41 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" -::ffff:127.0.0.1 - - [12/Mar/2023:13:35:27 +0000] "POST /users/login HTTP/1.1" 400 41 "-" "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)" diff --git a/modules/cronManager.js b/modules/cronManager.js new file mode 100644 index 0000000..cb434ff --- /dev/null +++ b/modules/cronManager.js @@ -0,0 +1,48 @@ +import cron from 'node-cron'; + +const daysOfWeek = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; +const hoursOfDay = [...Array(24).keys()].map(hour => hour.toString()); +const minutesOfHour = [...Array(60).keys()].map(minute => minute.toString()); + +function toCronExpression(str) { + switch (str.toLowerCase()) { + case 'everyfiveseconds': { + return '*/5 * * * * *'; + } + case 'everythirtyseconds': { + return '*/30 * * * * *'; + } + case 'everyminute': { + return '* * * * *'; + } + case 'everyfiveminutes': { + return '*/5 * * * *'; + } + case 'everyfifteenminutes': { + return '*/15 * * * *'; + } + case 'everythirtyminutes': { + return '*/30 * * * *'; + } + case 'everyday': { + return '0 0 * * *'; + } + case 'weekdays': { + return '0 0 * * 1-5'; + } + case 'weekends': { + return '0 0 * * 6,7'; + } + default: { + const [day, hour, minute] = str.toLowerCase().split(' '); + const dayIndex = daysOfWeek.indexOf(day); + const hourIndex = hoursOfDay.indexOf(hour); + const minuteIndex = minutesOfHour.indexOf(minute); + return `${minuteIndex} ${hourIndex} * * ${dayIndex}`; + } + } +} + +export function createCron(rate, exec) { + cron.schedule(toCronExpression(rate), exec); +} \ No newline at end of file diff --git a/modules/database.js b/modules/databaseManager.js similarity index 100% rename from modules/database.js rename to modules/databaseManager.js diff --git a/modules/fetcher.js b/modules/fetchManager.js similarity index 84% rename from modules/fetcher.js rename to modules/fetchManager.js index 499f12a..adb4a23 100644 --- a/modules/fetcher.js +++ b/modules/fetchManager.js @@ -1,7 +1,7 @@ import fetch from 'node-fetch'; -import { error } from './log'; +import { error } from './logManager'; -async function get(url, token) { +async function get(url, token = 'none') { const options = { method: 'GET', headers: { 'Content-Type': 'application/json', authorization: `${token}` }, @@ -15,7 +15,7 @@ async function get(url, token) { .catch(err => error(err)); } -async function post(url, body, token) { +async function post(url, body, token = 'none') { const options = { method: 'POST', mode: 'cors', @@ -31,7 +31,7 @@ async function post(url, body, token) { .catch(err => error(err)); } -async function patch(url, body, token) { +async function patch(url, body, token = 'none') { const options = { method: 'PATCH', mode: 'cors', @@ -47,7 +47,7 @@ async function patch(url, body, token) { .catch(err => error(err)); } -async function put(url, body, token) { +async function put(url, body, token = 'none') { const options = { method: 'PUT', mode: 'cors', diff --git a/modules/fileManager.js b/modules/fileManager.js index 558c972..f1d1918 100644 --- a/modules/fileManager.js +++ b/modules/fileManager.js @@ -1,6 +1,7 @@ import fs from 'fs'; -import download from 'download'; -import random from './random'; +import { Readable } from 'stream'; +import { finished } from 'stream/promises'; +import { random } from './random'; function fileExist(path) { try { @@ -22,9 +23,11 @@ function fileDelete(path) { } } -function fileDownload(url, name) { +async function fileDownload(url, path) { try { - download(url, '../cdn/images/', { filename: name }); + const stream = fs.createWriteStream(path); + const { body } = await fetch(url); + await finished(Readable.fromWeb(body).pipe(stream)); return true; } catch (err) { @@ -32,6 +35,7 @@ function fileDownload(url, name) { } } + function folderExist(path) { try { if (fs.existsSync(path)) { @@ -58,7 +62,7 @@ function getFilesFromFolder(path) { function randomFileFromFolder(path) { try { if (getFilesFromFolder(path)) { - return random.random(0, getFilesFromFolder(path).length); + return random(0, getFilesFromFolder(path).length); } else { return false; diff --git a/modules/formatHandler.js b/modules/formatManager.js similarity index 83% rename from modules/formatHandler.js rename to modules/formatManager.js index a28c1fd..9ac8207 100644 --- a/modules/formatHandler.js +++ b/modules/formatManager.js @@ -22,4 +22,9 @@ export function isValidEmail(email) { export function isNumber(x) { return /^-?[\d.]+(?:e-?\d+)?$/.test(x); +} + +export function isPhoneNumber(phone) { + const phoneRegex = /^\d{10}$/; + return phoneRegex.test(phone); } \ No newline at end of file diff --git a/modules/log.js b/modules/logManager.js similarity index 100% rename from modules/log.js rename to modules/logManager.js diff --git a/modules/mailHandler.js b/modules/mailHandler.js index e1f63b6..08b2648 100644 --- a/modules/mailHandler.js +++ b/modules/mailHandler.js @@ -1,9 +1,6 @@ /* eslint-disable no-undef */ import nodemailer from 'nodemailer'; import { random } from './random'; -import { createPool } from './database'; - -const pool = createPool('localhost', 'root', '', 'postfixadmin'); const transporter = nodemailer.createTransport({ host: process.env.SMTP, @@ -15,29 +12,6 @@ const transporter = nodemailer.createTransport({ }, }); -async function createAddress(username, domain, password, name = '', backup_email = '', phone = '') { - try { - const hashedPassword = await Bun.password.hash(password, { - type: Bun.password.argon2i, - memoryCost: 2 ** 15, - hashLength: 32, - timeCost: 5, - }); - const [result] = await pool.execute( - 'INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `created`, `modified`, `active`, `phone`, `email_other`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [ username, hashedPassword, name, `${domain}/${username}`, 0, username, domain, Date.now(), Date.now(), '1', phone, backup_email], - ); - if (result.affectedRows === 0) { - return false; - } - return true; - } - catch (error) { - console.error(error); - return false; - } -} - function sendMail(email, head, body) { try { // setup email data @@ -63,30 +37,29 @@ function sendMail(email, head, body) { } } -function sendVerification(email, userId) { +function sendVerification(email, userId, type = 'register', code = null) { try { - const code = random(100000, 999999); - if (sendMail(email, 'Your verification code for AirJet', `Verification code: ${code}\nLink: https://aostia.me/api/users/verify?u=${userId}&c=${code}`)) { - return code; - } - else { + code ? code : random(100000, 999999); + let title, body; + switch (type) { + case 'email': + title = 'Your verification code for HSP-GDH'; + body = `Verification code: ${code}\nLink: ${process.env.DOMAIN}/email/verify?code=${code}`; + break; + case 'password': + title = 'Your password reset code for HSP-GDH'; + body = `Verification code: ${code}\nLink: ${process.env.DOMAIN}/password/reset?u=${userId}&c=${code}`; + break; + case '2fa': + title = 'Your 2FA code for HSP-GDH'; + body = `Verification code: ${code}`; + break; + default: return false; } - } - catch (err) { + if (sendMail(email, title, body)) return code; return false; } -} - -function sendResetVerification(email, code = random(100000, 999999)) { - try { - if (sendMail(email, 'Your reset verification code for AirJet', `Verification code: ${code}`)) { - return code; - } - else { - return false; - } - } catch (err) { return false; } @@ -95,6 +68,4 @@ function sendResetVerification(email, code = random(100000, 999999)) { export { sendMail, sendVerification, - sendResetVerification, - createAddress, }; \ No newline at end of file diff --git a/modules/permission.js b/modules/permission.js deleted file mode 100644 index 16718d1..0000000 --- a/modules/permission.js +++ /dev/null @@ -1,101 +0,0 @@ -import { pool } from '../modules/database.js'; -import { respondWithStatus } from './requestHandler.js'; - -// Middleware to verify the user permissions -async function verifyPermissions(userId, perms_req) { - - try { - // Query the database to get the user - const [user] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [userId]); - if (user.length === 0) { - return false; - } - - // Query the database to get the perms and verify - const [hasPerm] = await pool.execute( - 'SELECT COUNT(*) AS count FROM user_type_permissions WHERE user_type_id = ? AND permission_id = (SELECT id FROM permissions WHERE name = ?) LIMIT 1', - [ user[0].user_type_id, perms_req ], - ); - if (hasPerm.length === 0) { - return false; - } - else { - return true; - } - } - catch (error) { - return false; - } -} - -const hasPermission = (perms_req) => async (req, res, next) => { - try { - const userId = req.userId; - - // Query the database to get the user - const [user] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [userId]); - if (user.length === 0) { - return await respondWithStatus(res, 401, 'User is invalid'); - } - // Query the database to get the perms and verify - const [hasPerm] = await pool.execute( - 'SELECT COUNT(*) AS count FROM user_type_permissions WHERE user_type_id = ? AND permission_id = (SELECT id FROM permissions WHERE name = ?) LIMIT 1', - [ user[0].user_type_id, perms_req ], - ); - if (req.originalUrl == '/api/users/me') { - next(); - return; - } - if (hasPerm.length === 0) { - return await respondWithStatus(res, 403, 'Missing permission'); - } - else if (hasPerm[0].count == 0) { - return await respondWithStatus(res, 403, 'Missing permission'); - } - else {next();} - } - catch (error) { - console.error(error); - return await respondWithStatus(res, 500, 'An error has occured'); - } -}; - -async function checkBanned(req, res, next) { - const userId = req.userId; - try { - const [user] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [userId]); - if (user.length === 0) { - return await respondWithStatus(res, 404, 'User not found'); - } - if (user[0].is_banned) { - return await respondWithStatus(res, 403, 'User is banned'); - } - next(); - } - catch (error) { - console.error(error); - return await respondWithStatus(res, 500, 'An error has occured'); - } -} - -async function isBanned(userId) { - try { - // Query the database to get the user - const [user] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [userId]); - if (user.length === 0) { - return true; - } - else if (user[0].is_banned == 1) { - return true; - } - else { - return false; - } - } - catch (error) { - console.error(error); - return true; - } -} - -export { verifyPermissions, hasPermission, checkBanned, isBanned }; \ No newline at end of file diff --git a/modules/permissionManager.js b/modules/permissionManager.js new file mode 100644 index 0000000..f9cc1e6 --- /dev/null +++ b/modules/permissionManager.js @@ -0,0 +1,65 @@ +import { pool } from './databaseManager.js'; +import { respondWithStatus } from './requestHandler.js'; +import { error } from './logManager.js'; + + +export async function userExists(userId) { + try { + const [user] = await pool.execute('SELECT * FROM users WHERE id = ? LIMIT 1', [userId]); + if (user.length === 0) return false; + return true; + } + catch (err) { + error(err); + return false; + } +} + +export async function isBanned(userId) { + try { + const [bannedUser] = await pool.execute('SELECT * FROM bans WHERE user_id = ? LIMIT 1', [userId]); + if (bannedUser.length > 0) return true; + return false; + } + catch (err) { + error(err); + return true; + } +} + +// permissionType is bitfield +// 1 = read +// 2 = write +// 4 = delete +export async function verifyPermissions(userId, permissionName, permissionType) { + try { + const [perms] = await pool.execute(`SELECT r.${permissionName}_bitfield AS permissionBitfield FROM users u INNER JOIN user_roles ur ON u.id = ur.user_id INNER JOIN roles r ON ur.role_id = r.id WHERE u.id = ?`, [userId]); + for (const row of perms) { + if (row.permissionBitfield & permissionType) { + return true; + } + } + } + catch (err) { + error(err); + return false; + } +} + +export async function checkUserExists(req, res, next) { + const userId = req.userId; + if (!userExists(userId)) return await respondWithStatus(res, 404, 'User not found'); + next(); +} + +export async function checkBanned(req, res, next) { + const userId = req.userId; + if (isBanned(userId)) return await respondWithStatus(res, 403, 'User is banned'); + next(); +} + +export const checkPermissions = (permissionName, permissionType) => async (req, res, next) => { + const userId = req.userId; + if (!verifyPermissions(userId, permissionName, permissionType)) return await respondWithStatus(res, 403, 'Missing permission'); + next(); +}; \ No newline at end of file diff --git a/modules/random.js b/modules/random.js index 75ac3b6..2fe78ff 100644 --- a/modules/random.js +++ b/modules/random.js @@ -1,9 +1,22 @@ import crypto from 'crypto'; export function random(x, y) { - return crypto.randomInt(x, y); + return crypto.randomInt(x, y + 1); +} + +export function random2(min, max) { + const range = max - min + 1; + const byteLength = Math.ceil(Math.log2(range) / 8); + let randomValue; + + do { + const randomBytes = crypto.randomBytes(byteLength); + randomValue = parseInt(randomBytes.toString('hex'), 16); + } while (randomValue >= range); + + return randomValue + min; } export function randomHEX(x) { return crypto.randomBytes(x).toString('hex'); -} +} \ No newline at end of file diff --git a/modules/requestHandler.js b/modules/requestHandler.js index bef8a75..bdf33a3 100644 --- a/modules/requestHandler.js +++ b/modules/requestHandler.js @@ -2,6 +2,7 @@ import rateLimit from 'express-rate-limit'; import slowDown from 'express-slow-down'; import http from 'http'; import os from 'os'; +import { log } from './logManager'; const requestLimiter = rateLimit({ windowMs: 60 * 1000, @@ -23,7 +24,7 @@ function checkSystemLoad(req, res, next) { const threshold = cores * 0.7; if (load > threshold) { - console.log('System load too high, please try again later'); + log('System load too high, please try again later'); return res.status(503).send(http.STATUS_CODES[503]); } diff --git a/modules/token.js b/modules/token.js deleted file mode 100644 index 589ee35..0000000 --- a/modules/token.js +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable no-undef */ -import jwt from 'jsonwebtoken'; -import levelup from 'levelup'; -import leveldown from 'leveldown'; -import { respondWithStatus } from './requestHandler'; -import { pool } from './database'; - - -// Set up LevelDB instance -const db = levelup(leveldown('./tokensDB')); - -// Generate a new JWT -const generateToken = async (userId, password) => { - const token = jwt.sign({ userId: userId, password: password }, process.env.JWT_SECRET, { expiresIn: '7d' }); - await db.put(token, 'valid'); - return token; -}; - -// Middleware to verify the JWT and set req.userId -const verifyToken = async (req, res, next) => { - const token = req.headers.authorization; - if (!token) { - return await respondWithStatus(res, 401, 'No token provided'); - } - - try { - const decoded = jwt.verify(token, process.env.JWT_SECRET); - req.userId = decoded.userId; - - const [rows] = await pool.execute( - 'SELECT * FROM users WHERE id = ? LIMIT 1', - [req.userId], - ); - if (!rows.length) { - return await respondWithStatus(res, 404, 'User not found!'); - } - const passwordMatch = await Bun.password.verify(decoded.password, rows[0].password); - if (!passwordMatch) { - return await respondWithStatus(res, 401, 'Token is invalid'); - } - // Check if the token is close to expiring - const now = Date.now().valueOf() / 1000; - if (decoded.exp - now < 36000) { - // Generate a new token if the old one is close to expiring - const newToken = generateToken(req.userId, decoded.password); - res.cookie('token', newToken, { - expires: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000), - httpOnly: true, - secure: true, - sameSite: 'strict', - }); - res.set('Authorization', newToken); - } - - // Check if the token has been revoked - const tokenStatus = await db.get(token); - if (tokenStatus != 'valid') { - return await respondWithStatus(res, 401, 'Token has been revoked '); - } - next(); - } - catch (error) { - return await respondWithStatus(res, 401, 'Invalid user'); - } -}; - -// Function to revoke a token -const revokeToken = (token) => { - return new Promise((resolve, reject) => { - db.put(token, 'revoked', (error) => { - if (error) { - reject(error); - } - else { - resolve(); - } - }); - }); -}; - -// Function to revoke all tokens of a user -const revokeUserTokens = (userId) => { - return new Promise((resolve, reject) => { - const tokensToRevoke = []; - db.createReadStream() - .on('data', (data) => { - const token = data.key; - const decoded = jwt.decode(token); - if (decoded.userId === userId) { - tokensToRevoke.push(token); - } - }) - .on('end', () => { - Promise.all(tokensToRevoke.map(revokeToken)) - .then(resolve) - .catch(reject); - }); - }); -}; - -export { generateToken, verifyToken, revokeToken, revokeUserTokens }; diff --git a/modules/tokenManager.js b/modules/tokenManager.js new file mode 100644 index 0000000..aa52b49 --- /dev/null +++ b/modules/tokenManager.js @@ -0,0 +1,40 @@ +/* eslint-disable no-undef */ +import jwt from 'jsonwebtoken'; +import { Level } from 'level'; +import { respondWithStatus } from './requestHandler'; +import { userExists } from './permissionManager'; + +const db = new Level('tokens', { valueEncoding: 'json' }); + +export async function generateToken(userId, password) { + const token = jwt.sign({ userId: userId, password: password }, process.env.JWT_SECRET, { expiresIn: '7d' }); + await db.put(token, 'valid'); + return token; +} + + +export async function verifyToken(req, res, next) { + const token = req.headers.authorization; + if (!token) return await respondWithStatus(res, 401, 'No token provided'); + + try { + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.userId = decoded.userId; + + if (!userExists(userId)) return await respondWithStatus(res, 404, 'User not found'); + const passwordMatch = await Bun.password.verify(decoded.password, rows[0].password); + if (!passwordMatch) return await respondWithStatus(res, 401, 'Token is invalid'); + const tokenStatus = await db.get(token); + if (tokenStatus != 'valid') { + return await respondWithStatus(res, 401, 'Token has been revoked '); + } + next(); + } + catch (error) { + return await respondWithStatus(res, 401, 'Invalid user'); + } +} + +export async function revokeToken(token) { + db.put(token, 'revoked'); +} \ No newline at end of file diff --git a/package.json b/package.json index 39a17db..e6af035 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,11 @@ "module": "index.js", "type": "module", "devDependencies": { + "@types/cookie-parser": "^1.4.6", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", + "@types/nodemailer": "^6.4.14", "bun-types": "latest", "eslint": "^8.54.0" }, @@ -16,12 +21,11 @@ "express-rate-limit": "^7.1.4", "express-slow-down": "^2.0.1", "jsonwebtoken": "^9.0.2", - "level": "^8.0.0", - "leveldown": "^6.1.1", - "levelup": "^5.1.1", + "level": "^8.0.1", "morgan": "^1.10.0", "mysql2": "^3.6.4", - "nodemailer": "^6.9.7", + "node-cron": "^3.0.3", + "nodemailer": "^6.9.10", "path": "^0.12.7", "pino": "^8.16.2" } diff --git a/public/index.html b/public/index.html index 06a40a2..7c26739 100644 --- a/public/index.html +++ b/public/index.html @@ -29,14 +29,13 @@
@@ -53,10 +52,15 @@
-

Fly with us,

-

the sky's the limit!

+

Stayin' Alive!

-

Fly with ease and control your journey with our airline's innovative flight management software. Whether you're booking your flights or making changes to your itinerary, our platform provides you with the flexibility and convenience you need to manage your flights with confidence.

+

Whether you're a brother or whether you're a mother
+ You're stayin' alive, stayin' alive
+ Feel the city breakin' and everybody shakin'
+ And we're stayin' alive, stayin' alive
+ Ah, ha, ha, ha, stayin' alive, stayin' alive
+ Ah, ha, ha, ha, stayin' alive
+ Oh when you walk

@@ -95,24 +99,24 @@

Register

- + - + - +