edit study_iuids & accNum in patient jwt to array
This commit is contained in:
@@ -63,7 +63,7 @@ func (h *DicomHandler) ForwardRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "patient":
|
case "patient":
|
||||||
// For patients requesting study list, filter to only show their studies
|
// For patients requesting study list, filter to only show their studies
|
||||||
if strings.HasPrefix(urlPath, "/studies") && !strings.Contains(urlPath, "/") {
|
if strings.HasPrefix(urlPath, "/studies") && !strings.Contains(urlPath, "/") {
|
||||||
// Check if multiple studies are available in the claim
|
// Check if studies are available in the claim
|
||||||
if len(claims.StudyIUIDs) > 0 {
|
if len(claims.StudyIUIDs) > 0 {
|
||||||
// Remove existing StudyInstanceUID param if it exists
|
// Remove existing StudyInstanceUID param if it exists
|
||||||
queryParams.Del("StudyInstanceUID")
|
queryParams.Del("StudyInstanceUID")
|
||||||
@@ -71,12 +71,9 @@ func (h *DicomHandler) ForwardRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
// For DICOMweb, we can use comma-separated UIDs
|
// For DICOMweb, we can use comma-separated UIDs
|
||||||
queryParams.Set("StudyInstanceUID", strings.Join(claims.StudyIUIDs, ","))
|
queryParams.Set("StudyInstanceUID", strings.Join(claims.StudyIUIDs, ","))
|
||||||
|
|
||||||
h.logger.Debug("Filtering by multiple studies",
|
h.logger.Debug("Filtering by studies",
|
||||||
zap.Strings("studies", claims.StudyIUIDs),
|
zap.Strings("studies", claims.StudyIUIDs),
|
||||||
)
|
)
|
||||||
} else if claims.StudyIUID != "" {
|
|
||||||
// Fallback for backward compatibility - ensure only the patient's study is shown
|
|
||||||
queryParams.Set("StudyInstanceUID", claims.StudyIUID)
|
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(urlPath, "/studies/") {
|
} else if strings.HasPrefix(urlPath, "/studies/") {
|
||||||
// This is a request for a specific study - check if the patient is authorized
|
// This is a request for a specific study - check if the patient is authorized
|
||||||
@@ -90,21 +87,14 @@ func (h *DicomHandler) ForwardRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Check if this study is in the patient's authorized studies
|
// Check if this study is in the patient's authorized studies
|
||||||
authorized := false
|
authorized := false
|
||||||
|
|
||||||
// First check StudyIUIDs array
|
// Check StudyIUIDs array
|
||||||
if len(claims.StudyIUIDs) > 0 {
|
for _, id := range claims.StudyIUIDs {
|
||||||
for _, id := range claims.StudyIUIDs {
|
if id == studyID {
|
||||||
if id == studyID {
|
authorized = true
|
||||||
authorized = true
|
break
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then check single StudyIUID for backward compatibility
|
|
||||||
if !authorized && claims.StudyIUID == studyID {
|
|
||||||
authorized = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not authorized, return 403 Forbidden
|
// If not authorized, return 403 Forbidden
|
||||||
if !authorized {
|
if !authorized {
|
||||||
h.logger.Warn("Unauthorized study access attempt",
|
h.logger.Warn("Unauthorized study access attempt",
|
||||||
|
|||||||
@@ -187,39 +187,27 @@ func PatientViewRestriction(logger *zap.Logger) func(http.Handler) http.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If a study is being requested, verify patient has access
|
// If a study is being requested, verify patient has access
|
||||||
if requestedStudyUID != "" {
|
if requestedStudyUID != "" && len(claims.StudyIUIDs) > 0 {
|
||||||
// Check if the requested study is authorized
|
// Check if the requested study is authorized
|
||||||
isAuthorized := false
|
isAuthorized := false
|
||||||
|
|
||||||
// First check the array of studies if available
|
for _, studyUID := range claims.StudyIUIDs {
|
||||||
if len(claims.StudyIUIDs) > 0 {
|
if studyUID == requestedStudyUID {
|
||||||
for _, studyUID := range claims.StudyIUIDs {
|
isAuthorized = true
|
||||||
if studyUID == requestedStudyUID {
|
logger.Debug("Patient authorized to access study",
|
||||||
isAuthorized = true
|
zap.String("userID", claims.UserID),
|
||||||
logger.Debug("Patient authorized to access study from StudyIUIDs array",
|
zap.String("requestedStudy", requestedStudyUID))
|
||||||
zap.String("userID", claims.UserID),
|
break
|
||||||
zap.String("requestedStudy", requestedStudyUID))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found in the array, check the single StudyIUID for backward compatibility
|
// If not authorized, return 403 Forbidden
|
||||||
if !isAuthorized && claims.StudyIUID == requestedStudyUID {
|
|
||||||
isAuthorized = true
|
|
||||||
logger.Debug("Patient authorized to access study from StudyIUID",
|
|
||||||
zap.String("userID", claims.UserID),
|
|
||||||
zap.String("requestedStudy", requestedStudyUID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If still not authorized, return 403 Forbidden
|
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
logger.Warn("Patient attempted to access unauthorized study",
|
logger.Warn("Patient attempted to access unauthorized study",
|
||||||
zap.String("userID", claims.UserID),
|
zap.String("userID", claims.UserID),
|
||||||
zap.String("role", claims.Role),
|
zap.String("role", claims.Role),
|
||||||
zap.String("requestedStudy", requestedStudyUID),
|
zap.String("requestedStudy", requestedStudyUID),
|
||||||
zap.Strings("authorizedStudies", claims.StudyIUIDs),
|
zap.Strings("authorizedStudies", claims.StudyIUIDs))
|
||||||
zap.String("authorizedStudy", claims.StudyIUID))
|
|
||||||
|
|
||||||
// Return 403 Forbidden with a clear message
|
// Return 403 Forbidden with a clear message
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ var MockUsers = []User{
|
|||||||
type PatientData struct {
|
type PatientData struct {
|
||||||
PatientID string `json:"patient_id"`
|
PatientID string `json:"patient_id"`
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
StudyIUID string `json:"study_iuid,omitempty"` // For backward compatibility
|
StudyIUIDs []string `json:"study_iuids"`
|
||||||
StudyIUIDs []string `json:"study_iuids,omitempty"` // Multiple study IDs
|
AccessionNumbers []string `json:"accession_numbers"`
|
||||||
AccessionNumber string `json:"accession_number,omitempty"` // For backward compatibility
|
|
||||||
AccessionNumbers []string `json:"accession_numbers,omitempty"` // Multiple accession numbers
|
|
||||||
PatientName string `json:"patient_name"`
|
PatientName string `json:"patient_name"`
|
||||||
ReferringPhysician string `json:"referring_physician"`
|
ReferringPhysician string `json:"referring_physician"`
|
||||||
}
|
}
|
||||||
@@ -61,8 +59,8 @@ var MockPatients = []PatientData{
|
|||||||
{
|
{
|
||||||
PatientID: "MR00000359",
|
PatientID: "MR00000359",
|
||||||
UserID: "4",
|
UserID: "4",
|
||||||
StudyIUID: "1.2.826.0.1.3680043.9.7307.1.202503196393.01",
|
StudyIUIDs: []string{"1.2.826.0.1.3680043.9.7307.1.202503196393.01"},
|
||||||
AccessionNumber: "CR.250319.6393.01",
|
AccessionNumbers: []string{"CR.250319.6393.01"},
|
||||||
PatientName: "Bobon Santoso",
|
PatientName: "Bobon Santoso",
|
||||||
ReferringPhysician: "DR. HERWINDO RIDWAN, SP.OT",
|
ReferringPhysician: "DR. HERWINDO RIDWAN, SP.OT",
|
||||||
},
|
},
|
||||||
@@ -99,7 +97,7 @@ func FindStudiesByReferringPhysician(physicianName string) []string {
|
|||||||
var studies []string
|
var studies []string
|
||||||
for _, patient := range MockPatients {
|
for _, patient := range MockPatients {
|
||||||
if patient.ReferringPhysician == physicianName {
|
if patient.ReferringPhysician == physicianName {
|
||||||
studies = append(studies, patient.StudyIUID)
|
studies = append(studies, patient.StudyIUIDs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return studies
|
return studies
|
||||||
|
|||||||
@@ -25,10 +25,8 @@ type RefreshToken struct {
|
|||||||
type PatientDetails struct {
|
type PatientDetails struct {
|
||||||
PatientID string `json:"patient_id"`
|
PatientID string `json:"patient_id"`
|
||||||
PatientName string `json:"patient_name"`
|
PatientName string `json:"patient_name"`
|
||||||
AccessionNumber string `json:"accession_number,omitempty"` // For backward compatibility
|
StudyInstanceUIDs []string `json:"study_instance_uids,omitempty"`
|
||||||
AccessionNumbers []string `json:"accession_numbers,omitempty"` // Multiple accession numbers
|
AccessionNumbers []string `json:"accession_numbers,omitempty"`
|
||||||
StudyInstanceUID string `json:"study_instance_uid,omitempty"` // For backward compatibility
|
|
||||||
StudyInstanceUIDs []string `json:"study_instance_uids,omitempty"` // Multiple study IDs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoctorDetails contains doctor-specific data
|
// DoctorDetails contains doctor-specific data
|
||||||
|
|||||||
@@ -158,8 +158,8 @@ func SetupRouter(cfg *config.Config, logger *zap.Logger) http.Handler {
|
|||||||
},
|
},
|
||||||
"patient_info": map[string]string{
|
"patient_info": map[string]string{
|
||||||
"patient_id": claims.PatientID,
|
"patient_id": claims.PatientID,
|
||||||
"study_iuid": claims.StudyIUID,
|
"study_iuid": claims.StudyIUIDs[0],
|
||||||
"accession_number": claims.AccessionNumber,
|
"accession_number": claims.AccessionNumbers[0],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -53,26 +53,17 @@ func (s *AuthService) Login(email, password string) (*models.LoginResponse, erro
|
|||||||
// Set patient-specific claims
|
// Set patient-specific claims
|
||||||
additionalClaims["patient_id"] = patientData.PatientID
|
additionalClaims["patient_id"] = patientData.PatientID
|
||||||
additionalClaims["patient_name"] = patientData.PatientName
|
additionalClaims["patient_name"] = patientData.PatientName
|
||||||
|
additionalClaims["study_iuids"] = patientData.StudyIUIDs
|
||||||
|
additionalClaims["accession_numbers"] = patientData.AccessionNumbers
|
||||||
|
|
||||||
// Handle multiple studies if available
|
// For redirectURL and home_url, use first study for simplicity
|
||||||
if len(patientData.StudyIUIDs) > 0 {
|
if len(patientData.StudyIUIDs) > 0 {
|
||||||
// Store all studies in the token for DICOMWeb access
|
|
||||||
additionalClaims["study_iuids"] = patientData.StudyIUIDs
|
|
||||||
additionalClaims["accession_numbers"] = patientData.AccessionNumbers
|
|
||||||
|
|
||||||
// Set the first study as default for display and backward compatibility
|
|
||||||
additionalClaims["study_iuid"] = patientData.StudyIUIDs[0]
|
|
||||||
additionalClaims["accession_number"] = patientData.AccessionNumbers[0]
|
|
||||||
|
|
||||||
// Only use the first study in the redirect URL
|
|
||||||
additionalClaims["home_url"] = fmt.Sprintf("viewer?StudyInstanceUIDs=%s", patientData.StudyIUIDs[0])
|
additionalClaims["home_url"] = fmt.Sprintf("viewer?StudyInstanceUIDs=%s", patientData.StudyIUIDs[0])
|
||||||
redirectURL = fmt.Sprintf("/viewer?StudyInstanceUIDs=%s", patientData.StudyIUIDs[0])
|
redirectURL = fmt.Sprintf("/viewer?StudyInstanceUIDs=%s", patientData.StudyIUIDs[0])
|
||||||
} else {
|
} else {
|
||||||
// Fall back to single study for backward compatibility
|
// Fallback for empty studies array (shouldn't happen)
|
||||||
additionalClaims["study_iuid"] = patientData.StudyIUID
|
additionalClaims["home_url"] = "/"
|
||||||
additionalClaims["accession_number"] = patientData.AccessionNumber
|
redirectURL = "/"
|
||||||
additionalClaims["home_url"] = fmt.Sprintf("viewer?StudyInstanceUIDs=%s", patientData.StudyIUID)
|
|
||||||
redirectURL = fmt.Sprintf("/viewer?StudyInstanceUIDs=%s", patientData.StudyIUID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalClaims["study_list"] = "disabled"
|
additionalClaims["study_list"] = "disabled"
|
||||||
@@ -138,12 +129,6 @@ func (s *AuthService) RefreshToken(refreshToken string) (string, error) {
|
|||||||
if claims.PatientName != "" {
|
if claims.PatientName != "" {
|
||||||
additionalClaims["patient_name"] = claims.PatientName
|
additionalClaims["patient_name"] = claims.PatientName
|
||||||
}
|
}
|
||||||
if claims.AccessionNumber != "" {
|
|
||||||
additionalClaims["accession_number"] = claims.AccessionNumber
|
|
||||||
}
|
|
||||||
if claims.StudyIUID != "" {
|
|
||||||
additionalClaims["study_iuid"] = claims.StudyIUID
|
|
||||||
}
|
|
||||||
if claims.HomeURL != "" {
|
if claims.HomeURL != "" {
|
||||||
additionalClaims["home_url"] = claims.HomeURL
|
additionalClaims["home_url"] = claims.HomeURL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ type CustomClaims struct {
|
|||||||
// Patient-specific fields
|
// Patient-specific fields
|
||||||
PatientID string `json:"patient_id,omitempty"`
|
PatientID string `json:"patient_id,omitempty"`
|
||||||
PatientName string `json:"patient_name,omitempty"`
|
PatientName string `json:"patient_name,omitempty"`
|
||||||
AccessionNumber string `json:"accession_number,omitempty"` // For backward compatibility
|
StudyIUIDs []string `json:"study_iuids,omitempty"`
|
||||||
AccessionNumbers []string `json:"accession_numbers,omitempty"` // Multiple accession numbers
|
AccessionNumbers []string `json:"accession_numbers,omitempty"`
|
||||||
StudyIUID string `json:"study_iuid,omitempty"` // For backward compatibility
|
|
||||||
StudyIUIDs []string `json:"study_iuids,omitempty"` // Multiple study IUIDs
|
|
||||||
|
|
||||||
// Navigation and permissions
|
// Navigation and permissions
|
||||||
HomeURL string `json:"home_url,omitempty"`
|
HomeURL string `json:"home_url,omitempty"`
|
||||||
@@ -76,12 +74,6 @@ func (m *JWTManager) GenerateAccessToken(userID, email, role, userName string, a
|
|||||||
if val, ok := additionalClaims["patient_name"].(string); ok {
|
if val, ok := additionalClaims["patient_name"].(string); ok {
|
||||||
claims.PatientName = val
|
claims.PatientName = val
|
||||||
}
|
}
|
||||||
if val, ok := additionalClaims["accession_number"].(string); ok {
|
|
||||||
claims.AccessionNumber = val
|
|
||||||
}
|
|
||||||
if val, ok := additionalClaims["study_iuid"].(string); ok {
|
|
||||||
claims.StudyIUID = val
|
|
||||||
}
|
|
||||||
if val, ok := additionalClaims["home_url"].(string); ok {
|
if val, ok := additionalClaims["home_url"].(string); ok {
|
||||||
claims.HomeURL = val
|
claims.HomeURL = val
|
||||||
}
|
}
|
||||||
@@ -128,12 +120,6 @@ func (m *JWTManager) GenerateRefreshToken(userID, email, role, userName string,
|
|||||||
if val, ok := additionalClaims["patient_name"].(string); ok {
|
if val, ok := additionalClaims["patient_name"].(string); ok {
|
||||||
claims.PatientName = val
|
claims.PatientName = val
|
||||||
}
|
}
|
||||||
if val, ok := additionalClaims["accession_number"].(string); ok {
|
|
||||||
claims.AccessionNumber = val
|
|
||||||
}
|
|
||||||
if val, ok := additionalClaims["study_iuid"].(string); ok {
|
|
||||||
claims.StudyIUID = val
|
|
||||||
}
|
|
||||||
if val, ok := additionalClaims["home_url"].(string); ok {
|
if val, ok := additionalClaims["home_url"].(string); ok {
|
||||||
claims.HomeURL = val
|
claims.HomeURL = val
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user