init push
This commit is contained in:
834
cmd/api/startup.go
Normal file
834
cmd/api/startup.go
Normal file
@@ -0,0 +1,834 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"wucher/internal/app/api"
|
||||
queueapp "wucher/internal/app/queueing"
|
||||
samlauth "wucher/internal/auth"
|
||||
"wucher/internal/config"
|
||||
filemanager "wucher/internal/domain/file_manager"
|
||||
filemanagerrealtime "wucher/internal/realtime/filemanager"
|
||||
helicopterfilerealtime "wucher/internal/realtime/helicopterfile"
|
||||
"wucher/internal/repository/mysql"
|
||||
s3repo "wucher/internal/repository/s3"
|
||||
"wucher/internal/resilience"
|
||||
"wucher/internal/service"
|
||||
pkglogger "wucher/internal/shared/pkg/logger"
|
||||
tzpkg "wucher/internal/shared/pkg/timezone"
|
||||
userctx "wucher/internal/shared/pkg/userctx"
|
||||
"wucher/internal/transport/http/handlers"
|
||||
)
|
||||
|
||||
type Repositories struct {
|
||||
User *mysql.UserRepository
|
||||
Contact *mysql.ContactRepository
|
||||
Role *mysql.RoleRepository
|
||||
Helicopter *mysql.HelicopterRepository
|
||||
HelicopterUsage *mysql.HelicopterUsageRepository
|
||||
FlightInspection *mysql.FlightInspectionRepository
|
||||
Flight *mysql.FlightRepository
|
||||
FlightData *mysql.FlightDataRepository
|
||||
Mission *mysql.MissionRepository
|
||||
ReserveAc *mysql.ReserveAcRepository
|
||||
HelicopterFile *mysql.HelicopterFileRepository
|
||||
FlightInspectionFileChecklist *mysql.FlightInspectionFileChecklistRepository
|
||||
BeforeFlightInspection *mysql.BeforeFlightInspectionRepository
|
||||
AfterFlightInspection *mysql.AfterFlightInspectionRepository
|
||||
FMReport *mysql.FMReportRepository
|
||||
FlightPrepCheck *mysql.FlightPrepCheckRepository
|
||||
Facility *mysql.FacilityRepository
|
||||
Base *mysql.BaseRepository
|
||||
Medicine *mysql.MedicineRepository
|
||||
Vocation *mysql.VocationRepository
|
||||
Opc *mysql.OpcRepository
|
||||
ForcesPresent *mysql.ForcesPresentRepository
|
||||
Hospital *mysql.HospitalRepository
|
||||
HealthInsuranceCompanies *mysql.HealthInsuranceCompaniesRepository
|
||||
FederalState *mysql.FederalStateRepository
|
||||
ICAO *mysql.ICAORepository
|
||||
Land *mysql.LandRepository
|
||||
Complaint *mysql.ComplaintRepository
|
||||
EASARelease *mysql.EASAReleaseRepository
|
||||
ActionSignoff *mysql.ActionSignoffRepository
|
||||
OtherPerson *mysql.OtherPersonRepository
|
||||
MCF *mysql.MCFRepository
|
||||
FleetHistory *mysql.FleetHistoryRepository
|
||||
HEMSOperationalData *mysql.HEMSOperationalDataRepository
|
||||
HEMSOperationCategory *mysql.HEMSOperationCategoryRepository
|
||||
HEMSOperation *mysql.HEMSOperationRepository
|
||||
MasterSettings *mysql.MasterSettingsRepository
|
||||
FileManagerFolder *mysql.FileManagerFolderRepository
|
||||
FileManagerFile *mysql.FileManagerFileRepository
|
||||
FileManagerAttachment *mysql.FileManagerAttachmentRepository
|
||||
DutyRoster *mysql.DutyRosterRepository
|
||||
AirRescuerChecklist *mysql.AirRescuerChecklistRepository
|
||||
InsurancePatientData *mysql.InsurancePatientDataRepository
|
||||
PatientData *mysql.PatientDataRepository
|
||||
DUL *mysql.DULRepository
|
||||
FleetStatus *mysql.FleetStatusRepository
|
||||
TokenStore *mysql.TokenStore
|
||||
Auth *mysql.AuthRepository
|
||||
Audit *mysql.AuditRepository
|
||||
}
|
||||
|
||||
type Infrastructure struct {
|
||||
DB *gorm.DB
|
||||
Logger *slog.Logger
|
||||
SQSBreaker *resilience.Executor
|
||||
FileStorage filemanager.ObjectStorage
|
||||
EmailQueue service.EmailQueue
|
||||
FileQueue filemanager.FileProcessingQueue
|
||||
FileStatusHub *filemanagerrealtime.Hub
|
||||
HelicopterFileHub *helicopterfilerealtime.Hub
|
||||
FileTrashPolicy config.FileManagerTrashPolicyConfig
|
||||
FileLifecycle config.FileManagerLifecycleConfig
|
||||
}
|
||||
|
||||
type Services struct {
|
||||
User *service.UserService
|
||||
Contact *service.ContactService
|
||||
Role *service.RoleService
|
||||
Helicopter *service.HelicopterService
|
||||
HelicopterUsage *service.HelicopterUsageService
|
||||
FlightInspection *service.FlightInspectionService
|
||||
Flight *service.FlightService
|
||||
FlightData *service.FlightDataService
|
||||
Mission *service.MissionService
|
||||
ReserveAc *service.ReserveAcService
|
||||
Takeover *service.TakeoverService
|
||||
OtherPerson *service.OtherPersonService
|
||||
HelicopterFile *service.HelicopterFileService
|
||||
FlightInspectionChecklist *service.FlightInspectionFileChecklistService
|
||||
BeforeFlightInspection *service.BeforeFlightInspectionService
|
||||
AfterFlightInspection *service.AfterFlightInspectionService
|
||||
FMReport *service.FMReportService
|
||||
FlightPrepCheck *service.FlightPrepCheckService
|
||||
Facility *service.FacilityService
|
||||
Base *service.BaseService
|
||||
Medicine *service.MedicineService
|
||||
Vocation *service.VocationService
|
||||
Opc *service.OpcService
|
||||
ForcesPresent *service.ForcesPresentService
|
||||
Hospital *service.HospitalService
|
||||
HealthInsuranceCompanies *service.HealthInsuranceCompaniesService
|
||||
FederalState *service.FederalStateService
|
||||
ICAO *service.ICAOService
|
||||
Land *service.LandService
|
||||
Complaint *service.ComplaintService
|
||||
EASARelease *service.EASAReleaseService
|
||||
ActionSignoff *service.ActionSignoffService
|
||||
MCF *service.MCFService
|
||||
FleetHistory *service.FleetHistoryService
|
||||
HEMSOperationalData *service.HEMSOperationalDataService
|
||||
HEMSOperationCategory *service.HEMSOperationCategoryService
|
||||
HEMSOperation *service.HEMSOperationService
|
||||
MasterSettings *service.MasterSettingsService
|
||||
FileManager *service.FileManagerService
|
||||
DutyRoster *service.DutyRosterService
|
||||
AirRescuerChecklist *service.AirRescuerChecklistService
|
||||
InsurancePatientData *service.InsurancePatientDataService
|
||||
PatientData *service.PatientDataService
|
||||
DUL *service.DULService
|
||||
FleetStatus *service.FleetStatusService
|
||||
WOPI *service.WOPIService
|
||||
Auth *service.AuthService
|
||||
Audit *service.AuditLogService
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
User *handlers.UserHandler
|
||||
Contact *handlers.ContactHandler
|
||||
Health *handlers.HealthHandler
|
||||
BuildInfo *handlers.BuildInfoHandler
|
||||
Auth *handlers.AuthHandler
|
||||
Role *handlers.RoleHandler
|
||||
Helicopter *handlers.HelicopterHandler
|
||||
HelicopterUsage *handlers.HelicopterUsageHandler
|
||||
HelicopterFile *handlers.HelicopterFileHandler
|
||||
Flight *handlers.FlightHandler
|
||||
FlightData *handlers.FlightDataHandler
|
||||
Mission *handlers.MissionHandler
|
||||
FMReport *handlers.FMReportHandler
|
||||
ReserveAc *handlers.ReserveAcHandler
|
||||
Takeover *handlers.TakeoverHandler
|
||||
OtherPerson *handlers.OtherPersonHandler
|
||||
Facility *handlers.FacilityHandler
|
||||
Base *handlers.BaseHandler
|
||||
Medicine *handlers.MedicineHandler
|
||||
Vocation *handlers.VocationHandler
|
||||
Opc *handlers.OpcHandler
|
||||
ForcesPresent *handlers.ForcesPresentHandler
|
||||
Hospital *handlers.HospitalHandler
|
||||
HealthInsuranceCompanies *handlers.HealthInsuranceCompaniesHandler
|
||||
FederalState *handlers.FederalStateHandler
|
||||
ICAO *handlers.ICAOHandler
|
||||
Land *handlers.LandHandler
|
||||
MasterSettings *handlers.MasterSettingsHandler
|
||||
Branding *handlers.BrandingHandler
|
||||
FileManagerFolder *handlers.FileManagerFolderHandler
|
||||
FileManagerFile *handlers.FileManagerFileHandler
|
||||
FileManagerAttachment *handlers.FileManagerAttachmentHandler
|
||||
FileManagerEvents *handlers.FileManagerEventsHandler
|
||||
HelicopterFileEvents *handlers.HelicopterFileEventsHandler
|
||||
DutyRoster *handlers.DutyRosterHandler
|
||||
AirRescuerChecklist *handlers.AirRescuerChecklistHandler
|
||||
InsurancePatientData *handlers.InsurancePatientDataHandler
|
||||
PatientData *handlers.PatientDataHandler
|
||||
DUL *handlers.DULHandler
|
||||
FleetStatus *handlers.FleetStatusHandler
|
||||
HEMSOperationalData *handlers.HEMSOperationalDataHandler
|
||||
HEMSOperationCategory *handlers.HEMSOperationCategoryHandler
|
||||
HEMSOperation *handlers.HEMSOperationHandler
|
||||
Complaint *handlers.ComplaintHandler
|
||||
EASARelease *handlers.EASAReleaseHandler
|
||||
ActionSignoff *handlers.ActionSignoffHandler
|
||||
MCF *handlers.MCFHandler
|
||||
}
|
||||
|
||||
func initializeDatabase(mysqlCfg config.MySQLConfig) (*gorm.DB, error) {
|
||||
return mysql.Connect(mysqlCfg)
|
||||
}
|
||||
|
||||
func bootstrapData(db *gorm.DB) error {
|
||||
if err := mysql.AutoMigrate(db); err != nil {
|
||||
return fmt.Errorf("auto migrate: %w", err)
|
||||
}
|
||||
if err := db.Exec("UPDATE users SET timezone = ? WHERE timezone IS NULL OR timezone = ''", tzpkg.Default).Error; err != nil {
|
||||
return fmt.Errorf("seed users timezone default: %w", err)
|
||||
}
|
||||
if err := api.SeedRoles(db); err != nil {
|
||||
return fmt.Errorf("seed roles: %w", err)
|
||||
}
|
||||
if err := api.SeedPermissions(db); err != nil {
|
||||
return fmt.Errorf("seed permissions: %w", err)
|
||||
}
|
||||
if err := api.SeedRolePermissions(db); err != nil {
|
||||
return fmt.Errorf("seed role permissions: %w", err)
|
||||
}
|
||||
if err := api.SeedBaseCategories(db); err != nil {
|
||||
return fmt.Errorf("seed base categories: %w", err)
|
||||
}
|
||||
if strings.EqualFold(strings.TrimSpace(os.Getenv("SEED_ROSTER_USERS")), "true") {
|
||||
if err := api.SeedRosterUsers(db); err != nil {
|
||||
return fmt.Errorf("seed roster users: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initializeRepositories(db *gorm.DB) (*Repositories, error) {
|
||||
if db == nil {
|
||||
return nil, errors.New("database is required")
|
||||
}
|
||||
repos := &Repositories{
|
||||
User: mysql.NewUserRepository(db),
|
||||
Contact: mysql.NewContactRepository(db),
|
||||
Role: mysql.NewRoleRepository(db),
|
||||
Helicopter: mysql.NewHelicopterRepository(db),
|
||||
HelicopterUsage: mysql.NewHelicopterUsageRepository(db),
|
||||
FlightInspection: mysql.NewFlightInspectionRepository(db),
|
||||
Flight: mysql.NewFlightRepository(db),
|
||||
FlightData: mysql.NewFlightDataRepository(db),
|
||||
Mission: mysql.NewMissionRepository(db),
|
||||
ReserveAc: mysql.NewReserveAcRepository(db),
|
||||
HelicopterFile: mysql.NewHelicopterFileRepository(db),
|
||||
FlightInspectionFileChecklist: mysql.NewFlightInspectionFileChecklistRepository(db),
|
||||
BeforeFlightInspection: mysql.NewBeforeFlightInspectionRepository(db),
|
||||
AfterFlightInspection: mysql.NewAfterFlightInspectionRepository(db),
|
||||
FMReport: mysql.NewFMReportRepository(db),
|
||||
FlightPrepCheck: mysql.NewFlightPrepCheckRepository(db),
|
||||
Facility: mysql.NewFacilityRepository(db),
|
||||
Base: mysql.NewBaseRepository(db),
|
||||
Medicine: mysql.NewMedicineRepository(db),
|
||||
Vocation: mysql.NewVocationRepository(db),
|
||||
Opc: mysql.NewOpcRepository(db),
|
||||
ForcesPresent: mysql.NewForcesPresentRepository(db),
|
||||
Hospital: mysql.NewHospitalRepository(db),
|
||||
HealthInsuranceCompanies: mysql.NewHealthInsuranceCompaniesRepository(db),
|
||||
FederalState: mysql.NewFederalStateRepository(db),
|
||||
ICAO: mysql.NewICAORepository(db),
|
||||
Land: mysql.NewLandRepository(db),
|
||||
Complaint: mysql.NewComplaintRepository(db),
|
||||
EASARelease: mysql.NewEASAReleaseRepository(db),
|
||||
ActionSignoff: mysql.NewActionSignoffRepository(db),
|
||||
OtherPerson: mysql.NewOtherPersonRepository(db),
|
||||
MCF: mysql.NewMCFRepository(db),
|
||||
FleetHistory: mysql.NewFleetHistoryRepository(db),
|
||||
HEMSOperationalData: mysql.NewHEMSOperationalDataRepository(db),
|
||||
HEMSOperationCategory: mysql.NewHEMSOperationCategoryRepository(db),
|
||||
HEMSOperation: mysql.NewHEMSOperationRepository(db),
|
||||
MasterSettings: mysql.NewMasterSettingsRepository(db),
|
||||
FileManagerFolder: mysql.NewFileManagerFolderRepository(db),
|
||||
FileManagerFile: mysql.NewFileManagerFileRepository(db),
|
||||
FileManagerAttachment: mysql.NewFileManagerAttachmentRepository(db),
|
||||
DutyRoster: mysql.NewDutyRosterRepository(db),
|
||||
AirRescuerChecklist: mysql.NewAirRescuerChecklistRepository(db),
|
||||
InsurancePatientData: mysql.NewInsurancePatientDataRepository(db),
|
||||
PatientData: mysql.NewPatientDataRepository(db),
|
||||
DUL: mysql.NewDULRepository(db),
|
||||
FleetStatus: mysql.NewFleetStatusRepository(db),
|
||||
TokenStore: mysql.NewTokenStore(db),
|
||||
Auth: mysql.NewAuthRepository(db),
|
||||
Audit: mysql.NewAuditRepository(db),
|
||||
}
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
func initializeInfrastructure(ctx context.Context, appCfg config.AppConfig, db *gorm.DB) (*Infrastructure, error) {
|
||||
appLogger := pkglogger.New(appCfg.Logging).With("component", "api")
|
||||
slog.SetDefault(appLogger)
|
||||
|
||||
if err := config.ValidateDistinctQueueURLs(appCfg.SQS, appCfg.FileSQS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resCfg := appCfg.Resilience
|
||||
sqsBreaker := resilience.NewExecutor("sqs", resCfg.SQS, appLogger, resilience.ClassifySQSError)
|
||||
|
||||
var emailQueue service.EmailQueue
|
||||
if !appCfg.Queue.OutboxEnabled {
|
||||
emailProducer, err := queueapp.NewEmailProducer(ctx, appCfg.Queue, appCfg.SQS, sqsBreaker, appLogger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
emailQueue = service.AdaptEmailQueue(emailProducer)
|
||||
}
|
||||
|
||||
var fileStorage filemanager.ObjectStorage
|
||||
if appCfg.FileStorage.Bucket != "" && appCfg.FileStorage.Region != "" {
|
||||
storage, err := s3repo.NewFileObjectStorage(ctx, appCfg.FileStorage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileStorage = storage
|
||||
}
|
||||
|
||||
var fileQueue filemanager.FileProcessingQueue
|
||||
if !appCfg.FileQueue.OutboxEnabled && strings.TrimSpace(appCfg.FileSQS.QueueURL) != "" {
|
||||
fileProducer, err := queueapp.NewFileProcessingProducer(ctx, appCfg.FileQueue, appCfg.FileSQS, sqsBreaker, appLogger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileQueue = service.AdaptFileProcessingQueue(fileProducer)
|
||||
}
|
||||
|
||||
return &Infrastructure{
|
||||
DB: db,
|
||||
Logger: appLogger,
|
||||
SQSBreaker: sqsBreaker,
|
||||
FileStorage: fileStorage,
|
||||
EmailQueue: emailQueue,
|
||||
FileQueue: fileQueue,
|
||||
FileStatusHub: filemanagerrealtime.NewHub(64, appLogger),
|
||||
HelicopterFileHub: helicopterfilerealtime.NewHub(64, appLogger),
|
||||
FileTrashPolicy: config.LoadFileManagerTrashPolicyConfigFromEnv(),
|
||||
FileLifecycle: config.LoadFileManagerLifecycleConfigFromEnv(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeServices(appCfg config.AppConfig, repos *Repositories, infra *Infrastructure) (*Services, error) {
|
||||
if repos == nil {
|
||||
return nil, errors.New("repositories are required")
|
||||
}
|
||||
if infra == nil {
|
||||
return nil, errors.New("infrastructure is required")
|
||||
}
|
||||
|
||||
var protector service.SecretProtector
|
||||
if p, err := service.NewAESGCMProtectorFromBase64(appCfg.Auth.TOTPSecretKeyB64); err == nil {
|
||||
protector = p
|
||||
}
|
||||
|
||||
fileManagerDeps := service.FileManagerServiceDependencies{
|
||||
Storage: infra.FileStorage,
|
||||
FileQueue: infra.FileQueue,
|
||||
UploadPolicy: filemanager.FileUploadPolicy{},
|
||||
TrashRetention: infra.FileTrashPolicy.Retention,
|
||||
FileStatusEvents: repos.FileManagerFile,
|
||||
Logger: infra.Logger,
|
||||
EnableS3Tagging: infra.FileLifecycle.EnableS3Tagging,
|
||||
}
|
||||
if appCfg.FileQueue.OutboxEnabled {
|
||||
fileManagerDeps.FileOutbox = repos.FileManagerFile
|
||||
fileManagerDeps.FileOutboxSerializer = queueapp.NewFileProcessingSerializer(appCfg.FileQueue, appCfg.FileSQS)
|
||||
}
|
||||
fileManagerDeps.UploadPolicy = filemanager.FileUploadPolicy{
|
||||
MaxFileSizeBytes: appCfg.FileUpload.MaxFileSizeBytes,
|
||||
AllowedMimeTypes: appCfg.FileUpload.AllowedMimeTypes,
|
||||
AllowedExtensions: appCfg.FileUpload.AllowedExtensions,
|
||||
AllowEmptyFile: appCfg.FileUpload.AllowEmptyFile,
|
||||
MaxFilenameLength: appCfg.FileUpload.MaxFilenameLength,
|
||||
}
|
||||
|
||||
flightDataSvc := service.NewFlightDataService(repos.FlightData)
|
||||
flightSvc := service.NewFlightService(repos.Flight)
|
||||
fileManagerSvc := service.NewFileManagerService(repos.FileManagerFolder, repos.FileManagerFile, repos.FileManagerAttachment, fileManagerDeps)
|
||||
helicopterSvc := service.NewHelicopterService(repos.Helicopter)
|
||||
helicopterUsageSvc := service.NewHelicopterUsageService(repos.HelicopterUsage)
|
||||
afterFlightInspectionSvc := service.NewAfterFlightInspectionService(repos.AfterFlightInspection)
|
||||
|
||||
services := &Services{
|
||||
User: service.NewUserService(repos.User),
|
||||
Role: service.NewRoleService(repos.Role),
|
||||
Helicopter: helicopterSvc,
|
||||
HelicopterUsage: helicopterUsageSvc,
|
||||
FlightInspection: service.NewFlightInspectionService(repos.FlightInspection),
|
||||
Flight: flightSvc,
|
||||
FlightData: flightDataSvc,
|
||||
Mission: nil,
|
||||
ReserveAc: service.NewReserveAcService(repos.ReserveAc),
|
||||
Takeover: service.NewTakeoverService(infra.DB),
|
||||
HelicopterFile: service.NewHelicopterFileService(repos.HelicopterFile),
|
||||
FlightInspectionChecklist: service.NewFlightInspectionFileChecklistService(repos.FlightInspectionFileChecklist),
|
||||
BeforeFlightInspection: service.NewBeforeFlightInspectionService(repos.BeforeFlightInspection),
|
||||
AfterFlightInspection: afterFlightInspectionSvc,
|
||||
FMReport: service.NewFMReportService(repos.FMReport),
|
||||
FlightPrepCheck: service.NewFlightPrepCheckService(repos.FlightPrepCheck, repos.FlightInspection),
|
||||
Facility: service.NewFacilityService(repos.Facility),
|
||||
Base: service.NewBaseService(repos.Base),
|
||||
Medicine: service.NewMedicineService(repos.Medicine),
|
||||
Vocation: service.NewVocationService(repos.Vocation),
|
||||
Opc: service.NewOpcService(repos.Opc),
|
||||
ForcesPresent: service.NewForcesPresentService(repos.ForcesPresent),
|
||||
Hospital: service.NewHospitalService(repos.Hospital),
|
||||
HealthInsuranceCompanies: service.NewHealthInsuranceCompaniesService(repos.HealthInsuranceCompanies),
|
||||
FederalState: service.NewFederalStateService(repos.FederalState),
|
||||
ICAO: service.NewICAOService(repos.ICAO),
|
||||
Land: service.NewLandService(repos.Land),
|
||||
Complaint: service.NewComplaintService(repos.Complaint),
|
||||
EASARelease: service.NewEASAReleaseService(repos.EASARelease),
|
||||
ActionSignoff: service.NewActionSignoffService(repos.ActionSignoff),
|
||||
OtherPerson: service.NewOtherPersonService(repos.OtherPerson),
|
||||
MCF: service.NewMCFService(repos.MCF),
|
||||
FleetHistory: service.NewFleetHistoryService(repos.FleetHistory),
|
||||
HEMSOperationalData: service.NewHEMSOperationalDataService(repos.HEMSOperationalData),
|
||||
HEMSOperationCategory: service.NewHEMSOperationCategoryService(repos.HEMSOperationCategory),
|
||||
HEMSOperation: service.NewHEMSOperationService(repos.HEMSOperation),
|
||||
MasterSettings: service.NewMasterSettingsService(repos.MasterSettings, service.MasterSettingsServiceDependencies{Protector: protector}),
|
||||
FileManager: fileManagerSvc,
|
||||
DutyRoster: service.NewDutyRosterService(repos.DutyRoster),
|
||||
AirRescuerChecklist: service.NewAirRescuerChecklistService(repos.AirRescuerChecklist),
|
||||
InsurancePatientData: service.NewInsurancePatientDataService(repos.InsurancePatientData),
|
||||
PatientData: service.NewPatientDataService(repos.PatientData),
|
||||
DUL: service.NewDULService(repos.DUL),
|
||||
Audit: service.NewAuditLogService(repos.Audit, service.AuditLogServiceDependencies{QueueSize: appCfg.Audit.QueueSize, Workers: appCfg.Audit.Workers, IPEncryptionKey: appCfg.Auth.IPEncryptionKey}),
|
||||
WOPI: service.NewWOPIService(service.WOPIConfig{
|
||||
TokenSecret: appCfg.WOPI.TokenSecret,
|
||||
ProofSecret: appCfg.WOPI.ProofSecret,
|
||||
DiscoveryURL: appCfg.WOPI.DiscoveryURL,
|
||||
PublicBaseURL: appCfg.WOPI.PublicBaseURL,
|
||||
EditActionURL: appCfg.WOPI.EditActionURL,
|
||||
TokenTTL: appCfg.WOPI.TokenTTL,
|
||||
MaxBodyBytes: appCfg.WOPI.MaxBodyBytes,
|
||||
RequireProof: appCfg.WOPI.RequireProof,
|
||||
}),
|
||||
}
|
||||
services.Mission = service.NewMissionService(repos.Mission, flightSvc, flightDataSvc, afterFlightInspectionSvc)
|
||||
services.FleetStatus = service.NewFleetStatusService(repos.FleetStatus, fileManagerSvc, helicopterSvc, services.Complaint).WithHistory(services.FleetHistory).WithUsage(services.HelicopterUsage)
|
||||
flightDataSvc.WithAOGRecalculator(services.FleetStatus)
|
||||
flightDataSvc.WithMissionResolver(services.Mission)
|
||||
flightDataSvc.WithFlightLookup(services.Flight)
|
||||
flightDataSvc.WithFMReportLookup(services.FMReport)
|
||||
flightDataSvc.WithAfterFlightInspectionLookup(services.AfterFlightInspection)
|
||||
services.FMReport.WithUsageRefresher(services.HelicopterUsage)
|
||||
|
||||
msSSO := service.NewMicrosoftSSO(appCfg.MicrosoftSSO).
|
||||
WithExecutor(resilience.NewExecutor("microsoft_sso", appCfg.Resilience.MicrosoftSSO, infra.Logger, resilience.ClassifyMicrosoftSSOError)).
|
||||
WithConfigResolver(func(ctx context.Context) (config.MicrosoftSSOConfig, error) {
|
||||
cfg, err := services.MasterSettings.LoadMicrosoftEntraRuntimeConfig(ctx)
|
||||
if err == nil {
|
||||
return cfg, nil
|
||||
}
|
||||
// Fallback for local/dev when master settings are missing or stale.
|
||||
// This prevents SSO flows from failing hard when DB-stored settings are invalid.
|
||||
if service.IsMicrosoftSSOConfigComplete(appCfg.MicrosoftSSO) {
|
||||
if infra.Logger != nil {
|
||||
infra.Logger.Warn("microsoft sso runtime config fallback to env", "reason", err.Error())
|
||||
}
|
||||
return appCfg.MicrosoftSSO, nil
|
||||
}
|
||||
return config.MicrosoftSSOConfig{}, err
|
||||
})
|
||||
|
||||
authDeps := service.AuthServiceDependencies{
|
||||
SSO: msSSO,
|
||||
Protector: protector,
|
||||
Config: appCfg.Auth,
|
||||
Audit: services.Audit,
|
||||
EmailBranding: service.NewAuthEmailBrandingResolver(services.MasterSettings, services.FileManager, infra.FileStorage),
|
||||
EmailOTPEnabled: services.MasterSettings.IsLoginEmailOTPEnabled,
|
||||
DisableLegacyNoopEmailQueue: true,
|
||||
}
|
||||
if appCfg.Queue.OutboxEnabled {
|
||||
authDeps.EmailOutbox = repos.Auth
|
||||
authDeps.EmailSerializer = queueapp.NewOutboxSerializer(appCfg.Queue, appCfg.SQS)
|
||||
}
|
||||
services.Auth = service.NewAuthService(
|
||||
repos.Auth,
|
||||
repos.Role,
|
||||
repos.TokenStore,
|
||||
infra.EmailQueue,
|
||||
authDeps,
|
||||
)
|
||||
|
||||
services.Contact = service.NewContactService(repos.Contact, services.Auth)
|
||||
services.HelicopterFile.
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithHelicopterFileEvents(infra.HelicopterFileHub)
|
||||
if infra.FileStorage != nil && !appCfg.FileQueue.OutboxEnabled && strings.TrimSpace(appCfg.FileSQS.QueueURL) == "" {
|
||||
return nil, errors.New("FILE_SQS_QUEUE_URL is required when FILE_QUEUE_OUTBOX_ENABLED=false and file manager upload is enabled")
|
||||
}
|
||||
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func initializeHandlers(services *Services, infra *Infrastructure) (*Handlers, error) {
|
||||
if services == nil {
|
||||
return nil, errors.New("services are required")
|
||||
}
|
||||
if infra == nil {
|
||||
return nil, errors.New("infrastructure is required")
|
||||
}
|
||||
|
||||
fleetStatusHandler := handlers.NewFleetStatusHandler(services.FleetStatus, handlers.FleetStatusDeps{
|
||||
Helicopter: services.Helicopter,
|
||||
Complaint: services.Complaint,
|
||||
EASA: services.EASARelease,
|
||||
History: services.FleetHistory,
|
||||
MCF: services.MCF,
|
||||
Signoff: services.ActionSignoff,
|
||||
Storage: infra.FileStorage,
|
||||
})
|
||||
|
||||
fmReportFlightHandler := handlers.NewFlightHandler(services.Flight).
|
||||
WithAuthService(services.Auth).
|
||||
WithAfterFlightInspectionService(services.AfterFlightInspection).
|
||||
WithFMReportService(services.FMReport).
|
||||
WithFlightDataService(services.FlightData).
|
||||
WithTakeoverService(service.NewTakeoverModuleService(mysql.NewTakeoverRepository(infra.DB))).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithReserveAcService(services.ReserveAc).
|
||||
WithMissionService(services.Mission)
|
||||
|
||||
services.FMReport.WithFleetHistoryBuilder(handlers.NewFMReportFleetHistoryBuilder(fleetStatusHandler, fmReportFlightHandler))
|
||||
services.FMReport.WithReportCodeResolver(fmReportFlightHandler)
|
||||
|
||||
return &Handlers{
|
||||
User: handlers.NewUserHandler(services.User).
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithFileStorage(infra.FileStorage),
|
||||
Contact: handlers.NewContactHandler(services.Contact, services.Auth).
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithFileStorage(infra.FileStorage),
|
||||
Health: handlers.NewHealthHandler(),
|
||||
BuildInfo: handlers.NewBuildInfoHandler(),
|
||||
Auth: handlers.NewAuthHandler(services.Auth).WithFileStorage(infra.FileStorage).WithContactService(services.Contact),
|
||||
Role: handlers.NewRoleHandler(services.Role),
|
||||
Helicopter: handlers.NewHelicopterHandler(services.Helicopter).
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithFileStorage(infra.FileStorage).
|
||||
WithReserveAcService(services.ReserveAc).
|
||||
WithFleetStatusService(services.FleetStatus).
|
||||
WithPINVerifier(services.Auth).
|
||||
WithComplaintService(services.Complaint).
|
||||
WithMCFService(services.MCF).
|
||||
WithHistoryService(services.FleetHistory),
|
||||
HelicopterUsage: handlers.NewHelicopterUsageHandler(services.HelicopterUsage),
|
||||
HelicopterFile: handlers.NewHelicopterFileHandler(services.HelicopterFile).
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithTakeoverService(services.Takeover).
|
||||
WithHelicopterFileEvents(infra.HelicopterFileHub).
|
||||
WithFileStorage(infra.FileStorage),
|
||||
Flight: handlers.NewFlightHandler(services.Flight).
|
||||
WithAuthService(services.Auth).
|
||||
WithAfterFlightInspectionService(services.AfterFlightInspection).
|
||||
WithFMReportService(services.FMReport).
|
||||
WithFlightDataService(services.FlightData).
|
||||
WithTakeoverService(service.NewTakeoverModuleService(mysql.NewTakeoverRepository(infra.DB))).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithReserveAcService(services.ReserveAc).
|
||||
WithMissionService(services.Mission),
|
||||
FlightData: handlers.NewFlightDataHandler(services.FlightData).
|
||||
WithMissionService(services.Mission).
|
||||
WithUserService(services.User).
|
||||
WithHospitalService(services.Hospital).
|
||||
WithICAOService(services.ICAO).
|
||||
WithFacilityService(services.Facility),
|
||||
Mission: handlers.NewMissionHandler(services.Mission).WithFlightDataService(services.FlightData).WithFileStorage(infra.FileStorage).WithFileManagerService(services.FileManager),
|
||||
FMReport: handlers.NewFMReportHandler(services.FMReport).
|
||||
WithFlightHandler(fmReportFlightHandler).
|
||||
WithMissionHandler(handlers.NewMissionHandler(services.Mission).WithFlightDataService(services.FlightData).WithFileStorage(infra.FileStorage).WithFileManagerService(services.FileManager)).
|
||||
WithFlightInspectionService(services.FlightInspection).
|
||||
WithAfterFlightInspectionService(services.AfterFlightInspection).
|
||||
WithHelicopterUsageService(services.HelicopterUsage).
|
||||
WithFleetStatusHandler(fleetStatusHandler).
|
||||
WithTakeoverService(services.Takeover).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithFileStorage(infra.FileStorage).
|
||||
WithFileManagerService(services.FileManager),
|
||||
ReserveAc: handlers.NewReserveAcHandler(services.ReserveAc).
|
||||
WithFlightService(services.Flight).
|
||||
WithFlightDataService(services.FlightData).
|
||||
WithMissionService(services.Mission).
|
||||
WithDutyRosterService(services.DutyRoster).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithFlightInspectionService(services.FlightInspection).
|
||||
WithBeforeFlightInspectionService(services.BeforeFlightInspection).
|
||||
WithAfterFlightInspectionService(services.AfterFlightInspection).
|
||||
WithFMReportService(services.FMReport).
|
||||
WithFlightPrepCheckService(services.FlightPrepCheck).
|
||||
WithHelicopterFileService(services.HelicopterFile).
|
||||
WithFlightInspectionFileChecklistService(services.FlightInspectionChecklist).
|
||||
WithFileStorage(infra.FileStorage),
|
||||
Takeover: handlers.NewTakeoverHandler(infra.DB).
|
||||
WithAuthService(services.Auth).
|
||||
WithBaseService(services.Base).
|
||||
WithFlightService(services.Flight).
|
||||
WithFileManagerService(services.FileManager).
|
||||
WithTakeoverAcService(service.NewTakeoverModuleService(mysql.NewTakeoverRepository(infra.DB))).
|
||||
WithReserveAcService(services.ReserveAc).
|
||||
WithDutyRosterService(services.DutyRoster).
|
||||
WithHelicopterService(services.Helicopter).
|
||||
WithComplaintService(services.Complaint).
|
||||
WithMCFService(services.MCF).
|
||||
WithFleetStatusService(services.FleetStatus).
|
||||
WithFlightInspectionService(services.FlightInspection).
|
||||
WithBeforeFlightInspectionService(services.BeforeFlightInspection).
|
||||
WithFlightPrepCheckService(services.FlightPrepCheck).
|
||||
WithHelicopterFileService(services.HelicopterFile).
|
||||
WithFlightInspectionFileChecklistService(services.FlightInspectionChecklist).
|
||||
WithFileStorage(infra.FileStorage),
|
||||
OtherPerson: handlers.NewOtherPersonHandler(services.OtherPerson),
|
||||
Facility: handlers.NewFacilityHandler(services.Facility),
|
||||
Base: handlers.NewBaseHandler(services.Base).WithFileManagerService(services.FileManager).WithFileStorage(infra.FileStorage),
|
||||
Medicine: handlers.NewMedicineHandler(services.Medicine),
|
||||
Vocation: handlers.NewVocationHandler(services.Vocation),
|
||||
Opc: handlers.NewOpcHandler(services.Opc),
|
||||
ForcesPresent: handlers.NewForcesPresentHandler(services.ForcesPresent),
|
||||
Hospital: handlers.NewHospitalHandler(services.Hospital),
|
||||
HealthInsuranceCompanies: handlers.NewHealthInsuranceCompaniesHandler(services.HealthInsuranceCompanies),
|
||||
FederalState: handlers.NewFederalStateHandler(services.FederalState),
|
||||
ICAO: handlers.NewICAOHandler(services.ICAO),
|
||||
Land: handlers.NewLandHandler(services.Land),
|
||||
MasterSettings: handlers.NewMasterSettingsHandler(services.MasterSettings, services.FileManager, infra.FileStorage),
|
||||
Branding: handlers.NewBrandingHandler(services.MasterSettings, services.FileManager, infra.FileStorage),
|
||||
FileManagerFolder: handlers.NewFileManagerFolderHandler(services.FileManager, infra.FileStorage),
|
||||
FileManagerFile: handlers.NewFileManagerFileHandler(services.FileManager, infra.FileStorage).
|
||||
WithHelicopterFileService(services.HelicopterFile).
|
||||
WithAircraftService(services.Helicopter).
|
||||
WithBaseService(services.Base).
|
||||
WithDULService(services.DUL).
|
||||
WithAuthService(services.Auth).
|
||||
WithTakeoverService(services.Takeover).
|
||||
WithMissionService(services.Mission).
|
||||
WithUserService(services.User).
|
||||
WithFleetStatusFileService(service.NewFleetStatusFileService(services.FileManager)).
|
||||
WithHelicopterFileEvents(infra.HelicopterFileHub).
|
||||
WithWOPIService(services.WOPI),
|
||||
FileManagerAttachment: handlers.NewFileManagerAttachmentHandler(services.FileManager),
|
||||
FileManagerEvents: handlers.NewFileManagerEventsHandler(infra.FileStatusHub),
|
||||
HelicopterFileEvents: handlers.NewHelicopterFileEventsHandler(infra.HelicopterFileHub),
|
||||
DutyRoster: handlers.NewDutyRosterHandler(services.DutyRoster).WithAudit(services.Audit).WithFlightService(services.Flight),
|
||||
AirRescuerChecklist: handlers.NewAirRescuerChecklistHandler(services.AirRescuerChecklist),
|
||||
InsurancePatientData: handlers.NewInsurancePatientDataHandler(services.InsurancePatientData),
|
||||
PatientData: handlers.NewPatientDataHandler(services.PatientData),
|
||||
DUL: handlers.NewDULHandler(services.DUL).WithBaseService(services.Base).WithContactService(services.Contact).WithFileManagerService(services.FileManager).WithFileStorage(infra.FileStorage),
|
||||
FleetStatus: fleetStatusHandler,
|
||||
HEMSOperationalData: handlers.NewHEMSOperationalDataHandler(services.HEMSOperationalData).WithFileManagerService(services.FileManager),
|
||||
HEMSOperationCategory: handlers.NewHEMSOperationCategoryHandler(services.HEMSOperationCategory),
|
||||
HEMSOperation: handlers.NewHEMSOperationHandler(services.HEMSOperation),
|
||||
Complaint: handlers.NewComplaintHandler(services.Complaint).WithHelicopterService(services.Helicopter).WithMCFService(services.MCF).WithHistoryService(services.FleetHistory).WithAOGRecalculator(services.FleetStatus).WithActionSignoffService(services.ActionSignoff),
|
||||
EASARelease: handlers.NewEASAReleaseHandler(services.EASARelease).WithComplaintActionChecker(services.Complaint).WithActionSignoffChecker(services.ActionSignoff).WithHistoryService(services.FleetHistory).WithContactResolver(services.Contact).WithAOGRecalculator(services.FleetStatus),
|
||||
ActionSignoff: handlers.NewActionSignoffHandler(services.ActionSignoff).WithComplaintService(services.Complaint),
|
||||
MCF: handlers.NewMCFHandler(services.MCF).WithHistoryService(services.FleetHistory),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeRealtimeComponents(
|
||||
ctx context.Context,
|
||||
repos *Repositories,
|
||||
services *Services,
|
||||
infra *Infrastructure,
|
||||
) error {
|
||||
if repos == nil || services == nil || infra == nil {
|
||||
return errors.New("repositories, services, and infrastructure are required")
|
||||
}
|
||||
userNameCache := userctx.NewUserNameCache(repos.User, 5*time.Minute)
|
||||
handlers.WireUserNameGetter(userNameCache)
|
||||
|
||||
startFileManagerAutoPurgeLoop(ctx, services.FileManager, infra.FileTrashPolicy, infra.Logger)
|
||||
startFileManagerLifecycleCleanupLoop(ctx, services.FileManager, infra.FileLifecycle, infra.Logger)
|
||||
startHelicopterFileAttachmentReconcileLoop(ctx, services.HelicopterFile, infra.Logger)
|
||||
startFleetStatusAOGRecomputeLoop(ctx, services.FleetStatus, infra.Logger)
|
||||
|
||||
fileStatusPoller := filemanagerrealtime.NewStatusPoller(infra.DB, infra.FileStatusHub, infra.Logger, filemanagerrealtime.StatusPollerConfig{
|
||||
// Keep the SSE ready event responsive; this poller is the bridge between
|
||||
// the async file processor and the live file.updated stream.
|
||||
PollInterval: 250 * time.Millisecond,
|
||||
BatchSize: 100,
|
||||
OnPublished: func(ctx context.Context, event filemanagerrealtime.FileStatusEvent) error {
|
||||
if filemanager.NormalizeFileStatus(event.Status) != filemanager.FileStatusReady {
|
||||
return nil
|
||||
}
|
||||
if services == nil || services.HelicopterFile == nil {
|
||||
return nil
|
||||
}
|
||||
finalized, err := services.HelicopterFile.FinalizePendingAttachmentsBySourceFileUUID(ctx, event.FileUUID, 50)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if finalized > 0 && infra.Logger != nil {
|
||||
infra.Logger.Info("helicopter file attachments finalized from file ready event", "file_uuid", event.FileUUID, "finalized", finalized)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
go func() {
|
||||
if err := fileStatusPoller.Run(ctx); err != nil && ctx.Err() == nil {
|
||||
infra.Logger.Error("file status poller stopped unexpectedly", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildHTTPServer(appCfg config.AppConfig, services *Services, handlersSet *Handlers, infra *Infrastructure) (*fiber.App, string, error) {
|
||||
if services == nil || handlersSet == nil || infra == nil {
|
||||
return nil, "", errors.New("services, handlers, and infra are required")
|
||||
}
|
||||
httpCfg := appCfg.HTTP
|
||||
app := fiber.New(fiber.Config{
|
||||
BodyLimit: httpCfg.BodyLimit,
|
||||
ReadTimeout: httpCfg.ReadTimeout,
|
||||
WriteTimeout: httpCfg.WriteTimeout,
|
||||
IdleTimeout: httpCfg.IdleTimeout,
|
||||
})
|
||||
api.UseDefaultMiddlewares(app, httpCfg)
|
||||
|
||||
envCfg := config.LoadEnvConfig()
|
||||
hasJSONSAML := appCfg.SAML.CertFile != "" ||
|
||||
appCfg.SAML.KeyFile != "" ||
|
||||
appCfg.SAML.MetadataFile != "" ||
|
||||
appCfg.SAML.RootURL != "" ||
|
||||
appCfg.SAML.FrontendURL != "" ||
|
||||
appCfg.SAML.CookieDomain != "" ||
|
||||
appCfg.SAML.SessionTTLHr > 0
|
||||
if appCfg.SAML.CertFile != "" {
|
||||
envCfg.SAMLCertFile = appCfg.SAML.CertFile
|
||||
}
|
||||
if appCfg.SAML.KeyFile != "" {
|
||||
envCfg.SAMLKeyFile = appCfg.SAML.KeyFile
|
||||
}
|
||||
if appCfg.SAML.MetadataFile != "" {
|
||||
envCfg.SAMLMetadataFile = appCfg.SAML.MetadataFile
|
||||
}
|
||||
if appCfg.SAML.RootURL != "" {
|
||||
envCfg.SAMLRootURL = appCfg.SAML.RootURL
|
||||
}
|
||||
if appCfg.SAML.FrontendURL != "" {
|
||||
envCfg.FrontendURL = appCfg.SAML.FrontendURL
|
||||
}
|
||||
if appCfg.SAML.CookieDomain != "" {
|
||||
envCfg.CookieDomain = appCfg.SAML.CookieDomain
|
||||
}
|
||||
if hasJSONSAML {
|
||||
envCfg.CookieSecure = appCfg.SAML.CookieSecure
|
||||
}
|
||||
if appCfg.SAML.SessionTTLHr > 0 {
|
||||
envCfg.SessionTTLHour = appCfg.SAML.SessionTTLHr
|
||||
}
|
||||
|
||||
// Microsoft auth mode selector. Default "oauth" uses the OIDC/OAuth2 authorization
|
||||
// code flow (Microsoft refresh tokens are stored in DB and validated on
|
||||
// /api/v1/auth/refresh). Set MICROSOFT_AUTH_MODE=saml to fall back to the legacy
|
||||
// SAML flow (kept intact for rollback).
|
||||
microsoftAuthMode := strings.ToLower(strings.TrimSpace(os.Getenv("MICROSOFT_AUTH_MODE")))
|
||||
if microsoftAuthMode == "" {
|
||||
microsoftAuthMode = "oauth"
|
||||
}
|
||||
|
||||
var samlHandler *samlauth.Handler
|
||||
if microsoftAuthMode == "saml" {
|
||||
if err := samlauth.InitSessionStoreDB(infra.DB); err == nil {
|
||||
if err := samlauth.InitSAML(envCfg); err == nil {
|
||||
samlHandler = samlauth.NewHandler(envCfg, services.Auth)
|
||||
}
|
||||
}
|
||||
}
|
||||
slog.Info("microsoft auth mode configured", slog.String("mode", microsoftAuthMode), slog.Bool("saml_active", samlHandler != nil))
|
||||
|
||||
api.RegisterRoutes(app, api.RouteDependencies{
|
||||
Handlers: api.RouteHandlers{
|
||||
User: handlersSet.User,
|
||||
Contact: handlersSet.Contact,
|
||||
Health: handlersSet.Health,
|
||||
BuildInfo: handlersSet.BuildInfo,
|
||||
Auth: handlersSet.Auth,
|
||||
Role: handlersSet.Role,
|
||||
Helicopter: handlersSet.Helicopter,
|
||||
HelicopterUsage: handlersSet.HelicopterUsage,
|
||||
HelicopterFile: handlersSet.HelicopterFile,
|
||||
Flight: handlersSet.Flight,
|
||||
FlightData: handlersSet.FlightData,
|
||||
Mission: handlersSet.Mission,
|
||||
FMReport: handlersSet.FMReport,
|
||||
ReserveAc: handlersSet.ReserveAc,
|
||||
Takeover: handlersSet.Takeover,
|
||||
OtherPerson: handlersSet.OtherPerson,
|
||||
Facility: handlersSet.Facility,
|
||||
Base: handlersSet.Base,
|
||||
Medicine: handlersSet.Medicine,
|
||||
Vocation: handlersSet.Vocation,
|
||||
Opc: handlersSet.Opc,
|
||||
ForcesPresent: handlersSet.ForcesPresent,
|
||||
Hospital: handlersSet.Hospital,
|
||||
HealthInsuranceCompanies: handlersSet.HealthInsuranceCompanies,
|
||||
FederalState: handlersSet.FederalState,
|
||||
ICAO: handlersSet.ICAO,
|
||||
Land: handlersSet.Land,
|
||||
MasterSettings: handlersSet.MasterSettings,
|
||||
Branding: handlersSet.Branding,
|
||||
FileManagerFolder: handlersSet.FileManagerFolder,
|
||||
FileManagerFile: handlersSet.FileManagerFile,
|
||||
FileManagerAttachment: handlersSet.FileManagerAttachment,
|
||||
FileManagerEvents: handlersSet.FileManagerEvents,
|
||||
HelicopterFileEvents: handlersSet.HelicopterFileEvents,
|
||||
DutyRoster: handlersSet.DutyRoster,
|
||||
AirRescuerChecklist: handlersSet.AirRescuerChecklist,
|
||||
InsurancePatientData: handlersSet.InsurancePatientData,
|
||||
PatientData: handlersSet.PatientData,
|
||||
DUL: handlersSet.DUL,
|
||||
FleetStatus: handlersSet.FleetStatus,
|
||||
HEMSOperationalData: handlersSet.HEMSOperationalData,
|
||||
HEMSOperationCategory: handlersSet.HEMSOperationCategory,
|
||||
HEMSOperation: handlersSet.HEMSOperation,
|
||||
Complaint: handlersSet.Complaint,
|
||||
EASARelease: handlersSet.EASARelease,
|
||||
ActionSignoff: handlersSet.ActionSignoff,
|
||||
MCF: handlersSet.MCF,
|
||||
SAMLAuth: samlHandler,
|
||||
},
|
||||
Services: api.RouteServices{
|
||||
Auth: services.Auth,
|
||||
Audit: services.Audit,
|
||||
WOPI: services.WOPI,
|
||||
},
|
||||
})
|
||||
|
||||
addr := ":8080"
|
||||
if appCfg.HTTPPort > 0 {
|
||||
addr = fmt.Sprintf(":%d", appCfg.HTTPPort)
|
||||
}
|
||||
return app, addr, nil
|
||||
}
|
||||
Reference in New Issue
Block a user