Changeset 946877f


Ignore:
Timestamp:
05/23/26 19:27:12 (4 months ago)
Author:
MBK <marija.karapandzova@…>
Branches:
master
Children:
ccb5a6b
Parents:
43e476a
Message:

Assign roles for doctors and patients and add role permissions

Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • backend/src/main/java/medora/controller/AppointmentController.java

    r43e476a r946877f  
    33import medora.dto.AppointmentDTO;
    44import medora.dto.CreateAppointmentRequest;
     5import medora.dto.PatientDTO;
    56import medora.dto.DoctorDTO;
    6 import medora.dto.PatientDTO;
    77import medora.models.domain.Appointment;
     8import medora.models.domain.Patient;
     9import medora.models.domain.Doctors;
    810import medora.service.AppointmentService;
     11import medora.util.SecurityUtil;
    912import org.slf4j.Logger;
    1013import org.slf4j.LoggerFactory;
     
    1316import org.springframework.http.ResponseEntity;
    1417import org.springframework.web.bind.annotation.*;
     18import jakarta.servlet.http.HttpServletRequest;
    1519
    1620import java.time.LocalDate;
     
    2630
    2731    private final AppointmentService appointmentService;
    28 
    29     public AppointmentController(AppointmentService appointmentService) {
     32    private final SecurityUtil securityUtil;
     33
     34    public AppointmentController(AppointmentService appointmentService, SecurityUtil securityUtil) {
    3035        this.appointmentService = appointmentService;
     36        this.securityUtil = securityUtil;
    3137    }
    3238
    3339    @PostMapping
    34     public ResponseEntity<?> createAppointment(@RequestBody CreateAppointmentRequest request) {
    35         try {
     40    public ResponseEntity<?> createAppointment(@RequestBody CreateAppointmentRequest request, HttpServletRequest httpRequest) {
     41        try {
     42            String role = securityUtil.getRoleFromRequest(httpRequest);
     43            if (role == null) {
     44                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     45                        .body(Map.of("error", "Unauthorized"));
     46            }
     47
    3648            if (request.getPatientId() == null || request.getPatientId() <= 0) {
    3749                return ResponseEntity.badRequest()
     
    4961                return ResponseEntity.badRequest()
    5062                        .body(Map.of("error", "Appointment time is required"));
     63            }
     64
     65            // Patients can only create appointments for themselves
     66            if (role.equals("PATIENT")) {
     67                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     68                if (patientIdFromToken == null || !patientIdFromToken.equals(request.getPatientId())) {
     69                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     70                            .body(Map.of("error", "You can only create appointments for yourself"));
     71                }
    5172            }
    5273
     
    90111
    91112    @GetMapping
    92     public ResponseEntity<?> getAllAppointments() {
    93         try {
    94             logger.info("Fetching all appointments");
    95             List<Appointment> appointments = appointmentService.getAllAppointments();
     113    public ResponseEntity<?> getAllAppointments(HttpServletRequest httpRequest) {
     114        try {
     115            String role = securityUtil.getRoleFromRequest(httpRequest);
     116            if (role == null) {
     117                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     118                        .body(Map.of("error", "Unauthorized"));
     119            }
     120
     121            // Patients cannot view all appointments
     122            if (role.equals("PATIENT")) {
     123                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     124                        .body(Map.of("error", "Patients cannot view all appointments"));
     125            }
     126
     127            List<Appointment> appointments;
     128
     129            // Doctors can only view their own appointments
     130            if (role.equals("DOCTOR")) {
     131                Long doctorIdFromToken = securityUtil.getDoctorIdFromRequest(httpRequest);
     132                if (doctorIdFromToken == null || doctorIdFromToken <= 0) {
     133                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     134                            .body(Map.of("error", "Doctor ID not found in token"));
     135                }
     136                logger.info("Fetching appointments for doctor ID: {}", doctorIdFromToken);
     137                appointments = appointmentService.getAppointmentsForDoctor(doctorIdFromToken);
     138            } else {
     139                // ADMIN and other roles can view all appointments
     140                logger.info("Fetching all appointments");
     141                appointments = appointmentService.getAllAppointments();
     142            }
     143
    96144            List<AppointmentDTO> dtos = appointments.stream()
    97145                    .map(this::convertToDTO)
     
    110158
    111159    @GetMapping("/patient/{patientId}")
    112     public ResponseEntity<?> getAppointmentsForPatient(@PathVariable Long patientId) {
    113         try {
     160    public ResponseEntity<?> getAppointmentsForPatient(@PathVariable Long patientId, HttpServletRequest httpRequest) {
     161        try {
     162            String role = securityUtil.getRoleFromRequest(httpRequest);
     163            if (role == null) {
     164                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     165                        .body(Map.of("error", "Unauthorized"));
     166            }
     167
     168            // Patients can only view their own appointments
     169            if (role.equals("PATIENT")) {
     170                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     171                if (patientIdFromToken == null || !patientIdFromToken.equals(patientId)) {
     172                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     173                            .body(Map.of("error", "You can only view your own appointments"));
     174                }
     175            }
     176
    114177            logger.info("Fetching appointments for patient ID: {}", patientId);
    115178            List<Appointment> appointments = appointmentService.getAppointmentsForPatient(patientId);
     
    172235
    173236    @PatchMapping("/{appointmentId}/cancel")
    174     public ResponseEntity<?> cancelAppointment(@PathVariable Long appointmentId) {
    175         try {
     237    public ResponseEntity<?> cancelAppointment(@PathVariable Long appointmentId, HttpServletRequest httpRequest) {
     238        try {
     239            String role = securityUtil.getRoleFromRequest(httpRequest);
     240            if (role == null) {
     241                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     242                        .body(Map.of("error", "Unauthorized"));
     243            }
     244
     245            // Verify appointment exists and check permissions for patients
     246            Appointment appointment = appointmentService.getAppointmentById(appointmentId)
     247                    .orElseThrow(() -> new RuntimeException("Appointment not found"));
     248
     249            if (role.equals("PATIENT")) {
     250                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     251                Long appointmentPatientId = appointment.getPatient() != null ? appointment.getPatient().getPatientId() : null;
     252                if (patientIdFromToken == null || !patientIdFromToken.equals(appointmentPatientId)) {
     253                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     254                            .body(Map.of("error", "You can only cancel your own appointments"));
     255                }
     256            }
     257
    176258            logger.info("Cancelling appointment with ID: {}", appointmentId);
    177             Appointment appointment = appointmentService.cancelAppointment(appointmentId);
     259            appointment = appointmentService.cancelAppointment(appointmentId);
    178260            AppointmentDTO dto = convertToDTO(appointment);
    179261            return ResponseEntity.ok(dto);
     
    190272
    191273    @PatchMapping("/{appointmentId}/complete")
    192     public ResponseEntity<?> completeAppointment(@PathVariable Long appointmentId) {
    193         try {
     274    public ResponseEntity<?> completeAppointment(@PathVariable Long appointmentId, HttpServletRequest httpRequest) {
     275        try {
     276            String role = securityUtil.getRoleFromRequest(httpRequest);
     277            if (role == null) {
     278                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     279                        .body(Map.of("error", "Unauthorized"));
     280            }
     281
     282            // Only ADMIN and DOCTOR can complete appointments
     283            if (role.equals("PATIENT")) {
     284                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     285                        .body(Map.of("error", "Patients cannot complete appointments"));
     286            }
     287
    194288            logger.info("Completing appointment with ID: {}", appointmentId);
    195289            Appointment appointment = appointmentService.completeAppointment(appointmentId);
  • backend/src/main/java/medora/controller/BillingController.java

    r43e476a r946877f  
    99import medora.service.BillingService;
    1010import medora.util.BillingPDFGenerator;
     11import medora.util.SecurityUtil;
    1112import org.slf4j.Logger;
    1213import org.slf4j.LoggerFactory;
     
    1617import org.springframework.http.ResponseEntity;
    1718import org.springframework.web.bind.annotation.*;
     19import jakarta.servlet.http.HttpServletRequest;
    1820
    1921import java.time.LocalDate;
     
    2931
    3032    private final BillingService billingService;
    31 
    32     public BillingController(BillingService billingService) {
     33    private final SecurityUtil securityUtil;
     34
     35    public BillingController(BillingService billingService, SecurityUtil securityUtil) {
    3336        this.billingService = billingService;
     37        this.securityUtil = securityUtil;
    3438    }
    3539
    3640    @PostMapping
    37     public ResponseEntity<?> generateBillingRecord(@RequestBody CreateBillingRequest request) {
    38         try {
     41    public ResponseEntity<?> generateBillingRecord(@RequestBody CreateBillingRequest request, HttpServletRequest httpRequest) {
     42        try {
     43            String role = securityUtil.getRoleFromRequest(httpRequest);
     44            if (role == null) {
     45                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     46                        .body(Map.of("error", "Unauthorized"));
     47            }
     48
     49            // Only ADMIN can generate billing records (doctors cannot access billing)
     50            if (!role.equals("ADMIN")) {
     51                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     52                        .body(Map.of("error", "Only administrators can generate billing records"));
     53            }
     54
    3955            if (request.getMedicalRecordId() == null || request.getMedicalRecordId() <= 0) {
    4056                return ResponseEntity.badRequest()
     
    7086
    7187    @GetMapping("/{billId}")
    72     public ResponseEntity<?> getBillingById(@PathVariable Long billId) {
    73         try {
     88    public ResponseEntity<?> getBillingById(@PathVariable Long billId, HttpServletRequest httpRequest) {
     89        try {
     90            String role = securityUtil.getRoleFromRequest(httpRequest);
     91            if (role == null) {
     92                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     93                        .body(Map.of("error", "Unauthorized"));
     94            }
     95
     96            // Doctors cannot access billing
     97            if (role.equals("DOCTOR")) {
     98                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     99                        .body(Map.of("error", "Doctors cannot access billing records"));
     100            }
     101
    74102            logger.info("Fetching billing record with ID: {}", billId);
    75             return billingService.getBillingById(billId)
    76                     .map(b -> ResponseEntity.ok(convertToDTO(b)))
    77                     .orElse(ResponseEntity.notFound().build());
     103            var billing = billingService.getBillingById(billId);
     104            if (billing.isEmpty()) {
     105                return ResponseEntity.notFound().build();
     106            }
     107
     108            // Patients can only view their own billing records
     109            if (role.equals("PATIENT")) {
     110                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     111                Long billPatientId = billing.get().getMedicalRecord() != null && billing.get().getMedicalRecord().getPatient() != null
     112                        ? billing.get().getMedicalRecord().getPatient().getPatientId()
     113                        : null;
     114                if (patientIdFromToken == null || !patientIdFromToken.equals(billPatientId)) {
     115                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     116                            .body(Map.of("error", "You can only view your own billing records"));
     117                }
     118            }
     119
     120            return ResponseEntity.ok(convertToDTO(billing.get()));
    78121        } catch (RuntimeException e) {
    79122            logger.error("Error fetching billing record: {}", e.getMessage());
     
    88131
    89132    @GetMapping("/{billId}/detail")
    90     public ResponseEntity<?> getBillingDetail(@PathVariable Long billId) {
    91         try {
     133    public ResponseEntity<?> getBillingDetail(@PathVariable Long billId, HttpServletRequest httpRequest) {
     134        try {
     135            String role = securityUtil.getRoleFromRequest(httpRequest);
     136            if (role == null) {
     137                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     138                        .body(Map.of("error", "Unauthorized"));
     139            }
     140
     141            // Doctors cannot access billing
     142            if (role.equals("DOCTOR")) {
     143                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     144                        .body(Map.of("error", "Doctors cannot access billing records"));
     145            }
     146
    92147            logger.info("Fetching detailed billing information for bill ID: {}", billId);
    93148            BillingDetailDTO detail = billingService.getBillingDetail(billId);
     149
     150            // Patients can only view their own billing details
     151            if (role.equals("PATIENT")) {
     152                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     153                if (patientIdFromToken == null || detail == null || !patientIdFromToken.equals(detail.getPatientId())) {
     154                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     155                            .body(Map.of("error", "You can only view your own billing records"));
     156                }
     157            }
     158
    94159            return ResponseEntity.ok(detail);
    95160        } catch (RuntimeException e) {
     
    105170
    106171    @GetMapping
    107     public ResponseEntity<?> getAllBillings() {
    108         try {
     172    public ResponseEntity<?> getAllBillings(HttpServletRequest httpRequest) {
     173        try {
     174            String role = securityUtil.getRoleFromRequest(httpRequest);
     175            if (role == null) {
     176                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     177                        .body(Map.of("error", "Unauthorized"));
     178            }
     179
     180            // Doctors and Patients cannot view all billing records
     181            if (role.equals("PATIENT") || role.equals("DOCTOR")) {
     182                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     183                        .body(Map.of("error", "You cannot view all billing records"));
     184            }
     185
    109186            logger.info("Fetching all billing records");
    110187            List<Billing> billings = billingService.getAllBillingRecords();
     
    125202
    126203    @GetMapping("/patient/{patientId}")
    127     public ResponseEntity<?> getBillingHistoryForPatient(@PathVariable Long patientId) {
    128         try {
     204    public ResponseEntity<?> getBillingHistoryForPatient(@PathVariable Long patientId, HttpServletRequest httpRequest) {
     205        try {
     206            String role = securityUtil.getRoleFromRequest(httpRequest);
     207            if (role == null) {
     208                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     209                        .body(Map.of("error", "Unauthorized"));
     210            }
     211
     212            // Doctors cannot access billing
     213            if (role.equals("DOCTOR")) {
     214                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     215                        .body(Map.of("error", "Doctors cannot access billing records"));
     216            }
     217
     218            // Patients can only view their own billing history
     219            if (role.equals("PATIENT")) {
     220                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     221                if (patientIdFromToken == null || !patientIdFromToken.equals(patientId)) {
     222                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     223                            .body(Map.of("error", "You can only view your own billing records"));
     224                }
     225            }
     226
    129227            logger.info("Fetching billing history for patient ID: {}", patientId);
    130228            List<Billing> billings = billingService.getBillingHistoryForPatient(patientId);
     
    146244    @PatchMapping("/{billId}/payment-status")
    147245    public ResponseEntity<?> updatePaymentStatus(@PathVariable Long billId,
    148                                                  @RequestBody UpdateBillingRequest request) {
    149         try {
     246                                                 @RequestBody UpdateBillingRequest request,
     247                                                 HttpServletRequest httpRequest) {
     248        try {
     249            String role = securityUtil.getRoleFromRequest(httpRequest);
     250            if (role == null) {
     251                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     252                        .body(Map.of("error", "Unauthorized"));
     253            }
     254
     255            // Only ADMIN can update payment status
     256            if (!role.equals("ADMIN")) {
     257                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     258                        .body(Map.of("error", "Only administrators can update payment status"));
     259            }
     260
    150261            if (request.getPaymentStatus() == null) {
    151262                return ResponseEntity.badRequest()
     
    170281
    171282    @GetMapping("/{billId}/invoice-pdf")
    172     public ResponseEntity<?> downloadInvoicePDF(@PathVariable Long billId) {
    173         try {
     283    public ResponseEntity<?> downloadInvoicePDF(@PathVariable Long billId, HttpServletRequest httpRequest) {
     284        try {
     285            String role = securityUtil.getRoleFromRequest(httpRequest);
     286            if (role == null) {
     287                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     288                        .body(Map.of("error", "Unauthorized"));
     289            }
     290
     291            // Doctors cannot access billing
     292            if (role.equals("DOCTOR")) {
     293                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     294                        .body(Map.of("error", "Doctors cannot access billing records"));
     295            }
     296
    174297            logger.info("Generating PDF invoice for bill ID: {}", billId);
    175298            BillingDetailDTO billingDetail = billingService.getBillingDetail(billId);
     299
     300            // Patients can only download their own invoices
     301            if (role.equals("PATIENT")) {
     302                Long patientIdFromToken = securityUtil.getPatientIdFromRequest(httpRequest);
     303                if (patientIdFromToken == null || !patientIdFromToken.equals(billingDetail.getPatientId())) {
     304                    return ResponseEntity.status(HttpStatus.FORBIDDEN)
     305                            .body(Map.of("error", "You can only download your own invoices"));
     306                }
     307            }
     308
    176309            byte[] pdfContent = BillingPDFGenerator.generateInvoicePDF(billingDetail);
    177310
  • backend/src/main/java/medora/controller/DepartmentController.java

    r43e476a r946877f  
    44import medora.models.domain.Doctors;
    55import medora.service.DepartmentService;
     6import medora.util.SecurityUtil;
    67import org.slf4j.Logger;
    78import org.slf4j.LoggerFactory;
     
    910import org.springframework.http.ResponseEntity;
    1011import org.springframework.web.bind.annotation.*;
     12import jakarta.servlet.http.HttpServletRequest;
    1113
    1214import java.util.List;
     
    2123
    2224    private final DepartmentService departmentService;
    23 
    24     public DepartmentController(DepartmentService departmentService) {
     25    private final SecurityUtil securityUtil;
     26
     27    public DepartmentController(DepartmentService departmentService, SecurityUtil securityUtil) {
    2528        this.departmentService = departmentService;
     29        this.securityUtil = securityUtil;
    2630    }
    2731
     
    6771    }
    6872
    69 
     73    /**
     74     * Get department by name
     75     */
    7076    @GetMapping("/name/{departmentName}")
    7177    public ResponseEntity<?> getDepartmentByName(@PathVariable String departmentName) {
     
    110116    }
    111117
    112 
     118    /**
     119     * Create a new department
     120     */
    113121    @PostMapping
    114     public ResponseEntity<?> createDepartment(@RequestBody Map<String, String> request) {
    115         try {
     122    public ResponseEntity<?> createDepartment(@RequestBody Map<String, String> request, HttpServletRequest httpRequest) {
     123        try {
     124            String role = securityUtil.getRoleFromRequest(httpRequest);
     125            if (role == null) {
     126                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     127                        .body(Map.of("error", "Unauthorized"));
     128            }
     129
     130            // Only ADMIN can create departments
     131            if (!role.equals("ADMIN")) {
     132                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     133                        .body(Map.of("error", "Only administrators can create departments"));
     134            }
     135
    116136            String departmentName = request.get("departmentName");
    117137            if (departmentName == null || departmentName.isBlank()) {
     
    137157    }
    138158
    139 
     159    /**
     160     * Update a department
     161     */
    140162    @PutMapping("/{departmentId}")
    141163    public ResponseEntity<?> updateDepartment(@PathVariable Long departmentId,
    142                                               @RequestBody Map<String, String> request) {
    143         try {
     164                                              @RequestBody Map<String, String> request,
     165                                              HttpServletRequest httpRequest) {
     166        try {
     167            String role = securityUtil.getRoleFromRequest(httpRequest);
     168            if (role == null) {
     169                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     170                        .body(Map.of("error", "Unauthorized"));
     171            }
     172
     173            // Only ADMIN can update departments
     174            if (!role.equals("ADMIN")) {
     175                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     176                        .body(Map.of("error", "Only administrators can update departments"));
     177            }
     178
    144179            String departmentName = request.get("departmentName");
    145180            if (departmentName == null || departmentName.isBlank()) {
  • backend/src/main/java/medora/controller/DoctorController.java

    r43e476a r946877f  
    11package medora.controller;
    22
    3 import medora.dto.*;
    4 import medora.models.domain.Departments;
     3import medora.dto.DoctorDTO;
     4import medora.dto.CreateDoctorRequest;
     5import medora.dto.DoctorLevelDTO;
     6import medora.dto.DoctorSpecializationDTO;
     7import medora.dto.DepartmentDTO;
     8import medora.models.domain.Doctors;
    59import medora.models.domain.DoctorLevel;
    610import medora.models.domain.DoctorSpecialization;
    7 import medora.models.domain.Doctors;
     11import medora.models.domain.Departments;
    812import medora.service.DoctorService;
     13import medora.util.SecurityUtil;
    914import org.slf4j.Logger;
    1015import org.slf4j.LoggerFactory;
     
    1217import org.springframework.http.ResponseEntity;
    1318import org.springframework.web.bind.annotation.*;
     19import jakarta.servlet.http.HttpServletRequest;
    1420
    1521import java.util.List;
     
    2430
    2531    private final DoctorService doctorService;
    26 
    27     public DoctorController(DoctorService doctorService) {
     32    private final SecurityUtil securityUtil;
     33
     34    public DoctorController(DoctorService doctorService, SecurityUtil securityUtil) {
    2835        this.doctorService = doctorService;
     36        this.securityUtil = securityUtil;
    2937    }
    3038
    3139    @PostMapping
    32     public ResponseEntity<?> createDoctor(@RequestBody CreateDoctorRequest request) {
    33         try {
     40    public ResponseEntity<?> createDoctor(@RequestBody CreateDoctorRequest request, HttpServletRequest httpRequest) {
     41        try {
     42            String role = securityUtil.getRoleFromRequest(httpRequest);
     43            if (role == null) {
     44                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     45                        .body(Map.of("error", "Unauthorized"));
     46            }
     47
     48            // Only ADMIN can create doctors
     49            if (!role.equals("ADMIN")) {
     50                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     51                        .body(Map.of("error", "Only administrators can create doctors"));
     52            }
    3453            if (request.getFirstName() == null || request.getFirstName().isBlank()) {
    3554                return ResponseEntity.badRequest()
     
    193212    @PutMapping("/{doctorId}")
    194213    public ResponseEntity<?> updateDoctor(@PathVariable Long doctorId,
    195                                          @RequestBody CreateDoctorRequest request) {
    196         try {
     214                                          @RequestBody CreateDoctorRequest request,
     215                                          HttpServletRequest httpRequest) {
     216        try {
     217            String role = securityUtil.getRoleFromRequest(httpRequest);
     218            if (role == null) {
     219                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     220                        .body(Map.of("error", "Unauthorized"));
     221            }
     222
     223            // Only ADMIN can update doctors
     224            if (!role.equals("ADMIN")) {
     225                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     226                        .body(Map.of("error", "Only administrators can update doctors"));
     227            }
     228
    197229            logger.info("Updating doctor with ID: {}", doctorId);
    198230
  • backend/src/main/java/medora/controller/LabController.java

    r43e476a r946877f  
    22
    33import medora.dto.*;
    4 import medora.models.domain.LabResults;
    5 import medora.models.domain.LabTests;
    6 import medora.models.domain.MedicalRecordLabResults;
    7 import medora.models.domain.PerformedLabTests;
     4import medora.models.domain.*;
    85import medora.service.LabService;
     6import medora.util.SecurityUtil;
    97import org.slf4j.Logger;
    108import org.slf4j.LoggerFactory;
     
    1210import org.springframework.http.ResponseEntity;
    1311import org.springframework.web.bind.annotation.*;
     12import jakarta.servlet.http.HttpServletRequest;
    1413
    1514import java.util.List;
     
    2423
    2524    private final LabService labService;
    26 
    27     public LabController(LabService labService) {
     25    private final SecurityUtil securityUtil;
     26
     27    public LabController(LabService labService, SecurityUtil securityUtil) {
    2828        this.labService = labService;
     29        this.securityUtil = securityUtil;
    2930    }
    3031
    3132    @PostMapping
    32     public ResponseEntity<?> createLabTest(@RequestBody CreateLabTestRequest request) {
    33         try {
     33    public ResponseEntity<?> createLabTest(@RequestBody CreateLabTestRequest request, HttpServletRequest httpRequest) {
     34        try {
     35            String role = securityUtil.getRoleFromRequest(httpRequest);
     36            if (role == null) {
     37                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     38                        .body(Map.of("error", "Unauthorized"));
     39            }
     40
     41            // Only ADMIN can create lab tests
     42            if (!role.equals("ADMIN")) {
     43                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     44                        .body(Map.of("error", "Only administrators can create lab tests"));
     45            }
     46
    3447            if (request.getTestName() == null || request.getTestName().isBlank()) {
    3548                return ResponseEntity.badRequest()
     
    100113    @PutMapping("/{testId}")
    101114    public ResponseEntity<?> updateLabTest(@PathVariable Long testId,
    102                                           @RequestBody CreateLabTestRequest request) {
     115                                           @RequestBody CreateLabTestRequest request) {
    103116        try {
    104117            logger.info("Updating lab test with ID: {}", testId);
     
    123136
    124137    @PostMapping("/request")
    125     public ResponseEntity<?> requestLabTest(@RequestBody RequestLabTestRequest request) {
    126         try {
     138    public ResponseEntity<?> requestLabTest(@RequestBody RequestLabTestRequest request, HttpServletRequest httpRequest) {
     139        try {
     140            String role = securityUtil.getRoleFromRequest(httpRequest);
     141            if (role == null) {
     142                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     143                        .body(Map.of("error", "Unauthorized"));
     144            }
     145
     146            // Patients cannot request lab tests
     147            if (role.equals("PATIENT")) {
     148                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     149                        .body(Map.of("error", "Patients cannot request lab tests"));
     150            }
     151
    127152            logger.info("Requesting lab test {} for patient {}", request.getTestId(), request.getPatientId());
    128153
     
    193218
    194219    @PostMapping("/results")
    195     public ResponseEntity<?> submitLabResult(@RequestBody SubmitLabResultRequest request) {
    196         try {
     220    public ResponseEntity<?> submitLabResult(@RequestBody SubmitLabResultRequest request, HttpServletRequest httpRequest) {
     221        try {
     222            String role = securityUtil.getRoleFromRequest(httpRequest);
     223            if (role == null) {
     224                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     225                        .body(Map.of("error", "Unauthorized"));
     226            }
     227
     228            // Only LAB_TECHNICIAN can submit lab results (not DOCTOR)
     229            if (!role.equals("LAB_TECHNICIAN")) {
     230                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     231                        .body(Map.of("error", "Only lab technicians can submit lab results"));
     232            }
     233
    197234            logger.info("Submitting lab result for medical record {}", request.getMedicalRecordId());
    198235
  • backend/src/main/java/medora/controller/PatientController.java

    r43e476a r946877f  
    11package medora.controller;
    22
     3import medora.dto.PatientDTO;
    34import medora.dto.CreatePatientRequest;
    4 import medora.dto.PatientDTO;
    55import medora.models.domain.Patient;
    66import medora.service.PatientService;
     7import medora.util.SecurityUtil;
    78import org.slf4j.Logger;
    89import org.slf4j.LoggerFactory;
     
    1011import org.springframework.http.ResponseEntity;
    1112import org.springframework.web.bind.annotation.*;
     13import jakarta.servlet.http.HttpServletRequest;
    1214
    1315import java.util.List;
     
    2224
    2325    private final PatientService patientService;
    24 
    25     public PatientController(PatientService patientService) {
     26    private final SecurityUtil securityUtil;
     27
     28    public PatientController(PatientService patientService, SecurityUtil securityUtil) {
    2629        this.patientService = patientService;
     30        this.securityUtil = securityUtil;
    2731    }
    2832
    2933    @PostMapping
    30     public ResponseEntity<?> createPatient(@RequestBody CreatePatientRequest request) {
    31         try {
     34    public ResponseEntity<?> createPatient(@RequestBody CreatePatientRequest request, HttpServletRequest httpRequest) {
     35        try {
     36            String role = securityUtil.getRoleFromRequest(httpRequest);
     37            if (role == null) {
     38                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     39                        .body(Map.of("error", "Unauthorized"));
     40            }
     41
     42            // Only ADMIN can create patients
     43            if (!role.equals("ADMIN")) {
     44                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     45                        .body(Map.of("error", "Only administrators can create patients"));
     46            }
    3247            if (request.getFirstName() == null || request.getFirstName().isBlank()) {
    3348                return ResponseEntity.badRequest()
     
    144159    @PutMapping("/{patientId}")
    145160    public ResponseEntity<?> updatePatient(@PathVariable Long patientId,
    146                                           @RequestBody CreatePatientRequest request) {
    147         try {
     161                                           @RequestBody CreatePatientRequest request,
     162                                           HttpServletRequest httpRequest) {
     163        try {
     164            String role = securityUtil.getRoleFromRequest(httpRequest);
     165            if (role == null) {
     166                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     167                        .body(Map.of("error", "Unauthorized"));
     168            }
     169
     170            // Only ADMIN can update patients
     171            if (!role.equals("ADMIN")) {
     172                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     173                        .body(Map.of("error", "Only administrators can update patients"));
     174            }
     175
    148176            logger.info("Updating patient with ID: {}", patientId);
    149177
  • backend/src/main/java/medora/controller/ProcedureController.java

    r43e476a r946877f  
    55import medora.dto.SubmitProcedureResultRequest;
    66import medora.models.domain.PerformedProcedures;
     7import medora.models.domain.Procedure;
    78import medora.models.domain.ProcedureResults;
    89import medora.service.ProcedureService;
     10import medora.util.SecurityUtil;
    911import org.slf4j.Logger;
    1012import org.slf4j.LoggerFactory;
     
    1315import org.springframework.http.ResponseEntity;
    1416import org.springframework.web.bind.annotation.*;
     17import jakarta.servlet.http.HttpServletRequest;
    1518
    1619import java.time.LocalDate;
     
    2629
    2730    private final ProcedureService procedureService;
    28 
    29     public ProcedureController(ProcedureService procedureService) {
     31    private final SecurityUtil securityUtil;
     32
     33    public ProcedureController(ProcedureService procedureService, SecurityUtil securityUtil) {
    3034        this.procedureService = procedureService;
     35        this.securityUtil = securityUtil;
    3136    }
    3237
     
    4853
    4954    @PostMapping("/request")
    50     public ResponseEntity<?> requestProcedure(@RequestBody RequestProcedureRequest request) {
    51         try {
     55    public ResponseEntity<?> requestProcedure(@RequestBody RequestProcedureRequest request, HttpServletRequest httpRequest) {
     56        try {
     57            String role = securityUtil.getRoleFromRequest(httpRequest);
     58            if (role == null) {
     59                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     60                        .body(Map.of("error", "Unauthorized"));
     61            }
     62
     63            // Patients cannot request procedures
     64            if (role.equals("PATIENT")) {
     65                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     66                        .body(Map.of("error", "Patients cannot request procedures"));
     67            }
     68
    5269            logger.info("Requesting procedure {} for patient {}", request.getProcedureId(), request.getPatientId());
    5370
     
    207224    public ResponseEntity<?> recordProcedureOutcome(
    208225            @PathVariable Long procedureId,
    209             @RequestParam String notes) {
    210         try {
     226            @RequestParam String notes,
     227            HttpServletRequest httpRequest) {
     228        try {
     229            String role = securityUtil.getRoleFromRequest(httpRequest);
     230            if (role == null) {
     231                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     232                        .body(Map.of("error", "Unauthorized"));
     233            }
     234
     235            // Only DOCTOR and ADMIN can record procedure outcomes
     236            if (role.equals("PATIENT")) {
     237                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     238                        .body(Map.of("error", "Patients cannot record procedure outcomes"));
     239            }
     240
    211241            logger.info("Recording procedure outcome for ID: {}", procedureId);
    212242            PerformedProcedures procedure = procedureService.recordProcedureOutcome(procedureId, notes);
     
    232262
    233263    @PostMapping("/results")
    234     public ResponseEntity<?> submitProcedureResult(@RequestBody SubmitProcedureResultRequest request) {
    235         try {
     264    public ResponseEntity<?> submitProcedureResult(@RequestBody SubmitProcedureResultRequest request, HttpServletRequest httpRequest) {
     265        try {
     266            String role = securityUtil.getRoleFromRequest(httpRequest);
     267            if (role == null) {
     268                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     269                        .body(Map.of("error", "Unauthorized"));
     270            }
     271
     272            // Only DOCTOR can submit procedure results
     273            if (!role.equals("DOCTOR")) {
     274                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     275                        .body(Map.of("error", "Only doctors can submit procedure results"));
     276            }
     277
    236278            logger.info("Submitting procedure result for medical record {}", request.getMedicalRecordId());
    237279
     
    292334    private Map<String, Object> convertResultToDTO(ProcedureResults result) {
    293335        return Map.of(
    294             "resultId", result.getResultId(),
    295             "procedureId", result.getProcedure().getProcedureId(),
    296             "procedureType", result.getProcedure().getProcedureType(),
    297             "resultDescription", result.getResultDescription() != null ? result.getResultDescription() : "",
    298             "resultDate", result.getResultDate()
     336                "resultId", result.getResultId(),
     337                "procedureId", result.getProcedure().getProcedureId(),
     338                "procedureType", result.getProcedure().getProcedureType(),
     339                "resultDescription", result.getResultDescription() != null ? result.getResultDescription() : "",
     340                "resultDate", result.getResultDate()
    299341        );
    300342    }
    301343}
     344
  • backend/src/main/java/medora/controller/ReferralController.java

    r43e476a r946877f  
    55import medora.models.domain.Referrals;
    66import medora.service.ReferralService;
     7import medora.util.SecurityUtil;
    78import org.slf4j.Logger;
    89import org.slf4j.LoggerFactory;
     
    1011import org.springframework.http.ResponseEntity;
    1112import org.springframework.web.bind.annotation.*;
     13import jakarta.servlet.http.HttpServletRequest;
    1214
    1315import java.util.List;
     
    2224
    2325    private final ReferralService referralService;
    24 
    25     public ReferralController(ReferralService referralService) {
     26    private final SecurityUtil securityUtil;
     27
     28    public ReferralController(ReferralService referralService, SecurityUtil securityUtil) {
    2629        this.referralService = referralService;
     30        this.securityUtil = securityUtil;
    2731    }
    2832
    2933    @PostMapping
    30     public ResponseEntity<?> createReferral(@RequestBody CreateReferralRequest request) {
    31         try {
     34    public ResponseEntity<?> createReferral(@RequestBody CreateReferralRequest request, HttpServletRequest httpRequest) {
     35        try {
     36            String role = securityUtil.getRoleFromRequest(httpRequest);
     37            if (role == null) {
     38                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
     39                        .body(Map.of("error", "Unauthorized"));
     40            }
     41
     42            // Patients cannot create referrals
     43            if (role.equals("PATIENT")) {
     44                return ResponseEntity.status(HttpStatus.FORBIDDEN)
     45                        .body(Map.of("error", "Patients cannot create referrals"));
     46            }
     47
    3248            if (request.getMedicalRecordId() == null || request.getMedicalRecordId() <= 0) {
    3349                return ResponseEntity.badRequest()
  • backend/src/main/java/medora/dto/BillingDetailDTO.java

    r43e476a r946877f  
    77public class BillingDetailDTO {
    88    private Long billId;
     9    private Long patientId;
    910    private String patientName;
    1011    private String patientEmbg;
     
    1920    public BillingDetailDTO() {}
    2021
    21     public BillingDetailDTO(Long billId, String patientName, String patientEmbg, String patientPhone,
     22    public BillingDetailDTO(Long billId, Long patientId, String patientName, String patientEmbg, String patientPhone,
    2223                            BigDecimal totalCost, String paymentStatus, LocalDate paymentDate,
    2324                            LocalDate billDate, List<BillingItemDTO> procedures, List<BillingItemDTO> labTests) {
    2425        this.billId = billId;
     26        this.patientId = patientId;
    2527        this.patientName = patientName;
    2628        this.patientEmbg = patientEmbg;
     
    3739    public Long getBillId() { return billId; }
    3840    public void setBillId(Long billId) { this.billId = billId; }
     41
     42    public Long getPatientId() { return patientId; }
     43    public void setPatientId(Long patientId) { this.patientId = patientId; }
    3944
    4045    public String getPatientName() { return patientName; }
  • backend/src/main/java/medora/util/JwtUtil.java

    r43e476a r946877f  
    11package medora.util;
    22
     3import io.jsonwebtoken.Claims;
    34import io.jsonwebtoken.Jwts;
    45import io.jsonwebtoken.SignatureAlgorithm;
     
    910import javax.crypto.SecretKey;
    1011import java.util.Date;
     12import java.util.HashMap;
     13import java.util.Map;
    1114
    1215@Component
    1316public class JwtUtil {
    1417
    15     @Value("${jwt.secret:your-secret-key-change-this-in-production}")
     18    @Value("${jwt.secret:MyVerySecretKeyForJWTTokenGenerationAndValidationPurposesOnly12345}")
    1619    private String jwtSecret;
    1720
    18     @Value("${jwt.expiration:86400000}")
     21    @Value("${jwt.expiration:86400000}") // 24 hours in milliseconds
    1922    private long jwtExpirationMs;
    2023
     24    private SecretKey getSigningKey() {
     25        return Keys.hmacShaKeyFor(jwtSecret.getBytes());
     26    }
     27
    2128    public String generateToken(String username, String role, Long userId, Long patientId) {
    22         SecretKey key = Keys.hmacShaKeyFor(jwtSecret.getBytes());
     29        return generateTokenWithDoctorId(username, role, userId, patientId, null);
     30    }
    2331
     32    public String generateTokenWithDoctorId(String username, String role, Long userId, Long patientId, Long doctorId) {
     33        Map<String, Object> claims = new HashMap<>();
     34        claims.put("role", role);
     35        claims.put("userId", userId);
     36        if (patientId != null) {
     37            claims.put("patientId", patientId);
     38        }
     39        if (doctorId != null) {
     40            claims.put("doctorId", doctorId);
     41        }
     42        return createToken(claims, username);
     43    }
     44
     45    private String createToken(Map<String, Object> claims, String subject) {
    2446        return Jwts.builder()
    25                 .subject(username)
    26                 .claim("role", role)
    27                 .claim("userId", userId)
    28                 .claim("patientId", patientId)
    29                 .issuedAt(new Date())
    30                 .expiration(new Date(System.currentTimeMillis() + jwtExpirationMs))
    31                 .signWith(key, SignatureAlgorithm.HS256)
     47                .setClaims(claims)
     48                .setSubject(subject)
     49                .setIssuedAt(new Date())
     50                .setExpiration(new Date(System.currentTimeMillis() + jwtExpirationMs))
     51                .signWith(getSigningKey(), SignatureAlgorithm.HS256)
    3252                .compact();
    3353    }
     54
     55    public String extractUsername(String token) {
     56        return extractClaim(token, Claims::getSubject);
     57    }
     58
     59    public String extractRole(String token) {
     60        return extractClaim(token, claims -> (String) claims.get("role"));
     61    }
     62
     63    public Long extractUserId(String token) {
     64        return extractClaim(token, claims -> ((Number) claims.get("userId")).longValue());
     65    }
     66
     67    public Long extractPatientId(String token) {
     68        return extractClaim(token, claims -> {
     69            Object patientId = claims.get("patientId");
     70            return patientId != null ? ((Number) patientId).longValue() : null;
     71        });
     72    }
     73
     74    public Long extractDoctorId(String token) {
     75        return extractClaim(token, claims -> {
     76            Object doctorId = claims.get("doctorId");
     77            return doctorId != null ? ((Number) doctorId).longValue() : null;
     78        });
     79    }
     80
     81    public <T> T extractClaim(String token, java.util.function.Function<Claims, T> claimsResolver) {
     82        final Claims claims = extractAllClaims(token);
     83        return claimsResolver.apply(claims);
     84    }
     85
     86    private Claims extractAllClaims(String token) {
     87        return Jwts.parser()
     88                .verifyWith(getSigningKey())
     89                .build()
     90                .parseSignedClaims(token)
     91                .getPayload();
     92    }
     93
     94    public boolean isTokenValid(String token) {
     95        try {
     96            Jwts.parser()
     97                    .verifyWith(getSigningKey())
     98                    .build()
     99                    .parseSignedClaims(token);
     100            return true;
     101        } catch (Exception e) {
     102            return false;
     103        }
     104    }
     105
     106    public boolean isTokenExpired(String token) {
     107        return extractClaim(token, Claims::getExpiration).before(new Date());
     108    }
    34109}
  • pom.xml

    r43e476a r946877f  
    1010    </parent>
    1111    <groupId>medora</groupId>
    12     <artifactId>medora4</artifactId>
     12    <artifactId>medora5</artifactId>
    1313    <version>0.0.1-SNAPSHOT</version>
    1414    <name>medora5</name>
Note: See TracChangeset for help on using the changeset viewer.