336 lines
16 KiB
Go
336 lines
16 KiB
Go
package http_router
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/pprof"
|
|
"strings"
|
|
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/logger"
|
|
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/cache"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/feed"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager/s3_storage"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/integration"
|
|
objectStorage "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/object_storage"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/agent"
|
|
authinfra "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/auth_infrastructure"
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/distributor"
|
|
|
|
pgdb "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/postgres"
|
|
formgenerator "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/form_generator"
|
|
|
|
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
type Router struct {
|
|
Mux *mux.Router
|
|
env string
|
|
logger *slog.Logger
|
|
middleware *Middleware
|
|
shortenerCfg *config.SecretConfig
|
|
abstractAPI string
|
|
cache cache.Client
|
|
objectStorage objectStorage.Client
|
|
feedHandler *feed.Handler
|
|
integrationClient integration.Client
|
|
databaseClient database.Client
|
|
agentService agent.AgentService
|
|
distributorService distributor.DistributorService
|
|
}
|
|
|
|
func New(logger *slog.Logger, cfg *config.Config) (*Router, error) {
|
|
middleware, err := NewMiddleware(&ConfigMiddleware{
|
|
logger: logger,
|
|
keycloakCfg: &cfg.Keycloak,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cacheClient, err := cache.New(cache.ValKeyCacheConfig{
|
|
Addrs: strings.Split(cfg.ValkeyCache.Addrs, ","),
|
|
Password: cfg.ValkeyCache.Password,
|
|
ReadOnly: cfg.ValkeyCache.ReadOnly,
|
|
DialTimeout: cfg.ValkeyCache.DialTimeout,
|
|
PoolSize: cfg.ValkeyCache.PoolSize,
|
|
DefaultTTL: cfg.ValkeyCache.DefaultTTL,
|
|
RootCaFilePath: cfg.ValkeyCache.RootCaFilePath,
|
|
}, cache.ValkeyCacheType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
databaseClient, err := database.New(database.PostgresClientType, pgdb.PostgresConfig{
|
|
Host: cfg.Database.Host,
|
|
Port: cfg.Database.Port,
|
|
Username: cfg.Database.Username,
|
|
Password: cfg.Database.Password,
|
|
Database: cfg.Database.DBName,
|
|
Schema: cfg.Database.Schema,
|
|
SSLMode: cfg.Database.SSLMode,
|
|
SSLRootCert: cfg.Database.RootCaFilePath,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agentService, err := agent.New(agent.CrmAgentServiceType, agent.CrmAgentServiceConfig{
|
|
DbClient: databaseClient,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
distributorService, err := distributor.New(distributor.CrmDistributorServiceType, distributor.CrmDistributorServiceConfig{
|
|
DbClient: databaseClient,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
objectStorageClient, err := objectStorage.New(objectStorage.S3StorageConfig{
|
|
Bucket: cfg.S3Storage.Bucket,
|
|
DefaultLinkTTL: cfg.ValkeyCache.DefaultTTL,
|
|
}, objectStorage.ClientTypeS3)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
integrationClient, err := integration.New(integration.Config{
|
|
Cache: cacheClient,
|
|
Db: databaseClient,
|
|
Logger: logger,
|
|
Secrets: map[string]integration.CompanySecrets{
|
|
integration.VkusvillCompanyName: integration.VkusvillSecretsConfig{
|
|
ApiToken: cfg.Integration.Vkusvill.ApiToken,
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: вырезать ненужные аргументы в рамках https://tracker.yandex.ru/MOLVARAZRABOTKA-363
|
|
service, err := feed.NewService(fmt.Sprintf(
|
|
"postgres://%s:%s@%s:%d/%s?sslmode=%s",
|
|
cfg.Database.Username,
|
|
cfg.Database.Password,
|
|
cfg.Database.Host,
|
|
cfg.Database.Port,
|
|
cfg.Database.DBName,
|
|
cfg.Database.SSLMode,
|
|
), cfg.Database.Schema, logger, databaseClient)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Router{
|
|
Mux: mux.NewRouter(),
|
|
env: cfg.Env,
|
|
logger: logger,
|
|
middleware: middleware,
|
|
shortenerCfg: &cfg.Secret,
|
|
abstractAPI: cfg.EmailVerificationService.APIKey, // may be nil dereference if no email verification service is configured
|
|
cache: cacheClient,
|
|
objectStorage: objectStorageClient,
|
|
feedHandler: feed.NewFeedHandler(logger, service),
|
|
databaseClient: databaseClient,
|
|
agentService: agentService,
|
|
distributorService: distributorService,
|
|
integrationClient: integrationClient,
|
|
}, nil
|
|
}
|
|
|
|
func SetupRouter(r *Router, buildCfg config.BuildInfo) {
|
|
authInfraService, err := authinfra.New(authinfra.CacheAuthInfrastructureServiceType, authinfra.CacheAuthInfraServiceConfig{
|
|
CacheClient: r.cache,
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
s3FileManager := s3_storage.NewS3Storage(
|
|
r.objectStorage,
|
|
r.cache,
|
|
)
|
|
|
|
h := newHandler(&Config{
|
|
env: r.env,
|
|
logger: r.logger,
|
|
authManager: r.middleware.authManager,
|
|
authInfraService: authInfraService,
|
|
fileManager: s3FileManager,
|
|
dbClient: r.databaseClient,
|
|
agentService: r.agentService,
|
|
distributorService: r.distributorService,
|
|
secretConfig: r.shortenerCfg,
|
|
emailVerificationServiceAPIKey: r.abstractAPI,
|
|
cacheClient: r.cache,
|
|
objectStorageClient: r.objectStorage,
|
|
feed: r.feedHandler,
|
|
integrationClient: r.integrationClient,
|
|
buildConfig: buildCfg,
|
|
})
|
|
|
|
r.Mux.Use(r.middleware.loggingMiddleware)
|
|
|
|
setupAuthHandlers(r, h)
|
|
setupIntegrationHandlers(r, h)
|
|
setupClientHandlers(r, h)
|
|
setupValidationHandlers(r, h)
|
|
|
|
if r.env != logger.EnvProd {
|
|
setupSystemInfoHandlers(r, h)
|
|
}
|
|
|
|
subRouter := r.Mux.PathPrefix("/api/v1").Subrouter()
|
|
subRouter.Use(r.middleware.authMiddleware)
|
|
|
|
setupAgentHandlers(subRouter, h)
|
|
setupDistributorHandlers(subRouter, h)
|
|
setupEmployeesHandlers(subRouter, h)
|
|
setupLogoHandlers(subRouter, h)
|
|
|
|
// --------------- DOCUMENTS FOR FORM ------------
|
|
r.Mux.HandleFunc("/api/v1/docs/{file}", h.getFileHandler).Methods(http.MethodGet)
|
|
|
|
// --------------- FEED ------------
|
|
subRouter.HandleFunc("/feed/{uid}/events", h.GetUserEventsHandler).Methods(http.MethodGet)
|
|
}
|
|
|
|
func setupAuthHandlers(r *Router, h *handler) {
|
|
r.Mux.HandleFunc("/api/v1/login", h.loginHandler).Methods(http.MethodPost)
|
|
r.Mux.HandleFunc("/api/v1/register", h.registerHandler).Methods(http.MethodPost)
|
|
r.Mux.HandleFunc("/api/v1/logout", h.logoutHandler).Methods(http.MethodPost)
|
|
r.Mux.HandleFunc("/api/v1/refresh-token", h.refreshTokenHandler).Methods(http.MethodPost)
|
|
|
|
r.Mux.HandleFunc("/api/v1/verify_email", h.verifyEmailHandler).Methods(http.MethodPatch)
|
|
r.Mux.HandleFunc("/api/v1/verify_email", h.getEmailVerificationStatusHandler).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/api/v1/confirm_email", h.confirmEmailPageHandler).Methods(http.MethodGet)
|
|
|
|
r.Mux.HandleFunc("/api/v1/forgot_password", h.forgotPasswordHandler).Methods(http.MethodPost)
|
|
r.Mux.HandleFunc("/api/v1/validate_otp", h.validateOTPHandler).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/api/v1/reset_password", h.resetPasswordHandler).Methods(http.MethodPut)
|
|
}
|
|
|
|
func setupAgentHandlers(subRouter *mux.Router, h *handler) {
|
|
// // =============== COMPANY HANDLERS ===============
|
|
subRouter.HandleFunc("/agents/{agent_id}/companies", h.getCompanyListAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/company/{company_id}", h.getCompanyByIdAgentHandler).Methods(http.MethodGet)
|
|
// TODO: review
|
|
// subRouter.HandleFunc("/agents/{agent_id}/company/{company_id}", h.addNewAgentCompanyMemberHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/agents/{agent_id}/company", h.createCompanyAgentHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/agents/{agent_id}/company/{company_id}", h.updateCompanyAgentHandler).Methods(http.MethodPatch)
|
|
|
|
// // =============== VACANCY HANDLERS ===============
|
|
subRouter.HandleFunc("/agents/{agent_id}/vacancies", h.getVacancyListAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/vacancies/{vacancy_id}", h.getPersonalLinkHandler).Methods(http.MethodGet)
|
|
|
|
// // =============== SUBMISSION HANDLERS ===============
|
|
subRouter.HandleFunc("/agents/{agent_id}/submissions", h.getSubmissionListAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/submissions/{submission_id}", h.deleteSubmissionAgentHandler).Methods(http.MethodDelete)
|
|
subRouter.HandleFunc("/agents/{agent_id}/submissions/{submission_id}/cv", h.getSubmissionCVHandler).Methods(http.MethodGet)
|
|
|
|
// // =============== PROFILE HANDLERS ===============
|
|
subRouter.HandleFunc("/agents/{agent_id}/profile", h.getProfileAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/profile", h.updateProfileAgentHandler).Methods(http.MethodPatch)
|
|
|
|
// // =============== BALANCE HANDLERS ===============
|
|
subRouter.HandleFunc("/agents/{agent_id}/balance", h.getBalanceAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/transactions", h.getTransactionListAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/transactions", h.createTransactionAgentHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/agents/{agent_id}/bank_accounts", h.getBankAccountListAgentHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/agents/{agent_id}/bank_accounts", h.createBankAccountAgentHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/agents/{agent_id}/bank_accounts/{bank_account_id}", h.updateBankAccountAgentHandler).Methods(http.MethodPatch)
|
|
subRouter.HandleFunc("/agents/{agent_id}/bank_accounts/{bank_account_id}", h.deleteBankAccountAgentHandler).Methods(http.MethodDelete)
|
|
}
|
|
|
|
func setupDistributorHandlers(subRouter *mux.Router, h *handler) {
|
|
// // =============== COMPANY HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/companies", h.getCompanyListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}", h.getCompanyByIdDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}", h.addCompanyMemberDistributorHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}", h.updateCompanyDistributorHandler).Methods(http.MethodPatch)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company", h.createCompanyDistributorHandler).Methods(http.MethodPost)
|
|
|
|
// // =============== VACANCY HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies", h.getVacancyListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies", h.createVacancyDistributorHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies/{vacancy_id}", h.updateVacancyDistributorHandler).Methods(http.MethodPatch)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies/{vacancy_id}", h.deleteVacancyDistributorHandler).Methods(http.MethodDelete)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies/{vacancy_id}/moderation", h.sendVacancyToModerationHandler).Methods(http.MethodPost)
|
|
|
|
// // =============== SUBMISSION HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies/{vacancy_id}/submissions", h.getSubmissionListDistributorHandler).Methods(http.MethodGet)
|
|
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/vacancies/{vacancy_id}/submissions/{submission_id}/status", h.updateSubmissionStatusDistributorHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/submissions/{submission_id}/cv", h.getSubmissionCVHandler).Methods(http.MethodGet)
|
|
|
|
// // =============== PROFILE HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/profile", h.getProfileDisributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/profile", h.updateProfileDistributorHandler).Methods(http.MethodPatch)
|
|
|
|
// // =============== BALANCE HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/balance", h.getBalanceDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/balance", h.getCompanyBalanceDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/transactions", h.getTransactionListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/transactions", h.getCompanyTransactionListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/transactions", h.createTransactionDistributorHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/bank_accounts", h.getBankAccountListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/bank_accounts", h.getCompanyBankAccountListDistributorHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/bank_accounts", h.createBankAccountDistributorHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/bank_accounts/{bank_account_id}", h.updateBankAccountDistributorHandler).Methods(http.MethodPut)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/bank_accounts/{bank_account_id}", h.deleteBankAccountDistributorHandler).Methods(http.MethodDelete)
|
|
}
|
|
|
|
func setupEmployeesHandlers(subRouter *mux.Router, h *handler) {
|
|
// // =============== EMPLOYEES HANDLERS ===============
|
|
subRouter.HandleFunc("/companies/{company_id}/employees", h.getEmployeesHandler).Methods(http.MethodGet)
|
|
}
|
|
|
|
func setupClientHandlers(r *Router, h *handler) {
|
|
// // =============== CLIENT HANDLERS ===============
|
|
r.Mux.HandleFunc("/api/v1/anketa", h.getAnketaHandler).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/api/v1/anketa", h.postAnketaHandler).Methods(http.MethodPost)
|
|
|
|
// --------------- FORM METADATA ---------------
|
|
//TODO FROM ALEXANDER: make err validation
|
|
formSys, _ := formgenerator.GetFileSystem()
|
|
|
|
r.Mux.PathPrefix("/api/v1/anketa/static/").Handler(http.StripPrefix("/api/v1/anketa/static/", http.FileServer(http.FS(formSys))))
|
|
}
|
|
|
|
func setupValidationHandlers(r *Router, h *handler) {
|
|
// // =============== VALIDATION HANDLERS ===============
|
|
r.Mux.HandleFunc("/api/v1/{uid}/validation", h.getUserValidationStatusHandler).Methods(http.MethodGet)
|
|
}
|
|
|
|
func setupLogoHandlers(subRouter *mux.Router, h *handler) {
|
|
// // =============== LOGO HANDLERS ===============
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/logo", h.getCompanyLogoHandler).Methods(http.MethodGet)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/logo", h.createCompanyLogoHandler).Methods(http.MethodPost)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/logo", h.updateCompanyLogoHandler).Methods(http.MethodPut)
|
|
subRouter.HandleFunc("/distributor/{distributor_id}/company/{company_id}/logo", h.deleteCompanyLogoHandler).Methods(http.MethodDelete)
|
|
}
|
|
|
|
func setupIntegrationHandlers(r *Router, h *handler) {
|
|
r.Mux.HandleFunc("/api/v1/integration/vkusvill/callback", h.vkusvillIntegrationCallbackHandler).Methods(http.MethodPost)
|
|
}
|
|
|
|
func setupSystemInfoHandlers(r *Router, h *handler) {
|
|
r.Mux.HandleFunc("/api/v1/healthcheck", h.getBuildInfoHandler).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/debug/pprof/", pprof.Index).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/debug/pprof/profile", pprof.Profile).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol).Methods(http.MethodGet)
|
|
r.Mux.HandleFunc("/debug/pprof/trace", pprof.Trace).Methods(http.MethodGet)
|
|
r.Mux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine")).Methods(http.MethodGet)
|
|
r.Mux.Handle("/debug/pprof/heap", pprof.Handler("heap")).Methods(http.MethodGet)
|
|
r.Mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate")).Methods(http.MethodGet)
|
|
r.Mux.Handle("/debug/pprof/block", pprof.Handler("block")).Methods(http.MethodGet)
|
|
}
|