Files
go-ohif-proxy/internal/api/routes.go
mario c35ec4180d Squashed commit of the following:
commit d2ec8c0f07
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Thu May 15 15:42:33 2025 +0700

    add: db tx commit and rollback implementation

commit 264435f67e
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Thu May 15 14:34:20 2025 +0700

    fix: shortlink generation logic update/create

commit 047ab1937a
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Thu May 15 11:06:04 2025 +0700

    fix: if multiple studies patient, show first study by default

commit c13f834b92
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Thu May 15 09:46:32 2025 +0700

    add: register and login with DB query AND some struct type correction

commit dd4451c2a8
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Wed May 14 10:23:33 2025 +0700

    new file structure & koneksi ke DB

commit 8289881df3
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 16:49:07 2025 +0700

    edit: rm debug route

commit dd784da232
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 15:44:11 2025 +0700

    add: implement shortlink

commit 2687a761cc
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 11:47:19 2025 +0700

    add new dummy doctor user

commit eb67eaca46
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 11:46:28 2025 +0700

    add: ref_doctor studylist filter

commit 0d4825d152
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 10:07:16 2025 +0700

    edit study_iuids & accNum in patient jwt to array

commit 2d1f135fda
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Tue May 13 09:52:45 2025 +0700

    patient see their multiple studies

commit 13bb380f51
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Fri May 9 10:13:16 2025 +0700

    add: cors handler route and readme

commit 6c9ab574ce
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Mon May 5 11:50:36 2025 +0700

    add: login & token validation tapi belum connect ke DB

commit 297c9a6a01
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Mon Apr 28 15:37:02 2025 +0700

    add readme.md

commit 9b8e0260f3
Author: mario <dev.mario@sismedika@gmail.com>
Date:   Mon Apr 7 15:46:07 2025 +0700

    connected-to-google

commit f340bc5916
Author: mario <dev.mario@sismedika.com>
Date:   Mon Apr 7 11:14:18 2025 +0700

    init
2025-05-15 15:50:40 +07:00

143 lines
5.1 KiB
Go

package api
import (
"net/http"
"time"
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/config"
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/api/handlers"
apiMiddleware "devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/api/middleware"
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/api/service"
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/auth"
"devone.aplikasi.web.id/gitea/mario/go-ohif-proxy/internal/proxy"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"go.uber.org/zap"
)
// SetupRouter configures and returns the API router
func SetupRouter(cfg *config.Config, logger *zap.Logger) http.Handler {
r := chi.NewRouter()
// Base middleware
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Recoverer)
r.Use(apiMiddleware.Logger(logger))
// CORS configuration
r.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"*"}, // In production, restrict this to your frontend domains
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "X-Requested-With"},
ExposedHeaders: []string{"Link", "Content-Length", "Content-Disposition", "Content-Type"},
AllowCredentials: true,
MaxAge: 300, // Maximum value not ignored by any of major browsers
}))
r.Options("/*", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
// Initialize Google auth client for proxy
googleAuth, err := auth.NewGoogleClient(cfg.Google.CredentialsPath)
if err != nil {
logger.Fatal("Failed to initialize Google auth client", zap.Error(err))
}
// Initialize Healthcare API client
healthcareClient := proxy.NewClient(googleAuth, cfg.Google)
// Initialize JWT auth service
jwtSecret := cfg.Auth.JWTSecret
if jwtSecret == "" {
logger.Warn("JWT secret not provided in config, using default value. This is insecure for production!")
jwtSecret = "vQ6PQqUyh7pBNOytClgN+Nw1XBq7F8Qo6VP3VwIqvHY="
}
// Convert config values to time.Duration
accessExpiry := time.Duration(cfg.Auth.AccessTokenExpiry) * time.Minute
refreshExpiry := time.Duration(cfg.Auth.RefreshTokenExpiry) * time.Hour
// Create JWT manager with config values
jwtManager := auth.NewJWTManager(jwtSecret, accessExpiry, refreshExpiry)
// Initialize services with domain-specific repositories
authService := service.NewAuthService(jwtManager)
// Initialize shortlink service with config values
shortLinkService := service.NewShortLinkService(
jwtManager,
logger,
cfg.Shortlink.BaseURL,
cfg.Shortlink.DefaultExpiryHours,
cfg.Shortlink.MaxAttempts,
)
// Public routes that don't require authentication
r.Group(func(r chi.Router) {
// Health check
r.Get("/health", handlers.HealthCheck)
// Authentication endpoints
r.Route("/auth", func(r chi.Router) {
authHandler := handlers.NewAuthHandler(logger, authService)
r.Post("/login", authHandler.Login)
r.Post("/refresh", authHandler.RefreshToken)
r.Post("/logout", authHandler.Logout)
// Registration endpoint
registerService := service.NewRegisterService(logger)
registerHandler := handlers.NewRegisterHandler(logger, registerService)
r.Post("/register", registerHandler.Register)
// ShortLink authentication - no auth required
shortLinkHandler := handlers.NewShortLinkHandler(logger, shortLinkService)
r.Post("/shortlink", shortLinkHandler.ShortLinkAuth)
})
})
// Protected routes that require authentication
r.Group(func(r chi.Router) {
// Apply authentication middleware
r.Use(apiMiddleware.Auth(authService, logger))
// Shortlink generation - only for admin and expertise_doctor roles
shortLinkHandler := handlers.NewShortLinkHandler(logger, shortLinkService)
r.Post("/generate-link", shortLinkHandler.GenerateShortLink)
// DICOM Web routes
r.Route("/dicomWeb", func(r chi.Router) {
// Add audit logging middleware to DICOM routes
r.Use(apiMiddleware.AuditLog(logger))
// Add patient view restriction for patient role
r.Use(apiMiddleware.PatientViewRestriction(logger))
// Create handler for all DICOM requests
dicomHandler := handlers.NewDicomHandler(healthcareClient, logger)
// Common routes for studies with role-specific handling
r.Route("/studies", func(r chi.Router) {
// StudyInstanceUID parameter routes - accessible by all roles
r.Get("/{studyInstanceUID}", dicomHandler.ForwardRequest) // Study details
r.Get("/{studyInstanceUID}/series", dicomHandler.ForwardRequest) // Series list for study
// Deep hierarchy routes - accessible by patients and all doctors
r.Get("/{studyInstanceUID}/series/{seriesUID}/metadata", dicomHandler.ForwardRequest)
r.Get("/{studyInstanceUID}/series/{seriesUID}/instances/{instanceUID}/frames/{frame}", dicomHandler.ForwardRequest)
// Query routes - accessible by all roles
r.Get("/", dicomHandler.ForwardRequest) // Study list with filters
})
// Expertise doctors have full access to all DICOM endpoints
r.With(apiMiddleware.RoleRequired("expertise_doctor")).HandleFunc("/*", dicomHandler.ForwardRequest)
})
})
return r
}