@omnizap-system/omnizap 2.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clusterfuzzlite/Dockerfile +10 -0
- package/.env.example +907 -0
- package/.github/codeql/codeql-config.yml +10 -0
- package/.github/dependabot.yml +35 -0
- package/.github/workflows/ci.yml +73 -0
- package/.github/workflows/codeql.yml +106 -0
- package/.github/workflows/db-migration-check.yml +98 -0
- package/.github/workflows/dependency-review.yml +22 -0
- package/.github/workflows/deploy.yml +95 -0
- package/.github/workflows/release.yml +106 -0
- package/.github/workflows/security-attest-provenance.yml +51 -0
- package/.github/workflows/security-gitleaks.yml +34 -0
- package/.github/workflows/security-runner-hardening.yml +31 -0
- package/.github/workflows/security-scorecard.yml +44 -0
- package/.github/workflows/security-zap-baseline.yml +44 -0
- package/.github/workflows/security-zap-full-scan.yml +43 -0
- package/.github/workflows/security-zizmor.yml +36 -0
- package/.github/workflows/wiki-sync.yml +44 -0
- package/.gitleaks.toml +15 -0
- package/.prettierrc +34 -0
- package/CODE_OF_CONDUCT.md +114 -0
- package/LICENSE +56 -0
- package/README.md +110 -0
- package/SECURITY.md +110 -0
- package/app/config/index.js +4 -0
- package/app/configParts/adminIdentity.js +92 -0
- package/app/configParts/baileysConfig.js +1818 -0
- package/app/configParts/groupUtils.js +692 -0
- package/app/configParts/loggerConfig.js +394 -0
- package/app/configParts/messagePersistenceService.js +305 -0
- package/app/connection/baileysCompatibility.test.js +40 -0
- package/app/connection/baileysDbAuthState.js +344 -0
- package/app/connection/socketController.js +2243 -0
- package/app/controllers/messageController.js +7 -0
- package/app/controllers/messagePipeline/commandMiddleware.js +146 -0
- package/app/controllers/messagePipeline/conversationMiddleware.js +183 -0
- package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +522 -0
- package/app/controllers/messagePipeline/postProcessingMiddleware.js +41 -0
- package/app/controllers/messagePipeline/preProcessingMiddlewares.js +166 -0
- package/app/controllers/messageProcessingPipeline.js +699 -0
- package/app/modules/adminModule/AGENT.md +4056 -0
- package/app/modules/adminModule/adminAiHelpService.js +56 -0
- package/app/modules/adminModule/adminConfigRuntime.js +177 -0
- package/app/modules/adminModule/commandConfig.json +7122 -0
- package/app/modules/adminModule/groupCommandHandlers.js +1823 -0
- package/app/modules/adminModule/groupCommandHandlers.test.js +350 -0
- package/app/modules/adminModule/groupEventHandlers.js +399 -0
- package/app/modules/aiModule/AGENT.md +547 -0
- package/app/modules/aiModule/aiAiHelpService.js +14 -0
- package/app/modules/aiModule/aiConfigRuntime.js +135 -0
- package/app/modules/aiModule/catCommand.js +967 -0
- package/app/modules/aiModule/commandConfig.json +981 -0
- package/app/modules/analyticsModule/messageAnalysisEventRepository.js +83 -0
- package/app/modules/gameModule/AGENT.md +196 -0
- package/app/modules/gameModule/commandConfig.json +366 -0
- package/app/modules/gameModule/diceCommand.js +42 -0
- package/app/modules/gameModule/gameAiHelpService.js +14 -0
- package/app/modules/gameModule/gameConfigRuntime.js +68 -0
- package/app/modules/menuModule/AGENT.md +205 -0
- package/app/modules/menuModule/commandConfig.json +366 -0
- package/app/modules/menuModule/common.js +316 -0
- package/app/modules/menuModule/menuAiHelpService.js +14 -0
- package/app/modules/menuModule/menuConfigRuntime.js +68 -0
- package/app/modules/menuModule/menus.js +66 -0
- package/app/modules/playModule/AGENT.md +321 -0
- package/app/modules/playModule/commandConfig.json +584 -0
- package/app/modules/playModule/playAiHelpService.js +14 -0
- package/app/modules/playModule/playCommand.js +1417 -0
- package/app/modules/playModule/playConfigRuntime.js +68 -0
- package/app/modules/quoteModule/AGENT.md +199 -0
- package/app/modules/quoteModule/commandConfig.json +366 -0
- package/app/modules/quoteModule/quoteAiHelpService.js +14 -0
- package/app/modules/quoteModule/quoteCommand.js +842 -0
- package/app/modules/quoteModule/quoteConfigRuntime.js +68 -0
- package/app/modules/rpgPokemonModule/AGENT.md +229 -0
- package/app/modules/rpgPokemonModule/commandConfig.json +386 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +795 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.js +2110 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +770 -0
- package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
- package/app/modules/rpgPokemonModule/rpgPokemonAiHelpService.js +14 -0
- package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +174 -0
- package/app/modules/rpgPokemonModule/rpgPokemonConfigRuntime.js +68 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
- package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
- package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1847 -0
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +6839 -0
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
- package/app/modules/statsModule/AGENT.md +320 -0
- package/app/modules/statsModule/commandConfig.json +540 -0
- package/app/modules/statsModule/globalRankingCommand.js +64 -0
- package/app/modules/statsModule/rankingCommand.js +41 -0
- package/app/modules/statsModule/rankingCommon.js +1305 -0
- package/app/modules/statsModule/statsAiHelpService.js +14 -0
- package/app/modules/statsModule/statsConfigRuntime.js +68 -0
- package/app/modules/stickerModule/AGENT.md +692 -0
- package/app/modules/stickerModule/addStickerMetadata.js +239 -0
- package/app/modules/stickerModule/commandConfig.json +1216 -0
- package/app/modules/stickerModule/convertToWebp.js +367 -0
- package/app/modules/stickerModule/stickerAiHelpService.js +14 -0
- package/app/modules/stickerModule/stickerCommand.js +446 -0
- package/app/modules/stickerModule/stickerConfigRuntime.js +68 -0
- package/app/modules/stickerModule/stickerConvertCommand.js +159 -0
- package/app/modules/stickerModule/stickerTextCommand.js +653 -0
- package/app/modules/stickerPackModule/AGENT.md +215 -0
- package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
- package/app/modules/stickerPackModule/autoPackCollectorService.js +357 -0
- package/app/modules/stickerPackModule/commandConfig.json +387 -0
- package/app/modules/stickerPackModule/domainEventOutboxRepository.js +227 -0
- package/app/modules/stickerPackModule/domainEvents.js +52 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +429 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +75 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +544 -0
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +175 -0
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +3702 -0
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +559 -0
- package/app/modules/stickerPackModule/stickerClassificationService.js +557 -0
- package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +249 -0
- package/app/modules/stickerPackModule/stickerDomainEventBus.js +65 -0
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +208 -0
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +99 -0
- package/app/modules/stickerPackModule/stickerObjectStorageService.js +285 -0
- package/app/modules/stickerPackModule/stickerPackAiHelpService.js +14 -0
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1148 -0
- package/app/modules/stickerPackModule/stickerPackConfigRuntime.js +68 -0
- package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +152 -0
- package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +101 -0
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +432 -0
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +313 -0
- package/app/modules/stickerPackModule/stickerPackMessageService.js +268 -0
- package/app/modules/stickerPackModule/stickerPackRepository.js +450 -0
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +179 -0
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +271 -0
- package/app/modules/stickerPackModule/stickerPackService.js +733 -0
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +32 -0
- package/app/modules/stickerPackModule/stickerPackUtils.js +107 -0
- package/app/modules/stickerPackModule/stickerStorageService.js +559 -0
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +242 -0
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +242 -0
- package/app/modules/systemMetricsModule/AGENT.md +193 -0
- package/app/modules/systemMetricsModule/commandConfig.json +344 -0
- package/app/modules/systemMetricsModule/pingCommand.js +399 -0
- package/app/modules/systemMetricsModule/systemMetricsAiHelpService.js +14 -0
- package/app/modules/systemMetricsModule/systemMetricsConfigRuntime.js +68 -0
- package/app/modules/tiktokModule/AGENT.md +196 -0
- package/app/modules/tiktokModule/commandConfig.json +366 -0
- package/app/modules/tiktokModule/tiktokAiHelpService.js +14 -0
- package/app/modules/tiktokModule/tiktokCommand.js +716 -0
- package/app/modules/tiktokModule/tiktokConfigRuntime.js +68 -0
- package/app/modules/userModule/AGENT.md +200 -0
- package/app/modules/userModule/commandConfig.json +386 -0
- package/app/modules/userModule/userAiHelpService.js +14 -0
- package/app/modules/userModule/userCommand.js +1155 -0
- package/app/modules/userModule/userConfigRuntime.js +68 -0
- package/app/modules/waifuPicsModule/AGENT.md +431 -0
- package/app/modules/waifuPicsModule/commandConfig.json +780 -0
- package/app/modules/waifuPicsModule/waifuPicsAiHelpService.js +14 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +586 -0
- package/app/modules/waifuPicsModule/waifuPicsConfigRuntime.js +68 -0
- package/app/observability/metrics.js +766 -0
- package/app/services/ai/aiHelpResponseCacheRepository.js +280 -0
- package/app/services/ai/aiLearningRepository.js +400 -0
- package/app/services/ai/commandConfigEnrichmentRepository.js +769 -0
- package/app/services/ai/commandConfigEnrichmentService.js +452 -0
- package/app/services/ai/commandConfigValidationService.js +443 -0
- package/app/services/ai/commandToolBuilderService.js +192 -0
- package/app/services/ai/conversationRouterService.js +516 -0
- package/app/services/ai/geminiService.js +115 -0
- package/app/services/ai/geminiService.test.js +87 -0
- package/app/services/ai/globalModuleAiHelpService.js +1412 -0
- package/app/services/ai/globalToolCallingService.js +203 -0
- package/app/services/ai/messageCommandExecutionService.js +391 -0
- package/app/services/ai/moduleAiHelpCoreService.js +1099 -0
- package/app/services/ai/moduleAiHelpWrapperFactory.js +65 -0
- package/app/services/ai/moduleCommandConfigRuntimeService.js +113 -0
- package/app/services/ai/moduleToolExecutorService.js +464 -0
- package/app/services/ai/moduleToolRegistryService.js +178 -0
- package/app/services/ai/toolCandidateSelectorService.js +781 -0
- package/app/services/auth/googleWebLinkService.js +80 -0
- package/app/services/auth/whatsappLoginLinkService.js +230 -0
- package/app/services/external/pokeApiService.js +398 -0
- package/app/services/group/groupMetadataService.js +311 -0
- package/app/services/infra/dbWriteQueue.js +874 -0
- package/app/services/infra/featureFlagService.js +131 -0
- package/app/services/infra/queueUtils.js +55 -0
- package/app/services/messaging/captchaService.js +491 -0
- package/app/services/messaging/messagePersistenceService.js +1 -0
- package/app/services/messaging/newsBroadcastService.js +347 -0
- package/app/services/sticker/stickerFocusService.js +347 -0
- package/app/services/sticker/stickerFocusService.test.js +43 -0
- package/app/store/aiPromptStore.js +38 -0
- package/app/store/conversationSessionStore.js +131 -0
- package/app/store/groupConfigStore.js +58 -0
- package/app/store/premiumUserStore.js +54 -0
- package/app/utils/antiLink/antiLinkModule.js +700 -0
- package/app/utils/http/getImageBufferModule.js +18 -0
- package/app/utils/json/jsonSanitizer.js +113 -0
- package/app/utils/json/jsonSanitizer.test.js +40 -0
- package/app/utils/systemMetrics/systemMetricsModule.js +88 -0
- package/app/workers/aiLearningWorker.js +605 -0
- package/app/workers/commandConfigEnrichmentWorker.js +242 -0
- package/database/index.js +2075 -0
- package/database/init.js +151 -0
- package/database/migrations/.gitkeep +0 -0
- package/database/migrations/20260307_d0_hardening_down.sql +64 -0
- package/database/migrations/20260307_d0_hardening_up.sql +79 -0
- package/database/migrations/20260307_d1_terms_acceptance_down.sql +11 -0
- package/database/migrations/20260307_d1_terms_acceptance_up.sql +37 -0
- package/database/migrations/20260307_d2_auth_hardening_down.sql +75 -0
- package/database/migrations/20260307_d2_auth_hardening_up.sql +100 -0
- package/database/migrations/20260314_d7_canonical_sender_down.sql +53 -0
- package/database/migrations/20260314_d7_canonical_sender_up.sql +114 -0
- package/database/migrations/20260406_d30_security_analytics_down.sql +95 -0
- package/database/migrations/20260406_d30_security_analytics_up.sql +292 -0
- package/database/migrations/20260407_d31_web_google_session_token_hardening_down.sql +2 -0
- package/database/migrations/20260407_d31_web_google_session_token_hardening_up.sql +17 -0
- package/database/migrations/20260408_d32_ai_help_response_cache_down.sql +1 -0
- package/database/migrations/20260408_d32_ai_help_response_cache_up.sql +22 -0
- package/database/migrations/20260409_d33_ai_learning_tables_down.sql +4 -0
- package/database/migrations/20260409_d33_ai_learning_tables_up.sql +52 -0
- package/database/migrations/20260410_d34_command_config_enrichment_down.sql +3 -0
- package/database/migrations/20260410_d34_command_config_enrichment_up.sql +48 -0
- package/database/schema.sql +1186 -0
- package/docker-compose.yml +104 -0
- package/docs/audits/stickerCatalogController-out-of-scope.md +103 -0
- package/docs/audits/stickerCatalogController-symbols.md +58 -0
- package/docs/compliance/acceptable-use-policy-2026-03-07.md +35 -0
- package/docs/compliance/dpa-b2b-standard-2026-03-07.md +80 -0
- package/docs/compliance/monthly-compliance-checklist-2026-03-07.md +88 -0
- package/docs/compliance/notice-and-takedown-policy-2026-03-07.md +34 -0
- package/docs/compliance/privacy-policy-2026-03-07.md +75 -0
- package/docs/compliance/subprocessors-inventory-2026-03-07.md +16 -0
- package/docs/database/production-db-evolution-runbook-2026q1.md +365 -0
- package/docs/security/dsar-lgpd-runbook-2026-03-07.md +86 -0
- package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +77 -0
- package/docs/security/network-hardening-runbook-2026-03-07.md +137 -0
- package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +238 -0
- package/docs/seo/satellite-page-template.md +116 -0
- package/docs/seo/satellite-pages-phase1.json +364 -0
- package/docs/wiki/Home.md +120 -0
- package/docs/wiki/pair-extraordinaire-2026-03-08.md +3 -0
- package/docs/wiki/recent-changes-2026-03-08.md +47 -0
- package/ecosystem.prod.config.cjs +135 -0
- package/eslint.config.js +89 -0
- package/index.js +488 -0
- package/ml/clip_classifier/Dockerfile +18 -0
- package/ml/clip_classifier/README.md +118 -0
- package/ml/clip_classifier/adaptive_scoring.py +40 -0
- package/ml/clip_classifier/classifier.py +654 -0
- package/ml/clip_classifier/embedding_store.py +481 -0
- package/ml/clip_classifier/env_loader.py +15 -0
- package/ml/clip_classifier/llm_label_expander.py +144 -0
- package/ml/clip_classifier/main.py +213 -0
- package/ml/clip_classifier/requirements.txt +10 -0
- package/ml/clip_classifier/similarity_engine.py +74 -0
- package/new-logo.png +0 -0
- package/observability/alert-rules.yml +60 -0
- package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
- package/observability/grafana/dashboards/omnizap-overview.json +170 -0
- package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
- package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
- package/observability/loki-config.yml +38 -0
- package/observability/mysql-setup.sql +46 -0
- package/observability/prometheus.yml +35 -0
- package/observability/promtail-config.yml +84 -0
- package/observability/sticker-catalog-slo.md +83 -0
- package/observability/sticker-scale-hardening-rollout.md +128 -0
- package/package.json +144 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/css/commands-react.input.css +71 -0
- package/public/assets/css/create-pack-react.input.css +31 -0
- package/public/assets/css/home-react.input.css +106 -0
- package/public/assets/css/login-react.input.css +58 -0
- package/public/assets/css/stickers-react.input.css +18 -0
- package/public/assets/css/terms-react.input.css +115 -0
- package/public/assets/css/user-react.input.css +57 -0
- package/public/assets/images/brand-icon-192.png +0 -0
- package/public/assets/images/brand-logo-128.webp +0 -0
- package/public/assets/images/hero-banner-1280.jpg +0 -0
- package/public/comandos/commands-catalog.json +4517 -0
- package/public/css/api-docs.css +161 -0
- package/public/css/stickers-admin.css +1288 -0
- package/public/css/styles.css +679 -0
- package/public/css/systemadm/admin.css +474 -0
- package/public/css/systemadm/base.css +73 -0
- package/public/css/systemadm/components.css +662 -0
- package/public/css/systemadm/layout.css +229 -0
- package/public/css/systemadm/tokens.css +56 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/js/apps/apiDocsApp.js +235 -0
- package/public/js/apps/commandsReactApp.js +528 -0
- package/public/js/apps/createPackApp.js +1646 -0
- package/public/js/apps/homeReactApp.js +942 -0
- package/public/js/apps/loginReactApp.js +496 -0
- package/public/js/apps/stickersAdminApp.js +1753 -0
- package/public/js/apps/stickersApp.js +3797 -0
- package/public/js/apps/termsReactApp.js +528 -0
- package/public/js/apps/userApp.js +2540 -0
- package/public/js/apps/userProfile/actions.js +66 -0
- package/public/js/apps/userReactApp.js +547 -0
- package/public/js/catalog.js +950 -0
- package/public/pages/api-docs.html +40 -0
- package/public/pages/aup.html +158 -0
- package/public/pages/comandos.html +41 -0
- package/public/pages/dpa.html +227 -0
- package/public/pages/home.html +45 -0
- package/public/pages/licenca.html +182 -0
- package/public/pages/login.html +40 -0
- package/public/pages/notice-and-takedown.html +234 -0
- package/public/pages/politica-de-privacidade.html +251 -0
- package/public/pages/seo-bot-whatsapp-para-grupo.html +350 -0
- package/public/pages/seo-bot-whatsapp-sem-programar.html +350 -0
- package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +350 -0
- package/public/pages/seo-como-criar-comandos-whatsapp.html +350 -0
- package/public/pages/seo-como-evitar-spam-no-whatsapp.html +350 -0
- package/public/pages/seo-como-moderar-grupo-whatsapp.html +350 -0
- package/public/pages/seo-como-organizar-comunidade-whatsapp.html +350 -0
- package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +350 -0
- package/public/pages/stickers-admin.html +31 -0
- package/public/pages/stickers-create.html +41 -0
- package/public/pages/stickers.html +45 -0
- package/public/pages/suboperadores.html +237 -0
- package/public/pages/termos-de-uso-texto-integral.html +241 -0
- package/public/pages/termos-de-uso.html +41 -0
- package/public/pages/user-password-reset.html +32 -0
- package/public/pages/user-systemadm.html +508 -0
- package/public/pages/user.html +39 -0
- package/public/robots.txt +9 -0
- package/public/site.webmanifest +24 -0
- package/public/sitemap.xml +98 -0
- package/schemas/command-config.schema.json +582 -0
- package/scripts/baileys-compat-smoke.mjs +12 -0
- package/scripts/cache-bust.mjs +142 -0
- package/scripts/deploy.sh +916 -0
- package/scripts/email-broadcast-terms-update.mjs +170 -0
- package/scripts/enrich-command-discovery-fields.mjs +286 -0
- package/scripts/generate-command-config-schema.mjs +273 -0
- package/scripts/generate-commands-catalog.mjs +308 -0
- package/scripts/generate-module-agents.mjs +631 -0
- package/scripts/generate-seo-satellite-pages.mjs +400 -0
- package/scripts/github-deploy-notify.mjs +174 -0
- package/scripts/github-release-notify.mjs +219 -0
- package/scripts/release.sh +599 -0
- package/scripts/run-codeql-local.sh +116 -0
- package/scripts/run-prettier-all.mjs +25 -0
- package/scripts/security-smoketest.mjs +581 -0
- package/scripts/sticker-catalog-loadtest.mjs +210 -0
- package/scripts/sticker-worker-task.mjs +119 -0
- package/scripts/sync-readme-snapshot.mjs +133 -0
- package/scripts/validate-command-config-schema.mjs +130 -0
- package/scripts/validate-command-configs.mjs +15 -0
- package/scripts/wiki-sync.sh +191 -0
- package/server/auth/googleWebAuth/googleWebAuthRuntime.js +62 -0
- package/server/auth/googleWebAuth/googleWebAuthService.js +807 -0
- package/server/auth/jwt/webJwtService.js +147 -0
- package/server/auth/stickerCatalogAuthContext.js +165 -0
- package/server/auth/termsAcceptance/termsAcceptanceHandler.js +189 -0
- package/server/auth/userPassword/index.js +14 -0
- package/server/auth/userPassword/userPasswordAuthService.js +422 -0
- package/server/auth/userPassword/userPasswordCrypto.js +199 -0
- package/server/auth/userPassword/userPasswordCrypto.test.js +76 -0
- package/server/auth/userPassword/userPasswordRecoveryService.js +728 -0
- package/server/auth/validation/authSchemas.js +236 -0
- package/server/auth/webAccount/webAccountHandlers.js +1434 -0
- package/server/controllers/admin/adminBanService.js +138 -0
- package/server/controllers/admin/adminPanelHandlers.js +2083 -0
- package/server/controllers/admin/stickerCatalogAdminContext.js +17 -0
- package/server/controllers/admin/systemAdminController.js +201 -0
- package/server/controllers/email/emailAutomationController.js +239 -0
- package/server/controllers/metricsController.js +21 -0
- package/server/controllers/seo/stickerCatalogSeoContext.js +514 -0
- package/server/controllers/sticker/nonCatalogHandlers.js +303 -0
- package/server/controllers/sticker/stickerCatalogController.js +4700 -0
- package/server/controllers/system/contactController.js +115 -0
- package/server/controllers/system/githubController.js +137 -0
- package/server/controllers/system/stickerCatalogSystemContext.js +758 -0
- package/server/controllers/system/storageController.js +154 -0
- package/server/controllers/system/systemController.js +135 -0
- package/server/controllers/system/systemMetricsController.js +156 -0
- package/server/controllers/system/visitController.js +90 -0
- package/server/controllers/userController.js +145 -0
- package/server/email/emailAutomationRuntime.js +225 -0
- package/server/email/emailAutomationService.js +125 -0
- package/server/email/emailOutboxRepository.js +282 -0
- package/server/email/emailTemplateService.js +480 -0
- package/server/email/emailTransportService.js +156 -0
- package/server/http/clientIp.js +95 -0
- package/server/http/httpRequestUtils.js +262 -0
- package/server/http/httpRequestUtils.test.js +80 -0
- package/server/http/httpServer.js +180 -0
- package/server/http/requestContext.js +20 -0
- package/server/http/siteRoutingUtils.js +87 -0
- package/server/index.js +1 -0
- package/server/middleware/cachePolicy.js +26 -0
- package/server/middleware/cachePolicyHelpers.js +1 -0
- package/server/middleware/endpointRateLimit.js +181 -0
- package/server/middleware/rateLimit.js +70 -0
- package/server/middleware/requireAdminAuth.js +48 -0
- package/server/middleware/securityHeaders.js +97 -0
- package/server/routes/admin/systemAdminRouter.js +64 -0
- package/server/routes/email/emailAutomationRouter.js +46 -0
- package/server/routes/health/healthRouter.js +41 -0
- package/server/routes/indexRouter.js +234 -0
- package/server/routes/metrics/metricsRouter.js +58 -0
- package/server/routes/static/staticPageRouter.js +134 -0
- package/server/routes/sticker/catalogHandlers/catalogAdminHttp.js +105 -0
- package/server/routes/sticker/catalogHandlers/catalogAuthHttp.js +77 -0
- package/server/routes/sticker/catalogHandlers/catalogPublicHttp.js +120 -0
- package/server/routes/sticker/catalogHandlers/catalogUploadHttp.js +83 -0
- package/server/routes/sticker/catalogRouter.js +77 -0
- package/server/routes/sticker/stickerApiRouter.js +84 -0
- package/server/routes/sticker/stickerDataRouter.js +145 -0
- package/server/routes/sticker/stickerSiteRouter.js +43 -0
- package/server/routes/user/userApiPaths.js +66 -0
- package/server/routes/user/userRouter.js +65 -0
- package/server/utils/safePath.js +26 -0
- package/utils/logger/loggerModule.js +35 -0
- package/vite.config.mjs +38 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
import { maybeHandleMetricsRequest } from './metrics/metricsRouter.js';
|
|
4
|
+
import { maybeHandleHealthRequest, shouldHandleHealthPath } from './health/healthRouter.js';
|
|
5
|
+
import { getEmailAutomationRouterConfig, maybeHandleEmailAutomationRequest, shouldHandleEmailAutomationPath } from './email/emailAutomationRouter.js';
|
|
6
|
+
import { buildUserApiPaths, getUserRouterConfig, maybeHandleUserRequest, shouldHandleUserPath } from './user/userRouter.js';
|
|
7
|
+
import { getSystemAdminRouterConfig, maybeHandleSystemAdminRequest, shouldHandleSystemAdminPath } from './admin/systemAdminRouter.js';
|
|
8
|
+
import { getStickerSiteRouterConfig, maybeHandleStickerSiteRequest, shouldHandleStickerSitePath } from './sticker/stickerSiteRouter.js';
|
|
9
|
+
import { getStickerDataRouterConfig, maybeHandleStickerDataRequest, shouldHandleStickerDataPath } from './sticker/stickerDataRouter.js';
|
|
10
|
+
import { getStickerApiRouterConfig, maybeHandleStickerApiRequest, shouldHandleStickerApiPath } from './sticker/stickerApiRouter.js';
|
|
11
|
+
import { maybeHandleStaticPageRequest, shouldHandleStaticPagePath } from './static/staticPageRouter.js';
|
|
12
|
+
|
|
13
|
+
const startsWithPath = (pathname, prefix) => {
|
|
14
|
+
if (!pathname || !prefix) return false;
|
|
15
|
+
if (pathname === prefix) return true;
|
|
16
|
+
return pathname.startsWith(`${prefix}/`);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const normalizeBasePath = (value, fallback) => {
|
|
20
|
+
const raw = String(value || '').trim() || fallback;
|
|
21
|
+
const withLeadingSlash = raw.startsWith('/') ? raw : `/${raw}`;
|
|
22
|
+
const withoutTrailingSlash = withLeadingSlash.length > 1 && withLeadingSlash.endsWith('/') ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
23
|
+
return withoutTrailingSlash || fallback;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const sendNotFound = (req, res) => {
|
|
27
|
+
if (res.writableEnded) return true;
|
|
28
|
+
res.statusCode = 404;
|
|
29
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
30
|
+
if (req.method === 'HEAD') {
|
|
31
|
+
res.end();
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
res.end(JSON.stringify({ error: 'Not Found' }));
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let indexRouteConfigsPromise = null;
|
|
39
|
+
|
|
40
|
+
const loadUserConfigSafe = async () => {
|
|
41
|
+
try {
|
|
42
|
+
return await getUserRouterConfig();
|
|
43
|
+
} catch {
|
|
44
|
+
return {
|
|
45
|
+
webPath: '/user',
|
|
46
|
+
passwordResetWebPath: '/user/password-reset',
|
|
47
|
+
apiBasePath: '/api',
|
|
48
|
+
legacyApiBasePath: '/api/sticker-packs',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const loadSystemAdminConfigSafe = async () => {
|
|
54
|
+
try {
|
|
55
|
+
return await getSystemAdminRouterConfig();
|
|
56
|
+
} catch {
|
|
57
|
+
return {
|
|
58
|
+
webPath: '/user/systemadm',
|
|
59
|
+
legacyWebPath: '/stickers/admin',
|
|
60
|
+
apiAdminBasePath: '/api/admin',
|
|
61
|
+
apiAdminSessionPath: '/api/admin/session',
|
|
62
|
+
legacyApiAdminBasePath: '/api/sticker-packs/admin',
|
|
63
|
+
legacyApiAdminSessionPath: '/api/sticker-packs/admin/session',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const loadEmailAutomationConfigSafe = async () => {
|
|
69
|
+
try {
|
|
70
|
+
return await getEmailAutomationRouterConfig();
|
|
71
|
+
} catch {
|
|
72
|
+
return {
|
|
73
|
+
apiBasePath: '/api/email',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const loadStickerSiteConfigSafe = async () => {
|
|
79
|
+
try {
|
|
80
|
+
return await getStickerSiteRouterConfig();
|
|
81
|
+
} catch {
|
|
82
|
+
return {
|
|
83
|
+
enabled: true,
|
|
84
|
+
webPath: '/stickers',
|
|
85
|
+
apiBasePath: '/api/sticker-packs',
|
|
86
|
+
orphanApiPath: '/api/sticker-packs/orphan-stickers',
|
|
87
|
+
dataPublicPath: '/data',
|
|
88
|
+
dataPublicDir: path.resolve(process.cwd(), 'data'),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const loadStickerDataConfigSafe = async () => {
|
|
94
|
+
try {
|
|
95
|
+
return await getStickerDataRouterConfig();
|
|
96
|
+
} catch {
|
|
97
|
+
return {
|
|
98
|
+
dataPublicPath: '/data',
|
|
99
|
+
dataPublicDir: path.resolve(process.cwd(), 'data'),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const loadStickerApiConfigSafe = async () => {
|
|
105
|
+
try {
|
|
106
|
+
return await getStickerApiRouterConfig();
|
|
107
|
+
} catch {
|
|
108
|
+
return {
|
|
109
|
+
apiBasePath: '/api/sticker-packs',
|
|
110
|
+
marketplaceStatsPath: '/api/marketplace/stats',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const getIndexRouteConfigs = async () => {
|
|
116
|
+
if (!indexRouteConfigsPromise) {
|
|
117
|
+
indexRouteConfigsPromise = Promise.all([loadUserConfigSafe(), loadSystemAdminConfigSafe(), loadEmailAutomationConfigSafe(), loadStickerSiteConfigSafe(), loadStickerDataConfigSafe(), loadStickerApiConfigSafe()]).then(([userConfig, systemAdminConfig, emailAutomationConfig, stickerSiteConfig, stickerDataConfig, stickerApiConfig]) => ({
|
|
118
|
+
userConfig,
|
|
119
|
+
systemAdminConfig,
|
|
120
|
+
emailAutomationConfig,
|
|
121
|
+
stickerConfig: {
|
|
122
|
+
...stickerSiteConfig,
|
|
123
|
+
...stickerDataConfig,
|
|
124
|
+
...stickerApiConfig,
|
|
125
|
+
},
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return indexRouteConfigsPromise;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const shouldHandleSystemAdminStep = (pathname, systemAdminConfig) => shouldHandleSystemAdminPath(pathname, systemAdminConfig);
|
|
133
|
+
|
|
134
|
+
const shouldHandleUserStep = (pathname, userConfig) => shouldHandleUserPath(pathname, userConfig);
|
|
135
|
+
|
|
136
|
+
const shouldHandleMetricsStep = (pathname, metricsPath) => startsWithPath(pathname, normalizeBasePath(metricsPath, '/metrics'));
|
|
137
|
+
|
|
138
|
+
export const routeRequest = async (req, res, { pathname, url, metricsPath = '/metrics', configs = null } = {}) => {
|
|
139
|
+
const resolvedConfigs = configs || (await getIndexRouteConfigs());
|
|
140
|
+
const userConfig = resolvedConfigs?.userConfig || null;
|
|
141
|
+
const systemAdminConfig = resolvedConfigs?.systemAdminConfig || null;
|
|
142
|
+
const emailAutomationConfig = resolvedConfigs?.emailAutomationConfig || null;
|
|
143
|
+
const stickerConfig = resolvedConfigs?.stickerConfig || null;
|
|
144
|
+
|
|
145
|
+
// 1) Metrics
|
|
146
|
+
if (shouldHandleMetricsStep(pathname, metricsPath)) {
|
|
147
|
+
const handled = await maybeHandleMetricsRequest(req, res, { pathname, metricsPath });
|
|
148
|
+
if (handled) return true;
|
|
149
|
+
return sendNotFound(req, res);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 2) Health checks
|
|
153
|
+
if (shouldHandleHealthPath(pathname)) {
|
|
154
|
+
const handled = await maybeHandleHealthRequest(req, res, { pathname });
|
|
155
|
+
if (handled) return true;
|
|
156
|
+
return sendNotFound(req, res);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 3) Email automation API
|
|
160
|
+
if (shouldHandleEmailAutomationPath(pathname, emailAutomationConfig)) {
|
|
161
|
+
const handled = await maybeHandleEmailAutomationRequest(req, res, { pathname, url });
|
|
162
|
+
if (handled) return true;
|
|
163
|
+
return sendNotFound(req, res);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 4) User
|
|
167
|
+
const systemAdminCandidate = shouldHandleSystemAdminStep(pathname, systemAdminConfig);
|
|
168
|
+
if (shouldHandleUserStep(pathname, userConfig)) {
|
|
169
|
+
const handled = await maybeHandleUserRequest(req, res, { pathname, url });
|
|
170
|
+
if (handled) return true;
|
|
171
|
+
|
|
172
|
+
// Permite /user/systemadm continuar para o router de admin.
|
|
173
|
+
if (!systemAdminCandidate) return sendNotFound(req, res);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 5) System admin + legacy /stickers/admin
|
|
177
|
+
if (systemAdminCandidate) {
|
|
178
|
+
const handled = await maybeHandleSystemAdminRequest(req, res, { pathname, url });
|
|
179
|
+
if (handled) return true;
|
|
180
|
+
return sendNotFound(req, res);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 6) Sticker catalog apenas nos prefixes permitidos
|
|
184
|
+
if (shouldHandleStickerSitePath(pathname, stickerConfig)) {
|
|
185
|
+
const handled = await maybeHandleStickerSiteRequest(req, res, { pathname, url });
|
|
186
|
+
if (handled) return true;
|
|
187
|
+
return sendNotFound(req, res);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (shouldHandleStickerDataPath(pathname, stickerConfig)) {
|
|
191
|
+
const handled = await maybeHandleStickerDataRequest(req, res, {
|
|
192
|
+
pathname,
|
|
193
|
+
config: {
|
|
194
|
+
dataPublicPath: stickerConfig?.dataPublicPath,
|
|
195
|
+
dataPublicDir: stickerConfig?.dataPublicDir,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
if (handled) return true;
|
|
199
|
+
return sendNotFound(req, res);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (shouldHandleStickerApiPath(pathname, stickerConfig)) {
|
|
203
|
+
const handled = await maybeHandleStickerApiRequest(req, res, {
|
|
204
|
+
pathname,
|
|
205
|
+
url,
|
|
206
|
+
config: {
|
|
207
|
+
apiBasePath: stickerConfig?.apiBasePath,
|
|
208
|
+
marketplaceStatsPath: stickerConfig?.marketplaceStatsPath,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
if (handled) return true;
|
|
212
|
+
return sendNotFound(req, res);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 7) Paginas estaticas (templates em public/pages)
|
|
216
|
+
if (shouldHandleStaticPagePath(pathname)) {
|
|
217
|
+
const handled = await maybeHandleStaticPageRequest(req, res, { pathname });
|
|
218
|
+
if (handled) return true;
|
|
219
|
+
return sendNotFound(req, res);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 8) 404 global
|
|
223
|
+
return sendNotFound(req, res);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export const getUserApiPathsFromConfig = (userConfig = null) => {
|
|
227
|
+
const apiBasePath = userConfig?.apiBasePath || '/api';
|
|
228
|
+
const paths = new Set(buildUserApiPaths(apiBasePath));
|
|
229
|
+
const legacyApiBasePath = userConfig?.legacyApiBasePath || '/api/sticker-packs';
|
|
230
|
+
for (const path of buildUserApiPaths(legacyApiBasePath, { legacyCompatible: true })) {
|
|
231
|
+
paths.add(path);
|
|
232
|
+
}
|
|
233
|
+
return paths;
|
|
234
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { sendMetricsResponse } from '../../controllers/metricsController.js';
|
|
2
|
+
import { resolveClientIp } from '../../http/clientIp.js';
|
|
3
|
+
|
|
4
|
+
const startsWithPath = (pathname, prefix) => {
|
|
5
|
+
if (!pathname || !prefix) return false;
|
|
6
|
+
if (pathname === prefix) return true;
|
|
7
|
+
return pathname.startsWith(`${prefix}/`);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const parseEnvBool = (value, fallback = false) => {
|
|
11
|
+
if (value === undefined || value === null || value === '') return fallback;
|
|
12
|
+
const normalized = String(value).trim().toLowerCase();
|
|
13
|
+
if (['1', 'true', 'yes', 'y', 'on'].includes(normalized)) return true;
|
|
14
|
+
if (['0', 'false', 'no', 'n', 'off'].includes(normalized)) return false;
|
|
15
|
+
return fallback;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const METRICS_ALLOW_REMOTE = parseEnvBool(process.env.METRICS_ALLOW_REMOTE, false);
|
|
19
|
+
const METRICS_TOKEN = String(process.env.METRICS_TOKEN || process.env.METRICS_API_KEY || '').trim();
|
|
20
|
+
const LOOPBACK_IPS = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);
|
|
21
|
+
|
|
22
|
+
const extractMetricsTokenFromRequest = (req) => {
|
|
23
|
+
const headerToken = String(req?.headers?.['x-metrics-token'] || '').trim();
|
|
24
|
+
if (headerToken) return headerToken;
|
|
25
|
+
const authHeader = String(req?.headers?.authorization || '').trim();
|
|
26
|
+
if (!authHeader.toLowerCase().startsWith('bearer ')) return '';
|
|
27
|
+
return authHeader.slice(7).trim();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const isLoopbackRequest = (req) => LOOPBACK_IPS.has(resolveClientIp(req));
|
|
31
|
+
|
|
32
|
+
const canAccessMetrics = (req) => {
|
|
33
|
+
if (METRICS_TOKEN) {
|
|
34
|
+
const requestToken = extractMetricsTokenFromRequest(req);
|
|
35
|
+
return Boolean(requestToken && requestToken === METRICS_TOKEN);
|
|
36
|
+
}
|
|
37
|
+
if (METRICS_ALLOW_REMOTE) return true;
|
|
38
|
+
return isLoopbackRequest(req);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const sendForbidden = (req, res) => {
|
|
42
|
+
if (res.writableEnded) return true;
|
|
43
|
+
res.statusCode = 403;
|
|
44
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
45
|
+
if (req.method === 'HEAD') {
|
|
46
|
+
res.end();
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
res.end(JSON.stringify({ error: 'Forbidden' }));
|
|
50
|
+
return true;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const maybeHandleMetricsRequest = async (req, res, { pathname, metricsPath }) => {
|
|
54
|
+
if (!startsWithPath(pathname, metricsPath)) return false;
|
|
55
|
+
if (!canAccessMetrics(req)) return sendForbidden(req, res);
|
|
56
|
+
await sendMetricsResponse(res);
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import logger from '#logger';
|
|
5
|
+
|
|
6
|
+
const normalizeBasePath = (value, fallback) => {
|
|
7
|
+
const raw = String(value || '').trim() || fallback;
|
|
8
|
+
const withLeadingSlash = raw.startsWith('/') ? raw : `/${raw}`;
|
|
9
|
+
const withoutTrailingSlash = withLeadingSlash.length > 1 && withLeadingSlash.endsWith('/') ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
|
|
10
|
+
return withoutTrailingSlash || fallback;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const normalizeRoutePath = (pathname) => {
|
|
14
|
+
const rawPath = String(pathname || '').trim();
|
|
15
|
+
if (!rawPath || rawPath === '/') return '/';
|
|
16
|
+
return rawPath.endsWith('/') ? rawPath.slice(0, -1) : rawPath;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const STICKER_LOGIN_WEB_PATH = normalizeBasePath(process.env.STICKER_LOGIN_WEB_PATH, '/login');
|
|
20
|
+
const PUBLIC_PAGES_DIR = path.join(process.cwd(), 'public', 'pages');
|
|
21
|
+
const SEO_ROUTE_PREFIX = '/seo/';
|
|
22
|
+
const SEO_SLUG_REGEX = /^[a-z0-9-]+$/;
|
|
23
|
+
const INDEX_FILE_SUFFIX = '/index.html';
|
|
24
|
+
|
|
25
|
+
const STATIC_PAGE_ROUTE_TO_FILE = new Map(
|
|
26
|
+
[
|
|
27
|
+
['/', 'home.html'],
|
|
28
|
+
['/api-docs', 'api-docs.html'],
|
|
29
|
+
['/aup', 'aup.html'],
|
|
30
|
+
['/comandos', 'comandos.html'],
|
|
31
|
+
['/dpa', 'dpa.html'],
|
|
32
|
+
['/licenca', 'licenca.html'],
|
|
33
|
+
['/notice-and-takedown', 'notice-and-takedown.html'],
|
|
34
|
+
['/politica-de-privacidade', 'politica-de-privacidade.html'],
|
|
35
|
+
['/suboperadores', 'suboperadores.html'],
|
|
36
|
+
['/termos-de-uso', 'termos-de-uso.html'],
|
|
37
|
+
['/termos-de-uso/texto-integral', 'termos-de-uso-texto-integral.html'],
|
|
38
|
+
['/termos-de-uso/texto-integral.html', 'termos-de-uso-texto-integral.html'],
|
|
39
|
+
[STICKER_LOGIN_WEB_PATH, 'login.html'],
|
|
40
|
+
].map(([routePath, fileName]) => [normalizeRoutePath(routePath), fileName]),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const resolveMappedTemplateName = (normalizedPath) => {
|
|
44
|
+
const mappedTemplate = STATIC_PAGE_ROUTE_TO_FILE.get(normalizedPath);
|
|
45
|
+
if (mappedTemplate) return mappedTemplate;
|
|
46
|
+
|
|
47
|
+
if (normalizedPath.startsWith(SEO_ROUTE_PREFIX)) {
|
|
48
|
+
const seoSlug = normalizedPath.slice(SEO_ROUTE_PREFIX.length);
|
|
49
|
+
if (seoSlug && SEO_SLUG_REGEX.test(seoSlug)) {
|
|
50
|
+
return `seo-${seoSlug}.html`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const resolveStaticTemplateName = (pathname) => {
|
|
58
|
+
const normalizedPath = normalizeRoutePath(pathname);
|
|
59
|
+
const mappedTemplate = resolveMappedTemplateName(normalizedPath);
|
|
60
|
+
if (mappedTemplate) return mappedTemplate;
|
|
61
|
+
|
|
62
|
+
if (normalizedPath.endsWith(INDEX_FILE_SUFFIX)) {
|
|
63
|
+
const withoutIndex = normalizedPath.slice(0, -INDEX_FILE_SUFFIX.length);
|
|
64
|
+
const aliasPath = withoutIndex || '/';
|
|
65
|
+
return resolveMappedTemplateName(aliasPath);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const sendHtml = (req, res, html) => {
|
|
72
|
+
res.statusCode = 200;
|
|
73
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
74
|
+
if (req.method === 'HEAD') {
|
|
75
|
+
res.end();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
res.end(html);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const sendJson = (req, res, statusCode, payload) => {
|
|
82
|
+
const body = JSON.stringify(payload);
|
|
83
|
+
res.statusCode = statusCode;
|
|
84
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
85
|
+
if (req.method === 'HEAD') {
|
|
86
|
+
res.end();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
res.end(body);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const shouldHandleStaticPagePath = (pathname) => Boolean(resolveStaticTemplateName(pathname));
|
|
93
|
+
|
|
94
|
+
export const maybeHandleStaticPageRequest = async (req, res, { pathname } = {}) => {
|
|
95
|
+
if (!['GET', 'HEAD'].includes(req.method || '')) return false;
|
|
96
|
+
|
|
97
|
+
const normalizedPath = normalizeRoutePath(pathname);
|
|
98
|
+
const templateName = resolveStaticTemplateName(normalizedPath);
|
|
99
|
+
if (!templateName) return false;
|
|
100
|
+
|
|
101
|
+
// Redireciona usuário logado tentando acessar página de login
|
|
102
|
+
if (templateName === 'login.html') {
|
|
103
|
+
try {
|
|
104
|
+
const session = await globalThis.resolveGoogleWebSessionFromRequestBridge?.(req);
|
|
105
|
+
if (session?.sub && (session.ownerJid || session.ownerPhone || session.email)) {
|
|
106
|
+
res.statusCode = 302;
|
|
107
|
+
res.setHeader('Location', '/user/');
|
|
108
|
+
res.end();
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
logger.warn('Falha ao verificar sessao para redirecionamento de login.', { error: error?.message });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const templatePath = path.join(PUBLIC_PAGES_DIR, templateName);
|
|
117
|
+
try {
|
|
118
|
+
const html = await fs.readFile(templatePath, 'utf8');
|
|
119
|
+
sendHtml(req, res, html);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
if (error?.code === 'ENOENT') {
|
|
122
|
+
sendJson(req, res, 404, { error: 'Template da pagina nao encontrado.' });
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
logger.error('Falha ao renderizar pagina estatica.', {
|
|
126
|
+
action: 'static_page_render_failed',
|
|
127
|
+
path: normalizedPath,
|
|
128
|
+
template: templateName,
|
|
129
|
+
error: error?.message,
|
|
130
|
+
});
|
|
131
|
+
sendJson(req, res, 500, { error: 'Falha interna ao renderizar pagina.' });
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export const handleCatalogAdminRoutes = async ({ req, res, url, segments, handlers, sendJson }) => {
|
|
2
|
+
if (segments[0] !== 'admin') return false;
|
|
3
|
+
|
|
4
|
+
if (segments.length === 2 && segments[1] === 'overview') {
|
|
5
|
+
await handlers.handleAdminOverviewRequest(req, res);
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (segments.length === 2 && segments[1] === 'users') {
|
|
10
|
+
await handlers.handleAdminUsersRequest(req, res, url);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (segments.length === 3 && segments[1] === 'users' && segments[2] === 'force-logout') {
|
|
15
|
+
await handlers.handleAdminForceLogoutRequest(req, res);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (segments.length === 2 && segments[1] === 'feature-flags') {
|
|
20
|
+
await handlers.handleAdminFeatureFlagsRequest(req, res);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (segments.length === 2 && segments[1] === 'ops') {
|
|
25
|
+
await handlers.handleAdminOpsActionRequest(req, res);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (segments.length === 2 && segments[1] === 'search') {
|
|
30
|
+
await handlers.handleAdminSearchRequest(req, res, url);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (segments.length === 2 && segments[1] === 'export') {
|
|
35
|
+
await handlers.handleAdminExportRequest(req, res, url);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (segments.length === 2 && segments[1] === 'moderators') {
|
|
40
|
+
await handlers.handleAdminModeratorsRequest(req, res);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (segments.length === 3 && segments[1] === 'moderators') {
|
|
45
|
+
await handlers.handleAdminModeratorDeleteRequest(req, res, segments[2]);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (segments.length === 2 && segments[1] === 'packs') {
|
|
50
|
+
await handlers.handleAdminPacksRequest(req, res, url);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (segments.length === 3 && segments[1] === 'packs') {
|
|
55
|
+
if (req.method === 'DELETE') {
|
|
56
|
+
await handlers.handleAdminPackDeleteRequest(req, res, segments[2]);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
await handlers.handleAdminPackDetailsRequest(req, res, segments[2]);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (segments.length === 4 && segments[1] === 'packs' && segments[3] === 'delete') {
|
|
64
|
+
await handlers.handleAdminPackDeleteRequest(req, res, segments[2]);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (segments.length === 5 && segments[1] === 'packs' && segments[3] === 'stickers') {
|
|
69
|
+
await handlers.handleAdminPackStickerDeleteRequest(req, res, segments[2], segments[4]);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (segments.length === 6 && segments[1] === 'packs' && segments[3] === 'stickers' && segments[5] === 'delete') {
|
|
74
|
+
await handlers.handleAdminPackStickerDeleteRequest(req, res, segments[2], segments[4]);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (segments.length === 3 && segments[1] === 'stickers') {
|
|
79
|
+
await handlers.handleAdminGlobalStickerDeleteRequest(req, res, segments[2]);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (segments.length === 4 && segments[1] === 'stickers' && segments[3] === 'delete') {
|
|
84
|
+
await handlers.handleAdminGlobalStickerDeleteRequest(req, res, segments[2]);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (segments.length === 2 && segments[1] === 'bans') {
|
|
89
|
+
await handlers.handleAdminBansRequest(req, res);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (segments.length === 4 && segments[1] === 'bans' && segments[3] === 'revoke') {
|
|
94
|
+
await handlers.handleAdminBanRevokeRequest(req, res, segments[2]);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (segments.length === 3 && segments[1] === 'bans') {
|
|
99
|
+
await handlers.handleAdminBanRevokeRequest(req, res, segments[2]);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
sendJson(req, res, 404, { error: 'Rota admin nao encontrada.' });
|
|
104
|
+
return true;
|
|
105
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const METHOD_NOT_ALLOWED_BODY = { error: 'Metodo nao permitido.' };
|
|
2
|
+
|
|
3
|
+
const isReadMethod = (method) => method === 'GET' || method === 'HEAD';
|
|
4
|
+
|
|
5
|
+
export const handleCatalogAuthRoutes = async ({ req, res, pathname, url, apiBasePath, handlers, sendJson }) => {
|
|
6
|
+
if (pathname === `${apiBasePath}/auth/google/session`) {
|
|
7
|
+
await handlers.handleGoogleAuthSessionRequest(req, res);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (pathname === `${apiBasePath}/auth/login`) {
|
|
12
|
+
await handlers.handlePasswordLoginRequest(req, res);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (pathname === `${apiBasePath}/auth/terms/acceptance`) {
|
|
17
|
+
await handlers.handleTermsAcceptanceRequest(req, res);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (pathname === `${apiBasePath}/auth/password`) {
|
|
22
|
+
await handlers.handlePasswordAuthRequest(req, res);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (pathname === `${apiBasePath}/auth/password/recovery/request`) {
|
|
27
|
+
await handlers.handlePasswordRecoveryRequest(req, res);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (pathname === `${apiBasePath}/auth/password/recovery/verify`) {
|
|
32
|
+
await handlers.handlePasswordRecoveryVerifyRequest(req, res);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const passwordRecoverySessionBasePath = `${apiBasePath}/auth/password/recovery/session`;
|
|
37
|
+
if (pathname === passwordRecoverySessionBasePath) {
|
|
38
|
+
if (isReadMethod(req.method || '')) {
|
|
39
|
+
await handlers.handlePasswordRecoverySessionStatusRequest(req, res);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (req.method === 'POST') {
|
|
44
|
+
await handlers.handlePasswordRecoverySessionCreateRequest(req, res);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (pathname === `${passwordRecoverySessionBasePath}/request`) {
|
|
53
|
+
await handlers.handlePasswordRecoverySessionRequest(req, res);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (pathname === `${passwordRecoverySessionBasePath}/verify`) {
|
|
58
|
+
await handlers.handlePasswordRecoverySessionVerifyRequest(req, res);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (pathname === `${apiBasePath}/me`) {
|
|
63
|
+
if (!isReadMethod(req.method || '')) {
|
|
64
|
+
sendJson(req, res, 405, METHOD_NOT_ALLOWED_BODY);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
await handlers.handleMyProfileRequest(req, res, url);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (pathname === `${apiBasePath}/admin/session`) {
|
|
72
|
+
await handlers.handleAdminPanelSessionRequest(req, res);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return false;
|
|
77
|
+
};
|