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 cf1eea9..e0b6543 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/database.sql b/database.sql index 7b9d932..4170894 100644 --- a/database.sql +++ b/database.sql @@ -10,128 +10,28 @@ GRANT ALL PRIVILEGES ON airjet.* TO 'hsp-gdh'@'%'; USE `hsp-gdh`; -CREATE TABLE pilots ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - first_name VARCHAR(255) NOT NULL, - last_name VARCHAR(255) NOT NULL, - email VARCHAR(255) NOT NULL, - phone VARCHAR(20) NOT NULL, - license_number VARCHAR(255) NOT NULL, - license_expiry DATE NOT NULL, - salary DECIMAL(10, 2) NOT NULL DEFAULT 0.0, - status VARCHAR(255) NOT NULL, - PRIMARY KEY (id) -) ENGINE=InnoDB; - -CREATE TABLE airplanes ( +CREATE TABLE roles ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, - type VARCHAR(255) NOT NULL, - manufacturer VARCHAR(255) NOT NULL, - capacity INT NOT NULL, - status VARCHAR(255) NOT NULL, - location VARCHAR(255), - PRIMARY KEY (id) -) ENGINE=InnoDB; - -CREATE TABLE airlines ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - code VARCHAR(2) NOT NULL, - logo VARCHAR(255), - PRIMARY KEY (id) -) ENGINE=InnoDB; - -CREATE TABLE airports ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - code VARCHAR(3) NOT NULL, - city VARCHAR(255) NOT NULL, - country VARCHAR(255) NOT NULL, - latitude FLOAT NOT NULL, - longitude FLOAT NOT NULL, - PRIMARY KEY (id) -) ENGINE=InnoDB; - -CREATE TABLE flights ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - airline_id INT UNSIGNED NOT NULL, - pilot_id INT UNSIGNED NOT NULL, - flight_no VARCHAR(10) NOT NULL, - origin_id INT UNSIGNED NOT NULL, - destination_id INT UNSIGNED NOT NULL, - departure_time DATETIME NOT NULL, - arrival_time DATETIME NOT NULL, - duration_minutes INT NOT NULL, - price_economy DECIMAL(10,2) NOT NULL, - price_business DECIMAL(10,2) NOT NULL, - price_first_class DECIMAL(10,2) NOT NULL, - status VARCHAR(255) NOT NULL, + user_bitfield INT UNSIGNED NOT NULL, + role_bitfield INT UNSIGNED NOT NULL, + verification_code_bitfield INT UNSIGNED NOT NULL, + ban_bitfield INT UNSIGNED NOT NULL, + patient_bitfield INT UNSIGNED NOT NULL, + doctor_bitfield INT UNSIGNED NOT NULL, + service_bitfield INT UNSIGNED NOT NULL, + company_bitfield INT UNSIGNED NOT NULL, + hospital_bitfield INT UNSIGNED NOT NULL, + room_bitfield INT UNSIGNED NOT NULL, + appointment_bitfield INT UNSIGNED NOT NULL, PRIMARY KEY (id), - CONSTRAINT fl_airline_id - FOREIGN KEY (airline_id) - REFERENCES airlines(id) - ON DELETE RESTRICT - ON UPDATE CASCADE, - CONSTRAINT fl_pilot_id - FOREIGN KEY (pilot_id) - REFERENCES pilots(id) - ON DELETE RESTRICT - ON UPDATE CASCADE, - CONSTRAINT fl_origin_id - FOREIGN KEY (origin_id) - REFERENCES airports(id) - ON DELETE RESTRICT - ON UPDATE CASCADE, - CONSTRAINT fl_destination_id - FOREIGN KEY (destination_id) - REFERENCES airports(id) - ON DELETE RESTRICT - ON UPDATE CASCADE + UNIQUE INDEX r_name_idx (name) ) ENGINE=InnoDB; -CREATE TABLE user_types ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - PRIMARY KEY (id), - UNIQUE INDEX ut_name_idx (name) -) ENGINE=InnoDB; - -INSERT INTO user_types (name) VALUES ('unverified'), ('customer'), ('support'), ('pilote'), ('staff'), ('admin'); - -CREATE TABLE permissions ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, - PRIMARY KEY (id), - UNIQUE INDEX p_name_idx (name) -) ENGINE=InnoDB; - -INSERT INTO permissions (name) VALUES -('view_users'), ('add_users'), ('edit_users'), ('delete_users'), -('view_flights'), ('add_flights'), ('edit_flights'), ('delete_flights'), -('view_airlines'), ('add_airlines'), ('edit_airlines'), ('delete_airlines'), -('view_airplanes'), ('add_airplanes'), ('edit_airplanes'), ('delete_airplanes'), -('view_airports'), ('add_airports'), ('edit_airports'), ('delete_airports'), -('view_seats'), ('add_seats'), ('edit_seats'), ('delete_seats'), -('view_pilots'), ('add_pilots'), ('edit_pilots'), ('delete_pilots'); - -CREATE TABLE user_type_permissions ( - id INT UNSIGNED NOT NULL AUTO_INCREMENT, - user_type_id INT UNSIGNED NOT NULL, - permission_id INT UNSIGNED NOT NULL, - PRIMARY KEY (id), - CONSTRAINT utp_user_type_id - FOREIGN KEY (user_type_id) - REFERENCES user_types(id) - ON DELETE CASCADE - ON UPDATE CASCADE, - CONSTRAINT utp_permission_id - FOREIGN KEY (permission_id) - REFERENCES permissions(id) - ON DELETE CASCADE - ON UPDATE CASCADE, - UNIQUE INDEX utp_user_type_permission_idx (user_type_id, permission_id) -) ENGINE=InnoDB; +INSERT INTO roles (name, user_bitfield, role_bitfield, verification_code_bitfield, ban_bitfield, patient_bitfield, doctor_bitfield, service_bitfield, company_bitfield, hospital_bitfield, room_bitfield, appointment_bitfield) VALUES + ('Admin', 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7), + ('Doctor', 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0), + ('Patient', 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0); CREATE TABLE users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, @@ -140,19 +40,31 @@ CREATE TABLE users ( username VARCHAR(64) NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(128) NOT NULL, + email_verified BOOLEAN NOT NULL DEFAULT FALSE, phone VARCHAR(32) DEFAULT 'None', - user_type_id INT UNSIGNED NOT NULL, - is_banned BOOLEAN NOT NULL DEFAULT 0, + phone_verified BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (id), - CONSTRAINT u_user_type_id - FOREIGN KEY (user_type_id) - REFERENCES user_types(id) - ON DELETE RESTRICT - ON UPDATE CASCADE, - INDEX ur_user_type_idx (user_type_id) ) ENGINE=InnoDB; -CREATE TABLE user_email_verifications ( +CREATE TABLE user_roles ( + user_id INT UNSIGNED NOT NULL, + role_id INT UNSIGNED NOT NULL, + PRIMARY KEY (user_id, role_id), + CONSTRAINT ur_user_id + FOREIGN KEY (user_id) + REFERENCES users(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ur_user_id_idx (user_id), + CONSTRAINT ur_role_id + FOREIGN KEY (role_id) + REFERENCES roles(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ur_role_id_idx (role_id) +) ENGINE=InnoDB; + +CREATE TABLE verification_codes ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, user_id INT UNSIGNED NOT NULL, verification_code VARCHAR(255), @@ -167,108 +79,169 @@ CREATE TABLE user_email_verifications ( INDEX mv_user_id_idx (user_id) ) ENGINE=InnoDB; -CREATE TABLE seats ( +CREATE TABLE bans ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, - user_id INT UNSIGNED, - flight_id INT UNSIGNED NOT NULL, - place_no INT UNSIGNED NOT NULL, - class VARCHAR(32) NOT NULL, - bought_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + user_id INT UNSIGNED NOT NULL, + reason TEXT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), - CONSTRAINT ps_user_id + CONSTRAINT bn_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT ON UPDATE CASCADE, - CONSTRAINT ps_flight_id - FOREIGN KEY (flight_id) - REFERENCES flights(id) - ON DELETE RESTRICT - ON UPDATE CASCADE, - INDEX ps_user_id_idx (user_id), - INDEX ps_flight_id_idx (flight_id) + INDEX bn_user_id_idx (user_id) ) ENGINE=InnoDB; -INSERT INTO pilots (id, first_name, last_name, email, phone, license_number, license_expiry, salary, status) VALUES -(1, 'John', 'Doe', 'john.doe@example.com', '555-1234', '1234-5678', '2025-06-30', 75000.00, 'Active'), -(2, 'Jane', 'Smith', 'jane.smith@example.com', '555-5678', '9876-5432', '2024-12-31', 80000.00, 'Active'), -(3, 'Bob', 'Johnson', 'bob.johnson@example.com', '555-7890', '3456-7890', '2023-09-30', 70000.00, 'Inactive'), -(4, 'Alice', 'Lee', 'alice.lee@example.com', '555-2345', '5678-1234', '2024-03-31', 85000.00, 'Active'), -(5, 'David', 'Nguyen', 'david.nguyen@example.com', '555-5678', '1234-5678', '2023-12-31', 75000.00, 'Active'), -(6, 'Maria', 'Garcia', 'maria.garcia@example.com', '555-7890', '9876-5432', '2024-06-30', 70000.00, 'Active'), -(7, 'Mohammed', 'Ali', 'mohammed.ali@example.com', '555-2345', '3456-7890', '2025-09-30', 85000.00, 'Inactive'), -(8, 'Sofia', 'Martinez', 'sofia.martinez@example.com', '555-3456', '5678-1234', '2022-03-31', 80000.00, 'Active'); +CREATE TABLE doctors ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + user_id INT UNSIGNED NOT NULL, + email VARCHAR(255) NOT NULL, + phone VARCHAR(20) NOT NULL, + speciality VARCHAR(255) NOT NULL, + status VARCHAR(255) NOT NULL, + PRIMARY KEY (id), + CONSTRAINT dt_user_id + FOREIGN KEY (user_id) + REFERENCES users(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX dt_user_id_idx (user_id) +) ENGINE=InnoDB; -INSERT INTO airplanes (id, name, type, manufacturer, capacity, status, location) VALUES -(1, 'Boeing 747', 'Jet', 'Boeing', 660, 'Active', 'Los Angeles'), -(2, 'Airbus A320', 'Jet', 'Airbus', 180, 'Active', 'New York'), -(3, 'Embraer E175', 'Jet', 'Embraer', 78, 'Inactive', 'Miami'), -(4, 'Boeing 737', 'Jet', 'Boeing', 160, 'Active', 'Chicago'), -(5, 'Airbus A330', 'Jet', 'Airbus', 440, 'Active', 'Paris'), -(6, 'Bombardier CRJ900', 'Jet', 'Bombardier', 88, 'Active', 'Montreal'), -(7, 'Boeing 777', 'Jet', 'Boeing', 396, 'Inactive', 'London'), -(8, 'Airbus A380', 'Jet', 'Airbus', 853, 'Active', 'Dubai'), -(9, 'Embraer E190', 'Jet', 'Embraer', 114, 'Active', 'Buenos Aires'), -(10, 'Boeing 787', 'Jet', 'Boeing', 335, 'Active', 'Tokyo'), -(11, 'Boeing 747-8', 'Jet', 'Boeing', 605, 'Active', 'Hong Kong'), -(12, 'Airbus A350', 'Jet', 'Airbus', 440, 'Active', 'Dublin'), -(13, 'Embraer E195', 'Jet', 'Embraer', 124, 'Inactive', 'Rio de Janeiro'), -(14, 'Boeing 737 MAX', 'Jet', 'Boeing', 230, 'Active', 'Seattle'), -(15, 'Airbus A321', 'Jet', 'Airbus', 236, 'Active', 'Shanghai'); +CREATE TABLE patients ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + user_id INT UNSIGNED NOT NULL, + date_of_birth DATE NOT NULL, + gender ENUM('M', 'F', 'O') NOT NULL, + address VARCHAR(255) NOT NULL, + social_security_number VARCHAR(128) NOT NULL, + insurance_number VARCHAR(128) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB; -INSERT INTO airlines (id, name, code, logo) VALUES -(1, 'Delta Air Lines', 'DL', 'https://www.delta.com/content/dam/delta-com/brand-icons/Delta_Icon_blue_72.png'), -(2, 'American Airlines', 'AA', 'https://www.aa.com/content/dam/aa-com/logo-web/aa-logo-blue-and-red-horz.png'), -(3, 'United Airlines', 'UA', 'https://www.united.com/web/en-US/content/images/global/header/header-united-logo.png'), -(4, 'Southwest Airlines', 'WN', 'https://www.southwest.com/etc/designs/southwest/v2/images/swa-logo--mod.svg'), -(5, 'Alaska Airlines', 'AS', 'https://www.alaskaair.com/content/dam/alaskaair/logo/2016/alaska-airlines-horiz-white-blue-1x.png'), -(6, 'JetBlue Airways', 'B6', 'https://www.jetblue.com/etc/designs/jetblue/clientlibs/dist/images/svg/jetblue-logo.svg'), -(7, 'Spirit Airlines', 'NK', 'https://www.spirit.com/images/spirit-logo.png'), -(8, 'Frontier Airlines', 'F9', 'https://www.flyfrontier.com/etc/designs/frontier-airlines/clientlibs/dist/images/f9-logo-horz.svg'), -(9, 'Air France', 'AF', 'https://www.airfrance.com/etc/designs/airfrance/clientlibs/dist/images/global/logo/airfrance-logo-blue.svg'), -(10, 'Transavia France', 'TO', 'https://www.transavia.com/content/dam/airlines/tv/fra/fr/common/img/logo.svg'), -(11, 'EasyJet France', 'U2', 'https://www.easyjet.com/etc/designs/easyjet/clientlibs/dist/images/logo.svg'), -(12, 'Corsair International', 'SS', 'https://www.corsair.fr/etc/designs/corsair/clientlibs/dist/images/logo.svg'), -(13, 'XL Airways France', 'SE', 'https://www.xl.com/assets/images/XL-logo.png'), -(14, 'Aigle Azur', 'ZI', 'https://www.aigle-azur.com/site/sites/all/themes/aigle-azur/images/logo-aigle-azur-160x80.png'); +CREATE TABLE services ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + description TEXT NOT NULL, + price DECIMAL(10, 2) NOT NULL, + status VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB; -INSERT INTO airports (id, name, code, city, country, latitude, longitude) VALUES -(1, 'John F. Kennedy International Airport', 'JFK', 'New York', 'United States', 40.6413, -73.7781), -(2, 'Los Angeles International Airport', 'LAX', 'Los Angeles', 'United States', 33.9416, -118.4085), -(3, 'London Heathrow Airport', 'LHR', 'London', 'United Kingdom', 51.4700, -0.4543), -(4, 'Paris-Charles de Gaulle Airport', 'CDG', 'Paris', 'France', 49.0097, 2.5479), -(5, 'Tokyo Haneda Airport', 'HND', 'Tokyo', 'Japan', 35.5532, 139.7818), -(6, 'Dubai International Airport', 'DXB', 'Dubai', 'United Arab Emirates', 25.2528, 55.3644), -(7, 'Sydney Kingsford Smith Airport', 'SYD', 'Sydney', 'Australia', -33.9461, 151.1772), -(8, 'São Paulo-Guarulhos International Airport', 'GRU', 'São Paulo', 'Brazil', -23.4356, -46.4731), -(9, 'Jomo Kenyatta International Airport', 'NBO', 'Nairobi', 'Kenya', -1.3192, 36.9258), -(10, 'Cairo International Airport', 'CAI', 'Cairo', 'Egypt', 30.1111, 31.4139), -(11, 'Paris Orly Airport', 'ORY', 'Paris', 'France', 48.7262, 2.3650), -(12, 'Nice Côte d''Azur Airport', 'NCE', 'Nice', 'France', 43.6584, 7.2157), -(13, 'Marseille Provence Airport', 'MRS', 'Marseille', 'France', 43.4393, 5.2214), -(14, 'Lyon-Saint-Exupéry Airport', 'LYS', 'Lyon', 'France', 45.7216, 5.0790), -(15, 'Bordeaux-Mérignac Airport', 'BOD', 'Bordeaux', 'France', 44.8283, -0.7156), -(16, 'Toulouse-Blagnac Airport', 'TLS', 'Toulouse', 'France', 43.6356, 1.3678), -(17, 'Nantes Atlantique Airport', 'NTE', 'Nantes', 'France', 47.1567, -1.6114), -(18, 'Strasbourg Airport', 'SXB', 'Strasbourg', 'France', 48.5442, 7.6277), -(19, 'Lille Airport', 'LIL', 'Lille', 'France', 50.5633, 3.0897), -(20, 'Brest Bretagne Airport', 'BES', 'Brest', 'France', 48.4472, -4.4228), -(21, 'Vienna International Airport', 'VIE', 'Vienna', 'Austria', 48.1197, 16.5667), -(22, 'Zürich Airport', 'ZRH', 'Zürich', 'Switzerland', 47.4502, 8.5618), -(23, 'Amsterdam Airport Schiphol', 'AMS', 'Amsterdam', 'Netherlands', 52.3081, 4.7642), -(24, 'Frankfurt Airport', 'FRA', 'Frankfurt', 'Germany', 50.0379, 8.5622), -(25, 'Barcelona-El Prat Airport', 'BCN', 'Barcelona', 'Spain', 41.2974, 2.0833), -(26, 'Adolfo Suárez Madrid-Barajas Airport', 'MAD', 'Madrid', 'Spain', 40.4936, -3.5668), -(27, 'Leonardo da Vinci-Fiumicino Airport', 'FCO', 'Rome', 'Italy', 41.8003, 12.2388), -(28, 'Stockholm Arlanda Airport', 'ARN', 'Stockholm', 'Sweden', 59.6519, 17.9186); +CREATE TABLE service_doctors ( + service_id INT UNSIGNED NOT NULL, + doctor_id INT UNSIGNED NOT NULL, + PRIMARY KEY (service_id, doctor_id), + CONSTRAINT sd_service_id + FOREIGN KEY (service_id) + REFERENCES services(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX sd_service_id_idx (service_id), + CONSTRAINT sd_doctor_id + FOREIGN KEY (doctor_id) + REFERENCES doctors(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX sd_doctor_id_idx (doctor_id) +) ENGINE=InnoDB; -INSERT INTO flights (id, airline_id, pilot_id, flight_no, origin_id, destination_id, departure_time, arrival_time, duration_minutes, price_economy, price_business, price_first_class, status) VALUES -(1, 1, 1, 'BA123', 1, 2, '2023-03-15 08:00:00', '2023-03-15 10:00:00', 120, 100, 200, 300, 'scheduled'), -(2, 2, 2, 'AF456', 2, 3, '2023-03-16 14:00:00', '2023-03-16 16:30:00', 150, 80, 150, 250, 'scheduled'), -(3, 3, 3, 'LH789', 4, 5, '2023-03-17 09:30:00', '2023-03-17 12:00:00', 150, 90, 170, 280, 'scheduled'), -(4, 1, 4, 'BA345', 2, 5, '2023-03-18 07:00:00', '2023-03-18 10:00:00', 180, 120, 240, 400, 'scheduled'), -(5, 4, 5, 'EZY678', 3, 1, '2023-03-19 11:00:00', '2023-03-19 13:00:00', 120, 60, 120, 200, 'scheduled'), -(6, 2, 6, 'AF901', 5, 6, '2023-03-20 16:30:00', '2023-03-20 19:00:00', 150, 100, 200, 350, 'scheduled'); +CREATE TABLE companies ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + code VARCHAR(2) NOT NULL, + logo VARCHAR(255), + PRIMARY KEY (id) +) ENGINE=InnoDB; -INSERT INTO `user_type_permissions` (`user_type_id`, `permission_id`) VALUES -('6', '1'),('6', '2'),('6', '3'),('6', '4'),('6', '5'),('6', '6'),('6', '7'),('6', '8'),('6', '9'),('6', '10'),('6', '11'),('6', '12'),('6', '13'),('6', '14'),('6', '15'),('6', '16'),('6', '17'),('6', '18'),('6', '19'),('6', '20'),('6', '21'),('6', '22'),('6', '23'),('6', '24'),('6', '25'),('6', '26'),('6', '27'),('6', '28'); \ No newline at end of file +CREATE TABLE hospitals ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + company_id INT UNSIGNED NOT NULL, + name VARCHAR(255) NOT NULL, + code VARCHAR(3) NOT NULL, + country VARCHAR(255) NOT NULL, + region VARCHAR(255) NOT NULL, + city VARCHAR(255) NOT NULL, + address VARCHAR(255) NOT NULL, + PRIMARY KEY (id), + CONSTRAINT hs_company_id + FOREIGN KEY (company_id) + REFERENCES companies(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX hs_company_id_idx (company_id) +) ENGINE=InnoDB; + +CREATE TABLE rooms ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + hospital_id INT UNSIGNED NOT NULL, + name VARCHAR(255) NOT NULL, + PRIMARY KEY (id) + CONSTRAINT ch_hospital_id + FOREIGN KEY (hospital_id) + REFERENCES hospitals(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, +) ENGINE=InnoDB; + +CREATE TABLE hospital_doctors ( + hospital_id INT UNSIGNED NOT NULL, + doctor_id INT UNSIGNED NOT NULL, + PRIMARY KEY (hospital_id, doctor_id), + CONSTRAINT hd_hospital_id + FOREIGN KEY (hospital_id) + REFERENCES hospitals(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX hd_hospital_id_idx (hospital_id), + CONSTRAINT hd_doctor_id + FOREIGN KEY (doctor_id) + REFERENCES doctors(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX hd_doctor_id_idx (doctor_id) +) ENGINE=InnoDB; + +CREATE TABLE appointments ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + patient_id INT UNSIGNED NOT NULL, + doctor_id INT UNSIGNED NOT NULL, + service_id INT UNSIGNED NOT NULL, + hospital_id INT UNSIGNED DEFAULT NULL, + room_id INT UNSIGNED DEFAULT NULL, + date DATE NOT NULL, + time TIME NOT NULL, + status VARCHAR(255) NOT NULL, + PRIMARY KEY (id) + CONSTRAINT ap_patient_id + FOREIGN KEY (patient_id) + REFERENCES patients(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ap_patient_id_idx (patient_id), + CONSTRAINT ap_doctor_id + FOREIGN KEY (doctor_id) + REFERENCES doctors(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ap_doctor_id_idx (doctor_id), + CONSTRAINT ap_service_id + FOREIGN KEY (service_id) + REFERENCES services(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ap_service_id_idx (service_id), + CONSTRAINT ap_hospital_id + FOREIGN KEY (hospital_id) + REFERENCES hospitals(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ap_hospital_id_idx (hospital_id), + CONSTRAINT ap_room_id + FOREIGN KEY (room_id) + REFERENCES rooms(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + INDEX ap_room_id_idx (room_id) +) ENGINE=InnoDB; \ No newline at end of file diff --git a/index.js b/index.js index a887282..e24077a 100644 --- a/index.js +++ b/index.js @@ -5,17 +5,19 @@ import logger from 'morgan'; import express from 'express'; import cookieParser from 'cookie-parser'; -import { log } from './modules/log'; +import { log } from './modules/logManager'; import { speedLimiter, checkSystemLoad } from './modules/requestHandler'; import testRouter from './routes/test'; import usersRouter from './routes/users'; -import pilotsRouter from './routes/pilots'; -import airplanesRouter from './routes/airplanes'; -import airlinesRouter from './routes/airlines'; -import airportsRouter from './routes/airports'; -import flightsRouter from './routes/flights'; -import seatsRouter from './routes/seats'; +import doctorsRouter from './routes/doctors'; +import patientsRouter from './routes/patients'; +import companiesRouter from './routes/companies'; +import hospitalsRouter from './routes/hospitals'; + +// create logs directory if it doesn't exist +const logsDir = path.join(import.meta.dir, 'logs'); +if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir); const app = express(); app.set('trust proxy', 1); @@ -25,7 +27,7 @@ app.use(cookieParser()); app.use(speedLimiter); app.use(checkSystemLoad); app.use(logger('dev')); -app.use(logger('combined', { stream: fs.createWriteStream(path.join(__dirname, 'logs/access.log'), { flags: 'a' }) })); +app.use(logger('combined', { stream: fs.createWriteStream(path.join(import.meta.dir, 'logs/access.log'), { flags: 'a' }) })); app.use(cors({ origin: '*', })); @@ -35,12 +37,10 @@ app.use(express.static('public')); // routes app.use('/api/test', testRouter); app.use('/api/users', usersRouter); -app.use('/api/pilots', pilotsRouter); -app.use('/api/airplanes', airplanesRouter); -app.use('/api/airlines', airlinesRouter); -app.use('/api/airports', airportsRouter); -app.use('/api/flights', flightsRouter); -app.use('/api/seats', seatsRouter); +app.use('/api/doctors', doctorsRouter); +app.use('/api/patients', patientsRouter); +app.use('/api/companies', companiesRouter); +app.use('/api/hospitals', hospitalsRouter); // run the API app.listen(process.env.PORT, async () => { 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

- + - + - +