Updating backend
- Added database self check - Added more @me handlers - Fixed issues
This commit is contained in:
980
database.json
Normal file
980
database.json
Normal file
@@ -0,0 +1,980 @@
|
||||
{
|
||||
"tables": [
|
||||
{
|
||||
"name": "roles",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"UNIQUE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "user_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "role_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "verification_code_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ban_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patient_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "doctor_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "company_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hospital_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "room_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appointment_bitfield",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"name": "Admin",
|
||||
"user_bitfield": 7,
|
||||
"role_bitfield": 7,
|
||||
"verification_code_bitfield": 7,
|
||||
"ban_bitfield": 7,
|
||||
"patient_bitfield": 7,
|
||||
"doctor_bitfield": 7,
|
||||
"service_bitfield": 7,
|
||||
"company_bitfield": 7,
|
||||
"hospital_bitfield": 7,
|
||||
"room_bitfield": 7,
|
||||
"appointment_bitfield": 7
|
||||
},
|
||||
{
|
||||
"name": "Doctor",
|
||||
"user_bitfield": 0,
|
||||
"role_bitfield": 0,
|
||||
"verification_code_bitfield": 0,
|
||||
"ban_bitfield": 0,
|
||||
"patient_bitfield": 1,
|
||||
"doctor_bitfield": 1,
|
||||
"service_bitfield": 1,
|
||||
"company_bitfield": 1,
|
||||
"hospital_bitfield": 1,
|
||||
"room_bitfield": 1,
|
||||
"appointment_bitfield": 0
|
||||
},
|
||||
{
|
||||
"name": "Patient",
|
||||
"user_bitfield": 0,
|
||||
"role_bitfield": 0,
|
||||
"verification_code_bitfield": 0,
|
||||
"ban_bitfield": 0,
|
||||
"patient_bitfield": 0,
|
||||
"doctor_bitfield": 1,
|
||||
"service_bitfield": 1,
|
||||
"company_bitfield": 1,
|
||||
"hospital_bitfield": 1,
|
||||
"room_bitfield": 1,
|
||||
"appointment_bitfield": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "users",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "first_name",
|
||||
"type": "VARCHAR(64)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "last_name",
|
||||
"type": "VARCHAR(64)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"type": "VARCHAR(64)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"type": "VARCHAR(128)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "email_verified",
|
||||
"type": "BOOLEAN",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT FALSE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "phone",
|
||||
"type": "VARCHAR(32)",
|
||||
"constraints": [
|
||||
"DEFAULT 'None'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "phone_verified",
|
||||
"type": "BOOLEAN",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT FALSE"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "user_roles",
|
||||
"columns": [
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "role_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"primary_key": true,
|
||||
"columns": ["user_id", "role_id"]
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "user_roles_user_id",
|
||||
"column": "user_id",
|
||||
"reference": "users(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "user_roles_role_id",
|
||||
"column": "role_id",
|
||||
"reference": "roles(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "user_roles_user_idx",
|
||||
"columns": ["user_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "user_roles_role_idx",
|
||||
"columns": ["role_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "verification_codes",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "verification_code",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"type": "VARCHAR(32)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"type": "TIMESTAMP",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT CURRENT_TIMESTAMP"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "verification_codes_user_id",
|
||||
"column": "user_id",
|
||||
"reference": "users(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "verification_codes_user_idx",
|
||||
"columns": ["user_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bans",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "reason",
|
||||
"type": "TEXT",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"type": "TIMESTAMP",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT CURRENT_TIMESTAMP"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "bans_user_id",
|
||||
"column": "user_id",
|
||||
"reference": "users(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "bans_user_idx",
|
||||
"columns": ["user_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "doctors",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"UNIQUE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "phone",
|
||||
"type": "VARCHAR(20)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "specialty",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"type": "ENUM('Available', 'Absent', 'Unavailable')",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT 'Available'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "is_verified",
|
||||
"type": "BOOLEAN",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"DEFAULT FALSE"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "doctors_user_id",
|
||||
"column": "user_id",
|
||||
"reference": "users(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "doctors_user_idx",
|
||||
"columns": ["user_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patients",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "user_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"UNIQUE"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "date_of_birth",
|
||||
"type": "DATE",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gender",
|
||||
"type": "ENUM('M', 'F', 'O')",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "address",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "social_security_number",
|
||||
"type": "VARCHAR(128)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "insurance_number",
|
||||
"type": "VARCHAR(128)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "patients_user_id",
|
||||
"column": "user_id",
|
||||
"reference": "users(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "patients_user_idx",
|
||||
"columns": ["user_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "services",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"type": "TEXT",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "price",
|
||||
"type": "DECIMAL(10, 2)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_doctors",
|
||||
"columns": [
|
||||
{
|
||||
"name": "service_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "doctor_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"primary_key": true,
|
||||
"columns": ["service_id", "doctor_id"]
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "service_doctors_service_id",
|
||||
"column": "service_id",
|
||||
"reference": "services(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "service_doctors_doctor_id",
|
||||
"column": "doctor_id",
|
||||
"reference": "doctors(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "service_doctors_service_idx",
|
||||
"columns": ["service_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "service_doctors_doctor_idx",
|
||||
"columns": ["doctor_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "companies",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "code",
|
||||
"type": "VARCHAR(2)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "logo",
|
||||
"type": "VARCHAR(255)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hospitals",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "company_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "code",
|
||||
"type": "VARCHAR(3)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "country",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "region",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "city",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "address",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "hospitals_company_id",
|
||||
"column": "company_id",
|
||||
"reference": "companies(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "hospitals_company_idx",
|
||||
"columns": ["company_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "rooms",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "hospital_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "VARCHAR(255)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "code",
|
||||
"type": "VARCHAR(3)",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "floor",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "room_number",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "room_type",
|
||||
"type": "ENUM('General Ward', 'Private', 'Intensive Care Unit', 'Labor and Delivery', 'Operating', 'Recovery', 'Isolation', 'Emergency', 'Imaging', 'Procedure', 'Physical Therapy', 'Consultation')",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "rooms_hospital_id",
|
||||
"column": "hospital_id",
|
||||
"reference": "hospitals(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "rooms_hospital_idx",
|
||||
"columns": ["hospital_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hospital_doctors",
|
||||
"columns": [
|
||||
{
|
||||
"name": "hospital_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "doctor_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"primary_key": true,
|
||||
"columns": ["hospital_id", "doctor_id"]
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "hospital_doctors_hospital_id",
|
||||
"column": "hospital_id",
|
||||
"reference": "hospitals(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "hospital_doctors_doctor_id",
|
||||
"column": "doctor_id",
|
||||
"reference": "doctors(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "hospital_doctors_hospital_idx",
|
||||
"columns": ["hospital_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "hospital_doctors_doctor_idx",
|
||||
"columns": ["doctor_id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "appointments",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL",
|
||||
"AUTO_INCREMENT"
|
||||
],
|
||||
"primary_key": true
|
||||
},
|
||||
{
|
||||
"name": "patient_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "doctor_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hospital_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"DEFAULT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "room_id",
|
||||
"type": "INT UNSIGNED",
|
||||
"constraints": [
|
||||
"DEFAULT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "date",
|
||||
"type": "DATE",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"type": "TIME",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"type": "ENUM('Confirmed', 'Completed', 'Absent', 'Cancelled by Patient', 'Cancelled by Doctor')",
|
||||
"constraints": [
|
||||
"NOT NULL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "appointments_patient_id",
|
||||
"column": "patient_id",
|
||||
"reference": "patients(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "appointments_doctor_id",
|
||||
"column": "doctor_id",
|
||||
"reference": "doctors(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "appointments_service_id",
|
||||
"column": "service_id",
|
||||
"reference": "services(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "appointments_hospital_id",
|
||||
"column": "hospital_id",
|
||||
"reference": "hospitals(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"foreign_key": true,
|
||||
"name": "appointments_room_id",
|
||||
"column": "room_id",
|
||||
"reference": "rooms(id)",
|
||||
"on_delete": "RESTRICT",
|
||||
"on_update": "CASCADE"
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "appointments_patient_idx",
|
||||
"columns": ["patient_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "appointments_doctor_idx",
|
||||
"columns": ["doctor_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "appointments_service_idx",
|
||||
"columns": ["service_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "appointments_hospital_idx",
|
||||
"columns": ["hospital_id"]
|
||||
},
|
||||
{
|
||||
"index": true,
|
||||
"name": "appointments_room_idx",
|
||||
"columns": ["room_id"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import mysql from 'mysql2';
|
||||
import dbconf from '../database.json';
|
||||
import { log } from './logManager';
|
||||
|
||||
const connection = mysql.createConnection({
|
||||
host: process.env.DATABASE_HOST,
|
||||
@@ -23,4 +25,58 @@ function createPool(host, user, password, db) {
|
||||
return newPool;
|
||||
}
|
||||
|
||||
export { connection, pool, createPool };
|
||||
function databaseSelfTest() {
|
||||
log('Database self-test');
|
||||
dbconf.tables.forEach(table => {
|
||||
let query = `CREATE TABLE IF NOT EXISTS ${table.name} (`;
|
||||
table.columns.forEach((column, index) => {
|
||||
query += `${column.name} ${column.type}`;
|
||||
if (column.primary_key) query += ' PRIMARY KEY';
|
||||
if (column.constraints && column.constraints.length > 0) query += ` ${column.constraints.join(' ')}`;
|
||||
if (column.index) query += `, INDEX ${column.name}_idx (${column.name})`;
|
||||
if (index < table.columns.length - 1) query += ', ';
|
||||
});
|
||||
if (table.constraints && table.constraints.length > 0) {
|
||||
table.constraints.forEach(constraint => {
|
||||
setTimeout(() => { // do not remove or it breaks /sarcasm
|
||||
if (constraint.primary_key) query += `, PRIMARY KEY (${constraint.columns.join(', ')})`;
|
||||
if (constraint.foreign_key) query += `, CONSTRAINT ${constraint.name} FOREIGN KEY (${constraint.column}) REFERENCES ${constraint.reference} ON DELETE ${constraint.on_delete} ON UPDATE ${constraint.on_update}`;
|
||||
if (constraint.index) query += `, INDEX ${constraint.name} (${constraint.columns.join(', ')})`;
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
query += ') ENGINE=InnoDB;';
|
||||
pool.query(query)
|
||||
.then(() => log(`Table ${table.name} validated`))
|
||||
.catch(err => console.log(`Error creating table ${table.name}: ${err}`));
|
||||
|
||||
if (table.data) {
|
||||
pool.query(`SELECT * FROM ${table.name}`)
|
||||
.then(([rows]) => {
|
||||
if (rows.length === 0) {
|
||||
table.data.forEach(row => {
|
||||
let insertQuery = `INSERT INTO ${table.name} (`;
|
||||
let values = 'VALUES (';
|
||||
Object.keys(row).forEach((key, index) => {
|
||||
insertQuery += key;
|
||||
values += `'${row[key]}'`;
|
||||
if (index < Object.keys(row).length - 1) {
|
||||
insertQuery += ', ';
|
||||
values += ', ';
|
||||
}
|
||||
});
|
||||
insertQuery += ') ' + values + ');';
|
||||
pool.query(insertQuery)
|
||||
.then(() => log(`Row inserted in table ${table.name}`))
|
||||
.catch(err => log(`Error inserting row in table ${table.name}: ${err}`));
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => log(`Error checking if table ${table.name} is empty: ${err}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
databaseSelfTest();
|
||||
|
||||
export { connection, pool, createPool, databaseSelfTest };
|
||||
|
||||
@@ -47,7 +47,6 @@ export async function verifyPermissions(userId, permissionName, permissionType)
|
||||
}
|
||||
|
||||
export async function checkIfUserEmailIsVerified(userId) {
|
||||
return true;
|
||||
try {
|
||||
const [user] = await pool.execute('SELECT email_verified FROM users WHERE id = ? LIMIT 1', [userId]);
|
||||
if (user.length === 0) return false;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
"node-cron": "^3.0.3",
|
||||
"nodemailer": "^6.9.10",
|
||||
"path": "^0.12.7",
|
||||
"pino": "^8.16.2",
|
||||
"pino-pretty": "^11.0.0"
|
||||
"pino": "^8.16.2"
|
||||
}
|
||||
}
|
||||
@@ -244,6 +244,7 @@ router.patch('/password/verify', antiVerificationSpam, async (req, res) => {
|
||||
|
||||
router.get('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 1)) return await respondWithStatus(res, 403, 'Missing permission');
|
||||
const [rows] = await pool.execute('SELECT id, first_name, last_name, username, email, phone FROM users WHERE id = ? LIMIT 1', [req.params.userId]);
|
||||
if (rows.length === 0) return await respondWithStatus(res, 404, 'User not found');
|
||||
@@ -260,6 +261,7 @@ router.get('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
|
||||
router.patch('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 2)) return await respondWithStatus(res, 403, 'Missing permission');
|
||||
const { type } = req.body;
|
||||
let { value } = req.body;
|
||||
@@ -285,6 +287,7 @@ router.patch('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
|
||||
router.put('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 2)) return await respondWithStatus(res, 403, 'Missing permission');
|
||||
const { first_name, last_name, username, password = null, email, phone = null } = req.body;
|
||||
if ([first_name, last_name, username, email].every(Boolean)) {
|
||||
@@ -313,6 +316,7 @@ router.put('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
|
||||
router.delete('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 4)) return await respondWithStatus(res, 403, 'Missing permission');
|
||||
if (!userExists(req.params.userId)) return await respondWithStatus(res, 404, 'User not found');
|
||||
const [result] = await pool.execute('DELETE FROM users WHERE id = ?', [ req.params.userId ]);
|
||||
@@ -327,9 +331,7 @@ router.delete('/:userId', verifyToken, checkBanned, async (req, res) => {
|
||||
|
||||
router.get('/:userId/roles', verifyToken, checkBanned, async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') {
|
||||
req.params.userId = req.userId;
|
||||
}
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
if (req.params.userId != req.userId && !verifyPermissions(req.userId, 'user', 1)) return await respondWithStatus(res, 403, 'Missing permission');
|
||||
const [rows] = await pool.execute('SELECT r.* 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 = ?', [ req.params.userId ]);
|
||||
if (rows.length === 0) return await respondWithStatus(res, 404, 'No roles found');
|
||||
@@ -345,6 +347,7 @@ router.post('/:userId/roles', verifyToken, checkBanned, checkPermissions('user',
|
||||
const { roleId } = req.body;
|
||||
if (roleId) {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
const [rows] = await pool.execute('SELECT * FROM roles WHERE id = ? LIMIT 1', [ roleId ]);
|
||||
if (rows.length === 0) return await respondWithStatus(res, 404, 'Role not found');
|
||||
const [result] = await pool.execute('INSERT INTO user_roles (user_id, role_id) VALUES (?, ?)', [ req.params.userId, roleId ]);
|
||||
@@ -363,6 +366,7 @@ router.post('/:userId/roles', verifyToken, checkBanned, checkPermissions('user',
|
||||
|
||||
router.delete('/:userId/roles/:roleId', verifyToken, checkBanned, checkPermissions('user', 4), async (req, res) => {
|
||||
try {
|
||||
if (req.params.userId == '@me') req.params.userId = req.userId;
|
||||
const [result] = await pool.execute('DELETE FROM user_roles WHERE user_id = ? AND role_id = ?', [ req.params.userId, req.params.roleId ]);
|
||||
if (result.affectedRows === 0) return await respondWithStatus(res, 500, 'Error removing role');
|
||||
return await respondWithStatus(res, 200, 'Role removed successfully');
|
||||
|
||||
Reference in New Issue
Block a user