add: cors handler route and readme
This commit is contained in:
@@ -2,7 +2,8 @@ package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
@@ -31,105 +32,70 @@ func NewAuthService(jwtManager *auth.JWTManager) *AuthService {
|
||||
|
||||
// Login authenticates a user and generates tokens
|
||||
func (s *AuthService) Login(email, password string) (*models.LoginResponse, error) {
|
||||
// For now, use hardcoded credentials
|
||||
// TODO: In a real implementation, you would query the database
|
||||
if email == "admin" && password == "admin" {
|
||||
// Create a dummy user
|
||||
user := &models.User{
|
||||
ID: "1",
|
||||
Email: "admin",
|
||||
Role: "expertise_doctor",
|
||||
Name: "Admin User",
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
UpdatedAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
// Generate tokens
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshToken, err := s.jwtManager.GenerateRefreshToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: In a real implementation, you would store the refresh token in the database
|
||||
// For example:
|
||||
// s.storeRefreshToken(user.ID, refreshToken)
|
||||
|
||||
// Determine redirect URL based on role
|
||||
redirectURL := "/viewer"
|
||||
if user.Role == "ref_doctor" || user.Role == "expertise_doctor" {
|
||||
redirectURL = "/studylist"
|
||||
}
|
||||
|
||||
return &models.LoginResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
User: user,
|
||||
RedirectURL: redirectURL,
|
||||
}, nil
|
||||
} else if email == "patient" && password == "patient" {
|
||||
// Create a patient user
|
||||
user := &models.User{
|
||||
ID: "2",
|
||||
Email: "patient",
|
||||
Role: "patient",
|
||||
Name: "Patient User",
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
UpdatedAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
// Generate tokens with patient-specific claims
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshToken, err := s.jwtManager.GenerateRefreshToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.LoginResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
User: user,
|
||||
RedirectURL: "/viewer",
|
||||
}, nil
|
||||
} else if email == "doctor" && password == "doctor" {
|
||||
// Create a referring doctor user
|
||||
user := &models.User{
|
||||
ID: "3",
|
||||
Email: "doctor",
|
||||
Role: "ref_doctor",
|
||||
Name: "Doctor User",
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
UpdatedAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
// Generate tokens
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshToken, err := s.jwtManager.GenerateRefreshToken(user.ID, user.Email, user.Role)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.LoginResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
User: user,
|
||||
RedirectURL: "/studylist",
|
||||
}, nil
|
||||
// Find user in mock data
|
||||
user := models.FindUserByCredentials(email, password)
|
||||
if user == nil {
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
|
||||
return nil, ErrInvalidCredentials
|
||||
// Create token claims based on user role
|
||||
additionalClaims := make(map[string]string)
|
||||
var redirectURL string
|
||||
|
||||
switch user.Role {
|
||||
case "patient":
|
||||
// Get patient data
|
||||
patientData := models.FindPatientDataByUserID(user.ID)
|
||||
if patientData == nil {
|
||||
return nil, ErrUserNotFound
|
||||
}
|
||||
|
||||
// Set patient-specific claims
|
||||
additionalClaims["patient_id"] = patientData.PatientID
|
||||
additionalClaims["patient_name"] = patientData.PatientName
|
||||
additionalClaims["accession_number"] = patientData.AccessionNumber
|
||||
additionalClaims["study_iuid"] = patientData.StudyIUID
|
||||
additionalClaims["home_url"] = fmt.Sprintf("viewer?StudyInstanceUIDs=%s", patientData.StudyIUID)
|
||||
additionalClaims["study_list"] = "disabled"
|
||||
|
||||
redirectURL = fmt.Sprintf("/viewer?StudyInstanceUIDs=%s", patientData.StudyIUID)
|
||||
|
||||
case "ref_doctor":
|
||||
// Set referring doctor claims
|
||||
encodedName := url.QueryEscape(user.Name)
|
||||
filterURL := fmt.Sprintf("studies?limit=101&offset=0&fuzzymatching=false&includefield=00081030,00080060,00080090&00080090=%s", encodedName)
|
||||
|
||||
additionalClaims["home_url"] = "/"
|
||||
additionalClaims["study_list"] = "enabled"
|
||||
additionalClaims["filter_url"] = filterURL
|
||||
|
||||
redirectURL = "/"
|
||||
|
||||
case "expertise_doctor":
|
||||
// Expertise doctors have full access
|
||||
additionalClaims["home_url"] = "/"
|
||||
additionalClaims["study_list"] = "enabled"
|
||||
|
||||
redirectURL = "/"
|
||||
}
|
||||
|
||||
// Generate tokens
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(user.ID, user.Email, user.Role, user.Name, additionalClaims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refreshToken, err := s.jwtManager.GenerateRefreshToken(user.ID, user.Email, user.Role, user.Name, additionalClaims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.LoginResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
User: user,
|
||||
RedirectURL: redirectURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RefreshToken generates a new access token using a refresh token
|
||||
@@ -145,9 +111,32 @@ func (s *AuthService) RefreshToken(refreshToken string) (string, error) {
|
||||
return "", errors.New("invalid token type")
|
||||
}
|
||||
|
||||
// TODO: In a real implementation, you would check if the token is in the database and not revoked
|
||||
// Here we just generate a new access token
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(claims.UserID, claims.Email, claims.Role)
|
||||
// Build additionalClaims from the refresh token
|
||||
additionalClaims := make(map[string]string)
|
||||
if claims.PatientID != "" {
|
||||
additionalClaims["patient_id"] = claims.PatientID
|
||||
}
|
||||
if 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 != "" {
|
||||
additionalClaims["home_url"] = claims.HomeURL
|
||||
}
|
||||
if claims.StudyList != "" {
|
||||
additionalClaims["study_list"] = claims.StudyList
|
||||
}
|
||||
if claims.FilterURL != "" {
|
||||
additionalClaims["filter_url"] = claims.FilterURL
|
||||
}
|
||||
|
||||
// Generate a new access token with the same claims
|
||||
accessToken, err := s.jwtManager.GenerateAccessToken(claims.UserID, claims.Email, claims.Role, claims.UserName, additionalClaims)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -179,39 +168,11 @@ func CheckPassword(password, hash string) error {
|
||||
// storeRefreshToken stores a refresh token in the database
|
||||
func (s *AuthService) storeRefreshToken(userID, token string) error {
|
||||
// TODO: In a real implementation, this would insert a record in the database
|
||||
// For example:
|
||||
/*
|
||||
refreshToken := &models.RefreshToken{
|
||||
ID: uuid.New().String(),
|
||||
UserID: userID,
|
||||
Token: token,
|
||||
ExpiresAt: time.Now().Add(7 * 24 * time.Hour).Format(time.RFC3339),
|
||||
IsRevoked: false,
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
_, err := s.db.NamedExec(
|
||||
`INSERT INTO refresh_tokens (id, user_id, token, expires_at, is_revoked, created_at)
|
||||
VALUES (:id, :user_id, :token, :expires_at, :is_revoked, :created_at)`,
|
||||
refreshToken,
|
||||
)
|
||||
return err
|
||||
*/
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// revokeRefreshToken marks a refresh token as revoked
|
||||
func (s *AuthService) revokeRefreshToken(token string) error {
|
||||
// TODO: In a real implementation, this would update a record in the database
|
||||
// For example:
|
||||
/*
|
||||
_, err := s.db.Exec(
|
||||
"UPDATE refresh_tokens SET is_revoked = true WHERE token = ?",
|
||||
token,
|
||||
)
|
||||
return err
|
||||
*/
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user