-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path06_auth_and_triggers.sql
More file actions
390 lines (348 loc) · 14.2 KB
/
06_auth_and_triggers.sql
File metadata and controls
390 lines (348 loc) · 14.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
-- AUTHENTICATION AND TRIGGERS
-- For University Health Clinic EMR Project
USE university_health_clinic;
-- USER AUTHENTICATION SYSTEM
-- Create users table if not already created
CREATE TABLE IF NOT EXISTS Users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
provider_id INT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
last_login DATETIME NULL,
active BOOLEAN DEFAULT TRUE,
CONSTRAINT fk_user_provider FOREIGN KEY (provider_id)
REFERENCES Provider(provider_id)
ON DELETE SET NULL
);
-- Create roles table if not already created
CREATE TABLE IF NOT EXISTS Roles (
role_id INT AUTO_INCREMENT PRIMARY KEY,
role_name VARCHAR(50) NOT NULL UNIQUE,
description TEXT
);
-- Create user_roles junction table if not already created
CREATE TABLE IF NOT EXISTS UserRoles (
user_id INT NOT NULL,
role_id INT NOT NULL,
granted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
granted_by INT,
PRIMARY KEY (user_id, role_id),
CONSTRAINT fk_userrole_user FOREIGN KEY (user_id)
REFERENCES Users(user_id)
ON DELETE CASCADE,
CONSTRAINT fk_userrole_role FOREIGN KEY (role_id)
REFERENCES Roles(role_id)
ON DELETE CASCADE,
CONSTRAINT fk_userrole_granter FOREIGN KEY (granted_by)
REFERENCES Users(user_id)
ON DELETE SET NULL
);
-- Create permissions table if not already created
CREATE TABLE IF NOT EXISTS Permissions (
permission_id INT AUTO_INCREMENT PRIMARY KEY,
permission_name VARCHAR(100) NOT NULL UNIQUE,
description TEXT
);
-- Create role_permissions junction table if not already created
CREATE TABLE IF NOT EXISTS RolePermissions (
role_id INT NOT NULL,
permission_id INT NOT NULL,
PRIMARY KEY (role_id, permission_id),
CONSTRAINT fk_roleperm_role FOREIGN KEY (role_id)
REFERENCES Roles(role_id)
ON DELETE CASCADE,
CONSTRAINT fk_roleperm_permission FOREIGN KEY (permission_id)
REFERENCES Permissions(permission_id)
ON DELETE CASCADE
);
-- Create session management table if not already created
CREATE TABLE IF NOT EXISTS UserSessions (
session_id VARCHAR(64) PRIMARY KEY,
user_id INT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME NOT NULL,
ip_address VARCHAR(45),
user_agent TEXT,
CONSTRAINT fk_session_user FOREIGN KEY (user_id)
REFERENCES Users(user_id)
ON DELETE CASCADE
);
-- Create user activity log if not already created
CREATE TABLE IF NOT EXISTS UserActivityLog (
log_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
activity_type VARCHAR(50) NOT NULL,
entity_type VARCHAR(50),
entity_id INT,
activity_details TEXT,
ip_address VARCHAR(45),
activity_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_activitylog_user FOREIGN KEY (user_id)
REFERENCES Users(user_id)
ON DELETE SET NULL
);
-- Insert default roles if they don't exist
INSERT IGNORE INTO Roles (role_name, description) VALUES
('Administrator', 'System administrator with full access to all functions'),
('Doctor', 'Medical provider with access to clinical functions'),
('Nurse', 'Nursing staff with limited clinical access'),
('Receptionist', 'Front desk staff for scheduling and check-in'),
('Billing', 'Billing department staff for financial operations');
-- Insert default permissions if they don't exist
INSERT IGNORE INTO Permissions (permission_name, description) VALUES
('patient:view', 'View patient information'),
('patient:add', 'Add new patients'),
('patient:edit', 'Edit patient information'),
('appointment:view', 'View appointments'),
('appointment:schedule', 'Schedule appointments'),
('appointment:cancel', 'Cancel appointments'),
('visit:record', 'Record patient visits'),
('diagnosis:add', 'Add diagnoses'),
('prescription:add', 'Add prescriptions'),
('labtest:order', 'Order lab tests'),
('billing:view', 'View billing information'),
('billing:add', 'Create billing records'),
('billing:process', 'Process payments'),
('report:run', 'Run system reports'),
('user:manage', 'Manage system users');
-- Assign permissions to roles if not already assigned
-- Administrator permissions (all)
INSERT IGNORE INTO RolePermissions
SELECT (SELECT role_id FROM Roles WHERE role_name = 'Administrator'), permission_id
FROM Permissions;
-- Doctor permissions
INSERT IGNORE INTO RolePermissions
SELECT (SELECT role_id FROM Roles WHERE role_name = 'Doctor'), permission_id
FROM Permissions
WHERE permission_name IN (
'patient:view', 'patient:edit', 'appointment:view', 'appointment:schedule',
'appointment:cancel', 'visit:record', 'diagnosis:add', 'prescription:add',
'labtest:order', 'report:run'
);
-- Nurse permissions
INSERT IGNORE INTO RolePermissions
SELECT (SELECT role_id FROM Roles WHERE role_name = 'Nurse'), permission_id
FROM Permissions
WHERE permission_name IN (
'patient:view', 'appointment:view', 'visit:record', 'labtest:order'
);
-- Receptionist permissions
INSERT IGNORE INTO RolePermissions
SELECT (SELECT role_id FROM Roles WHERE role_name = 'Receptionist'), permission_id
FROM Permissions
WHERE permission_name IN (
'patient:view', 'patient:add', 'patient:edit', 'appointment:view',
'appointment:schedule', 'appointment:cancel'
);
-- Billing permissions
INSERT IGNORE INTO RolePermissions
SELECT (SELECT role_id FROM Roles WHERE role_name = 'Billing'), permission_id
FROM Permissions
WHERE permission_name IN (
'patient:view', 'billing:view', 'billing:add', 'billing:process', 'report:run'
);
-- Create admin user if it doesn't exist
INSERT IGNORE INTO Users (username, password_hash, email, provider_id) VALUES
('admin', SHA2('password', 256), 'admin@clinic.edu', NULL);
-- Assign admin role to admin user if not already assigned
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'admin'),
(SELECT role_id FROM Roles WHERE role_name = 'Administrator'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'admin')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Administrator')
);
-- Create sample users if they don't exist
INSERT IGNORE INTO Users (username, password_hash, email, provider_id) VALUES
('dr.chen', SHA2('password', 256), 'r.chen@university.edu', 1),
('dr.williams', SHA2('password', 256), 's.williams@university.edu', 2),
('nurse.lee', SHA2('password', 256), 'o.lee@university.edu', 8),
('receptionist', SHA2('password', 256), 'reception@clinic.edu', NULL),
('billing', SHA2('password', 256), 'billing@clinic.edu', NULL);
-- Assign roles to sample users if not already assigned
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'dr.chen'),
(SELECT role_id FROM Roles WHERE role_name = 'Doctor'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'dr.chen')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Doctor')
);
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'dr.williams'),
(SELECT role_id FROM Roles WHERE role_name = 'Doctor'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'dr.williams')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Doctor')
);
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'nurse.lee'),
(SELECT role_id FROM Roles WHERE role_name = 'Nurse'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'nurse.lee')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Nurse')
);
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'receptionist'),
(SELECT role_id FROM Roles WHERE role_name = 'Receptionist'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'receptionist')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Receptionist')
);
INSERT IGNORE INTO UserRoles (user_id, role_id, granted_by)
SELECT
(SELECT user_id FROM Users WHERE username = 'billing'),
(SELECT role_id FROM Roles WHERE role_name = 'Billing'),
(SELECT user_id FROM Users WHERE username = 'admin')
WHERE NOT EXISTS (
SELECT 1 FROM UserRoles
WHERE user_id = (SELECT user_id FROM Users WHERE username = 'billing')
AND role_id = (SELECT role_id FROM Roles WHERE role_name = 'Billing')
);
-- AUDIT TRAIL SETUP
-- Create additional audit tables if needed
-- Create PatientInsuranceAudit table if not exists
CREATE TABLE IF NOT EXISTS PatientInsuranceAudit (
audit_id INT AUTO_INCREMENT PRIMARY KEY,
insurance_id INT NOT NULL,
action_type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
field_changed VARCHAR(50),
old_value TEXT,
new_value TEXT,
changed_by INT,
change_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_insuranceaudit_insurance FOREIGN KEY (insurance_id)
REFERENCES PatientInsurance(insurance_id)
ON DELETE CASCADE,
CONSTRAINT fk_insuranceaudit_user FOREIGN KEY (changed_by)
REFERENCES Users(user_id)
ON DELETE SET NULL
);
-- Create MedicalHistoryAudit table if not exists
CREATE TABLE IF NOT EXISTS MedicalHistoryAudit (
audit_id INT AUTO_INCREMENT PRIMARY KEY,
history_id INT NOT NULL,
action_type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
field_changed VARCHAR(50),
old_value TEXT,
new_value TEXT,
changed_by INT,
change_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_historyaudit_history FOREIGN KEY (history_id)
REFERENCES MedicalHistory(history_id)
ON DELETE CASCADE,
CONSTRAINT fk_historyaudit_user FOREIGN KEY (changed_by)
REFERENCES Users(user_id)
ON DELETE SET NULL
);
-- Create audit trigger for PatientInsurance
DELIMITER //
CREATE TRIGGER IF NOT EXISTS tr_patient_insurance_update AFTER UPDATE ON PatientInsurance
FOR EACH ROW
BEGIN
-- Get current user ID for audit
SET @user_id = (SELECT @current_user_id);
IF OLD.policy_number != NEW.policy_number THEN
INSERT INTO PatientInsuranceAudit (
insurance_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.insurance_id, 'UPDATE', 'policy_number', OLD.policy_number, NEW.policy_number, @user_id
);
END IF;
IF OLD.coverage_start_date != NEW.coverage_start_date THEN
INSERT INTO PatientInsuranceAudit (
insurance_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.insurance_id, 'UPDATE', 'coverage_start_date',
DATE_FORMAT(OLD.coverage_start_date, '%Y-%m-%d'),
DATE_FORMAT(NEW.coverage_start_date, '%Y-%m-%d'),
@user_id
);
END IF;
IF OLD.coverage_end_date != NEW.coverage_end_date THEN
INSERT INTO PatientInsuranceAudit (
insurance_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.insurance_id, 'UPDATE', 'coverage_end_date',
DATE_FORMAT(OLD.coverage_end_date, '%Y-%m-%d'),
DATE_FORMAT(NEW.coverage_end_date, '%Y-%m-%d'),
@user_id
);
END IF;
IF OLD.verification_status != NEW.verification_status THEN
INSERT INTO PatientInsuranceAudit (
insurance_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.insurance_id, 'UPDATE', 'verification_status',
OLD.verification_status, NEW.verification_status, @user_id
);
END IF;
-- Log activity
INSERT INTO UserActivityLog (
user_id, activity_type, entity_type, entity_id, activity_details
) VALUES (
@user_id, 'UPDATE', 'PatientInsurance', NEW.insurance_id,
CONCAT('Updated insurance information for patient ID ', NEW.patient_id)
);
END//
CREATE TRIGGER IF NOT EXISTS tr_medical_history_update AFTER UPDATE ON MedicalHistory
FOR EACH ROW
BEGIN
-- Get current user ID for audit
SET @user_id = (SELECT @current_user_id);
IF OLD.allergies != NEW.allergies THEN
INSERT INTO MedicalHistoryAudit (
history_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.history_id, 'UPDATE', 'allergies', OLD.allergies, NEW.allergies, @user_id
);
END IF;
IF OLD.chronic_conditions != NEW.chronic_conditions THEN
INSERT INTO MedicalHistoryAudit (
history_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.history_id, 'UPDATE', 'chronic_conditions',
OLD.chronic_conditions, NEW.chronic_conditions, @user_id
);
END IF;
IF OLD.past_surgeries != NEW.past_surgeries THEN
INSERT INTO MedicalHistoryAudit (
history_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.history_id, 'UPDATE', 'past_surgeries',
OLD.past_surgeries, NEW.past_surgeries, @user_id
);
END IF;
IF OLD.family_history != NEW.family_history THEN
INSERT INTO MedicalHistoryAudit (
history_id, action_type, field_changed, old_value, new_value, changed_by
) VALUES (
NEW.history_id, 'UPDATE', 'family_history',
OLD.family_history, NEW.family_history, @user_id
);
END IF;
-- Log activity
INSERT INTO UserActivityLog (
user_id, activity_type, entity_type, entity_id, activity_details
) VALUES (
@user_id, 'UPDATE', 'MedicalHistory', NEW.history_id,
CONCAT('Updated medical history for patient ID ', NEW.patient_id)
);
END//
DELIMITER ;