Update community IDs, enhance CaptchaController caching, and modify home template for Altcha integration

- Changed community IDs for various components in graph.json to reflect updated associations.
- Added Cache-Control headers to the challenge and config methods in CaptchaController to prevent caching by CDNs and proxies.
- Updated the Altcha widget in home.html.twig to include a language attribute for better localization.
- Added a new AST cache file for CaptchaController to improve performance.
- Updated manifest.json with new modification times and AST hashes for several files.
This commit is contained in:
hamed
2026-07-10 11:57:16 +03:30
parent ec184dfcc8
commit 3eee6c3886
11 changed files with 111 additions and 116 deletions
+10 -12
View File
@@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import 'altcha';
import 'altcha/i18n/fa'; // ثبت locale رسمی فارسی → با language="fa" فعال می‌شود
// ALTCHA خودمیزبان: widget با گرفتن challenge از بک‌اند، proof-of-work را در
// پس‌زمینه‌ی مرورگر حل می‌کند و مقدار base64 حل‌شده را در event `verified` می‌دهد.
@@ -10,16 +11,6 @@ interface AltchaProps {
challengeUrl?: string;
}
// برچسب‌های فارسی widget (ترجمه‌ی رسمی locale fa).
const FA_STRINGS = JSON.stringify({
label: 'من ربات نیستم',
verifying: 'در حال بررسی...',
verified: 'تأیید شد',
waitAlert: 'در حال بررسی... لطفاً منتظر بمانید.',
error: 'احراز هویت ناموفق بود. کمی بعد دوباره تلاش کنید.',
expired: 'احراز هویت منقضی شد. دوباره تلاش کنید.',
});
// altcha-widget یک custom element است؛ به JSX معرفی می‌شود (React 19: namespace زیر React.JSX).
declare module 'react' {
namespace JSX {
@@ -50,7 +41,11 @@ export default function Altcha({ onVerified, challengeUrl = '/api/v1/altcha/chal
return () => { alive = false; };
}, [onVerified]);
// config (challengeurl/strings/auto) را با setAttribute ست می‌کنیم، نه JSX prop —
// React ممکن است پراپ custom element را به‌صورت property ست کند و widget آن را
// نخواند؛ نتیجه challengeurl خالی و fetch صفحه‌ی جاری (HTML) به‌جای JSON بود.
useEffect(() => {
if (enabled !== true) return;
const el = ref.current;
if (!el) return;
@@ -61,11 +56,14 @@ export default function Altcha({ onVerified, challengeUrl = '/api/v1/altcha/chal
}
};
el.setAttribute('challengeurl', challengeUrl);
el.setAttribute('language', 'fa');
el.setAttribute('auto', 'onload');
el.addEventListener('statechange', onStateChange);
return () => el.removeEventListener('statechange', onStateChange);
}, [onVerified, enabled]);
}, [onVerified, enabled, challengeUrl]);
if (enabled !== true) return null;
return <altcha-widget ref={ref as React.Ref<HTMLElement>} challengeurl={challengeUrl} strings={FA_STRINGS} />;
return <altcha-widget ref={ref as React.Ref<HTMLElement>} />;
}
+1
View File
@@ -1,2 +1,3 @@
import './styles.css';
import 'altcha'; // ثبت custom element <altcha-widget> برای مودال‌های صفحه‌ی عمومی
import 'altcha/i18n/fa'; // locale رسمی فارسی → با language="fa" روی widget فعال می‌شود
+1 -1
View File
@@ -39,7 +39,7 @@ x-app-env: &app-env
# ALTCHA self-hosted captcha. HMAC key is a secret → inject from Coolify's
# Environment Variables tab. Symfony reads this via %env(bool:...)% so
# true/false (or 1/0) both work; کپچا در prod روشن است.
ALTCHA_ENABLED: "true"
ALTCHA_ENABLED: "false"
ALTCHA_HMAC_KEY: ${ALTCHA_HMAC_KEY}
ALTCHA_MAX_NUMBER: "100000"
ALTCHA_EXPIRE_SECONDS: "300"
-3
View File
@@ -693,7 +693,6 @@
"691": "Community 691",
"692": "Community 692",
"693": "Community 693",
"694": "Community 694",
"695": "Community 695",
"696": "Community 696",
"697": "Community 697",
@@ -702,14 +701,12 @@
"700": "Community 700",
"701": "Community 701",
"702": "Community 702",
"703": "Community 703",
"704": "Community 704",
"705": "Community 705",
"706": "Community 706",
"707": "Community 707",
"708": "Community 708",
"709": "Community 709",
"710": "Community 710",
"711": "Community 711",
"712": "Community 712",
"713": "Community 713",
+19 -30
View File
@@ -1,16 +1,16 @@
# Graph Report - clinicpro (2026-07-10)
## Corpus Check
- 736 files · ~541,964 words
- 736 files · ~542,018 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 9274 nodes · 12833 edges · 719 communities (569 shown, 150 thin omitted)
- 9274 nodes · 12833 edges · 716 communities (567 shown, 149 thin omitted)
- Extraction: 98% EXTRACTED · 2% INFERRED · 0% AMBIGUOUS · INFERRED: 279 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `c3c52080`
- Built from commit: `ec184dfc`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -695,7 +695,6 @@
- [[_COMMUNITY_Community 691|Community 691]]
- [[_COMMUNITY_Community 692|Community 692]]
- [[_COMMUNITY_Community 693|Community 693]]
- [[_COMMUNITY_Community 694|Community 694]]
- [[_COMMUNITY_Community 695|Community 695]]
- [[_COMMUNITY_Community 696|Community 696]]
- [[_COMMUNITY_Community 697|Community 697]]
@@ -704,14 +703,12 @@
- [[_COMMUNITY_Community 700|Community 700]]
- [[_COMMUNITY_Community 701|Community 701]]
- [[_COMMUNITY_Community 702|Community 702]]
- [[_COMMUNITY_Community 703|Community 703]]
- [[_COMMUNITY_Community 704|Community 704]]
- [[_COMMUNITY_Community 705|Community 705]]
- [[_COMMUNITY_Community 706|Community 706]]
- [[_COMMUNITY_Community 707|Community 707]]
- [[_COMMUNITY_Community 708|Community 708]]
- [[_COMMUNITY_Community 709|Community 709]]
- [[_COMMUNITY_Community 710|Community 710]]
- [[_COMMUNITY_Community 711|Community 711]]
- [[_COMMUNITY_Community 712|Community 712]]
- [[_COMMUNITY_Community 713|Community 713]]
@@ -748,7 +745,7 @@
## Import Cycles
- None detected.
## Communities (719 total, 150 thin omitted)
## Communities (716 total, 149 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.05
@@ -816,7 +813,7 @@ Nodes (7): PaymentController, Appointment, JsonResponse, Payment, Request, Respo
### Community 16 - "Community 16"
Cohesion: 0.06
Nodes (8): PatientSession, SmsWallet, AppLog, Appointment, Collection, PatientRecord, self, SessionService
Nodes (9): PatientSession, SmsWallet, AppLog, LogPruneService, Appointment, Collection, PatientRecord, self (+1 more)
### Community 17 - "Community 17"
Cohesion: 0.05
@@ -1364,7 +1361,7 @@ Nodes (15): Date Overrides, DELETE `/api/v1/appointment-settings/date-override/{
### Community 161 - "Community 161"
Cohesion: 0.24
Nodes (5): ClaimsListNPlusOneTest, ClaimItem, ClaimService, Claim, Invoice
Nodes (7): ClaimSubmitterInterface, ClaimService, ManualClaimSubmitter, Claim, Invoice, Claim, ClaimSubmissionResult
### Community 162 - "Community 162"
Cohesion: 0.13
@@ -1612,7 +1609,7 @@ Nodes (51): Bulk import / export, DELETE `/api/v1/admin/insurance/{id}`, DELETE
### Community 229 - "Community 229"
Cohesion: 0.14
Nodes (13): DELETE `/api/v1/representation/{uuid}`, Errors, Errors, GET `/api/v1/representation/{uuid}/dashboard/monthly`, GET `/api/v1/site-context`, Path Parameters, Query Parameters, Query Parameters (+5 more)
Nodes (13): Errors, GET `/api/v1/representation/{uuid}/dashboard/monthly`, GET `/api/v1/representation/{uuid}/dashboard/yearly`, GET `/api/v1/site-context`, Path Parameters, Query Parameters, Query Parameters, Query Parameters (+5 more)
### Community 230 - "Community 230"
Cohesion: 0.35
@@ -1871,8 +1868,8 @@ Cohesion: 0.22
Nodes (9): Clinic Management, DELETE `/api/v1/admin/clinic/{uuid}`, Errors, GET `/api/v1/admin/clinics`, PATCH `/api/v1/admin/clinic/{uuid}/status`, Query Parameters, Response `200`, Response `200` (+1 more)
### Community 297 - "Community 297"
Cohesion: 0.22
Nodes (9): DELETE `/api/v1/representation/iban/{id}`, Errors, Errors, GET `/api/v1/representation/doctors/stats`, GET `/api/v1/representation/me`, Response `200`, Response `200`, Response `200` (+1 more)
Cohesion: 0.15
Nodes (13): DELETE `/api/v1/representation/iban/{id}`, Errors, Errors, Errors, GET `/api/v1/representation/doctors`, GET `/api/v1/representation/doctors/stats`, GET `/api/v1/representation/me`, Query Parameters (+5 more)
### Community 298 - "Community 298"
Cohesion: 0.22
@@ -1947,8 +1944,8 @@ Cohesion: 0.31
Nodes (3): SubscriptionPlanRepository, ManagerRegistry, SubscriptionPlan
### Community 318 - "Community 318"
Cohesion: 0.21
Nodes (5): ErrorCodes, AuthController, JsonResponse, Request, User
Cohesion: 0.24
Nodes (4): AuthController, JsonResponse, Request, User
### Community 319 - "Community 319"
Cohesion: 0.39
@@ -2175,8 +2172,8 @@ Cohesion: 0.29
Nodes (7): بک‌اند — endpoint جدید: `GET /api/v1/my/appointments` `[IS_AUTHENTICATED_FULLY]`, فرانت‌اند — `AppointmentsPage.tsx`, مرحله ۸ — نوبت‌های فیلترشده (بک‌اند + فرانت‌اند) — API جدید, نمای جدولی (`TableView`):, نمای زمانبندی (`TimelineView`):, هدر صفحه (مشترک هر دو نما):, وضعیت‌های نوبت (باید در entity و frontend هر دو باشند):
### Community 380 - "Community 380"
Cohesion: 0.36
Nodes (5): ClinicServiceController, JsonResponse, Request, ServiceSection, User
Cohesion: 0.31
Nodes (6): ErrorCodes, ClinicServiceController, JsonResponse, Request, ServiceSection, User
### Community 381 - "Community 381"
Cohesion: 0.13
@@ -2239,8 +2236,8 @@ Cohesion: 0.33
Nodes (6): Refactoring Plan, فاز ۰ — مستندسازی (۳ تا ۵ روز، قبل از هر کدنویسی), فاز ۱ — زیرساخت پایه (task-01), فاز ۲ — پیاده‌سازی ماژول‌ها (به ترتیب dependency), فاز ۳ — بهینه‌سازی (بعد از پیاده‌سازی), فاز ۴ — آماده‌سازی تولید
### Community 397 - "Community 397"
Cohesion: 0.36
Nodes (4): ClaimAmountBoundsTest, Claim, Doctor, User
Cohesion: 0.21
Nodes (6): ClaimAmountBoundsTest, ClaimsListNPlusOneTest, ClaimItem, Claim, Doctor, User
### Community 398 - "Community 398"
Cohesion: 0.22
@@ -2248,7 +2245,7 @@ Nodes (7): initiate(), refund(), reverse(), verify(), PaymentInitResult, Payment
### Community 399 - "Community 399"
Cohesion: 0.23
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260628165710
Nodes (5): AbstractMigration, Schema, Version20260609130407, Schema, Version20260619121047
### Community 401 - "Community 401"
Cohesion: 0.12
@@ -2775,8 +2772,8 @@ Cohesion: 0.43
Nodes (3): InvoiceService, Invoice, PatientSession
### Community 631 - "Community 631"
Cohesion: 0.53
Nodes (4): ClaimSubmitterInterface, ManualClaimSubmitter, Claim, ClaimSubmissionResult
Cohesion: 0.67
Nodes (3): DELETE `/api/v1/representation/{uuid}`, Errors, Response `200`
### Community 633 - "Community 633"
Cohesion: 0.40
@@ -2906,10 +2903,6 @@ Nodes (4): GET `/api/v1/admin/representations`, Query Parameters, Representation
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/doctor/{uuid}`, Path Parameters, Response `200`
### Community 694 - "Community 694"
Cohesion: 0.50
Nodes (4): Errors, GET `/api/v1/representation/doctors`, Query Parameters, Response `200`
### Community 695 - "Community 695"
Cohesion: 0.67
Nodes (3): DELETE `/api/v1/sms/template/{uuid}`, Errors, Response `200`
@@ -2942,10 +2935,6 @@ Nodes (4): Errors, Path Parameters, POST `/api/v1/clinic-pro/doctor-address/from
Cohesion: 0.50
Nodes (4): Errors, POST `/api/v1/user/register`, Request Body, Response `201`
### Community 710 - "Community 710"
Cohesion: 0.67
Nodes (3): GET `/api/v1/representation/{uuid}/dashboard/yearly`, Query Parameters, Response `200`
### Community 712 - "Community 712"
Cohesion: 0.67
Nodes (3): GET `/api/v1/clinic-pro/doctor-addresses/{doctorId}`, Path Parameters, Response `200`
@@ -2973,7 +2962,7 @@ Nodes (4): Errors, GET `/api/v1/representation/{uuid}`, Path Parameters, Respons
## Knowledge Gaps
- **4032 isolated node(s):** `ALLOWED_ROLES`, `Pricing`, `ImageCropModalProps`, `TenantInsurance`, `CoverageRow` (+4027 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **150 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **149 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
@@ -0,0 +1 @@
{"nodes": [{"id": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "label": "CaptchaController.php", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L1"}, {"id": "captcha_captchacontroller_captchacontroller", "label": "CaptchaController", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L10"}, {"id": "basecontroller", "label": "BaseController", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "captcha_captchacontroller_captchacontroller_construct", "label": ".__construct()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L13"}, {"id": "captcha_captchacontroller_captchacontroller_challenge", "label": ".challenge()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15"}, {"id": "jsonresponse", "label": "JsonResponse", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15"}, {"id": "captcha_captchacontroller_captchacontroller_config", "label": ".config()", "file_type": "code", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L32"}], "edges": [{"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "basecontroller", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L5", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "attributes", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L6", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "jsonresponse", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L7", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "route", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L8", "weight": 1.0}, {"source": "users_hamed_pj_my_pj_clinic_pro_clinicpro_src_shared_captcha_captchacontroller_php", "target": "captcha_captchacontroller_captchacontroller", "relation": "contains", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L10", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "basecontroller", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L11", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_construct", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L13", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_challenge", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller_challenge", "target": "jsonresponse", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L15", "weight": 1.0, "context": "return_type"}, {"source": "captcha_captchacontroller_captchacontroller", "target": "captcha_captchacontroller_captchacontroller_config", "relation": "method", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L32", "weight": 1.0}, {"source": "captcha_captchacontroller_captchacontroller_config", "target": "jsonresponse", "relation": "references", "confidence": "EXTRACTED", "source_file": "src/Shared/Captcha/CaptchaController.php", "source_location": "L32", "weight": 1.0, "context": "return_type"}], "raw_calls": [{"caller_nid": "captcha_captchacontroller_captchacontroller_challenge", "callee": "createChallenge", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Captcha/CaptchaController.php", "source_location": "L26", "receiver": null}, {"caller_nid": "captcha_captchacontroller_captchacontroller_config", "callee": "enabled", "is_member_call": true, "source_file": "/Users/hamed/pj/my_pj/clinic_pro/clinicpro/src/Shared/Captcha/CaptchaController.php", "source_location": "L40", "receiver": null}]}
+1 -1
View File
File diff suppressed because one or more lines are too long
+60 -60
View File
@@ -11130,7 +11130,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "migrations_version20260619121047",
"community": 538,
"community": 399,
"norm_label": "version20260619121047.php"
},
{
@@ -11140,7 +11140,7 @@
"source_location": "L13",
"_origin": "ast",
"id": "migrations_version20260619121047_version20260619121047",
"community": 538,
"community": 399,
"norm_label": "version20260619121047"
},
{
@@ -11150,7 +11150,7 @@
"source_location": "L15",
"_origin": "ast",
"id": "migrations_version20260619121047_version20260619121047_getdescription",
"community": 538,
"community": 399,
"norm_label": ".getdescription()"
},
{
@@ -11160,7 +11160,7 @@
"source_location": "L20",
"_origin": "ast",
"id": "migrations_version20260619121047_version20260619121047_up",
"community": 538,
"community": 399,
"norm_label": ".up()"
},
{
@@ -11170,7 +11170,7 @@
"source_location": "L20",
"_origin": "ast",
"id": "migrations_version20260619121047_php_schema",
"community": 538,
"community": 399,
"norm_label": "schema"
},
{
@@ -11180,7 +11180,7 @@
"source_location": "L26",
"_origin": "ast",
"id": "migrations_version20260619121047_version20260619121047_down",
"community": 538,
"community": 399,
"norm_label": ".down()"
},
{
@@ -12570,7 +12570,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "migrations_version20260628165710",
"community": 399,
"community": 538,
"norm_label": "version20260628165710.php"
},
{
@@ -12580,7 +12580,7 @@
"source_location": "L13",
"_origin": "ast",
"id": "migrations_version20260628165710_version20260628165710",
"community": 399,
"community": 538,
"norm_label": "version20260628165710"
},
{
@@ -12590,7 +12590,7 @@
"source_location": "L15",
"_origin": "ast",
"id": "migrations_version20260628165710_version20260628165710_getdescription",
"community": 399,
"community": 538,
"norm_label": ".getdescription()"
},
{
@@ -12600,7 +12600,7 @@
"source_location": "L20",
"_origin": "ast",
"id": "migrations_version20260628165710_version20260628165710_up",
"community": 399,
"community": 538,
"norm_label": ".up()"
},
{
@@ -12610,7 +12610,7 @@
"source_location": "L20",
"_origin": "ast",
"id": "migrations_version20260628165710_php_schema",
"community": 399,
"community": 538,
"norm_label": "schema"
},
{
@@ -12620,7 +12620,7 @@
"source_location": "L26",
"_origin": "ast",
"id": "migrations_version20260628165710_version20260628165710_down",
"community": 399,
"community": 538,
"norm_label": ".down()"
},
{
@@ -19000,7 +19000,7 @@
"source_location": "L109",
"_origin": "ast",
"id": "claimitem",
"community": 161,
"community": 397,
"norm_label": "claimitem"
},
{
@@ -20100,7 +20100,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "service_manualclaimsubmitter",
"community": 631,
"community": 161,
"norm_label": "manualclaimsubmitter.php"
},
{
@@ -20110,7 +20110,7 @@
"source_location": "L14",
"_origin": "ast",
"id": "service_manualclaimsubmitter_manualclaimsubmitter",
"community": 631,
"community": 161,
"norm_label": "manualclaimsubmitter"
},
{
@@ -20120,7 +20120,7 @@
"source_location": "",
"_origin": "ast",
"id": "claimsubmitterinterface",
"community": 631,
"community": 161,
"norm_label": "claimsubmitterinterface"
},
{
@@ -20130,7 +20130,7 @@
"source_location": "L16",
"_origin": "ast",
"id": "service_manualclaimsubmitter_manualclaimsubmitter_submit",
"community": 631,
"community": 161,
"norm_label": ".submit()"
},
{
@@ -20140,7 +20140,7 @@
"source_location": "L16",
"_origin": "ast",
"id": "src_billing_service_manualclaimsubmitter_php_claim",
"community": 631,
"community": 161,
"norm_label": "claim"
},
{
@@ -20150,7 +20150,7 @@
"source_location": "L16",
"_origin": "ast",
"id": "src_billing_service_manualclaimsubmitter_php_claimsubmissionresult",
"community": 631,
"community": 161,
"norm_label": "claimsubmissionresult"
},
{
@@ -35857,7 +35857,7 @@
"label": ".config()",
"file_type": "code",
"source_file": "src/Shared/Captcha/CaptchaController.php",
"source_location": "L26",
"source_location": "L32",
"_origin": "ast",
"id": "captcha_captchacontroller_captchacontroller_config",
"community": 108,
@@ -36160,7 +36160,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "constant_errorcodes",
"community": 318,
"community": 380,
"norm_label": "errorcodes.php"
},
{
@@ -36170,7 +36170,7 @@
"source_location": "L5",
"_origin": "ast",
"id": "constant_errorcodes_errorcodes",
"community": 318,
"community": 380,
"norm_label": "errorcodes"
},
{
@@ -36180,7 +36180,7 @@
"source_location": "L106",
"_origin": "ast",
"id": "constant_errorcodes_errorcodes_message",
"community": 318,
"community": 380,
"norm_label": ".message()"
},
{
@@ -37060,7 +37060,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "logging_logpruneservice",
"community": 703,
"community": 16,
"norm_label": "logpruneservice.php"
},
{
@@ -37070,7 +37070,7 @@
"source_location": "L11",
"_origin": "ast",
"id": "logging_logpruneservice_logpruneservice",
"community": 703,
"community": 16,
"norm_label": "logpruneservice"
},
{
@@ -37080,7 +37080,7 @@
"source_location": "L13",
"_origin": "ast",
"id": "logging_logpruneservice_logpruneservice_construct",
"community": 703,
"community": 16,
"norm_label": ".__construct()"
},
{
@@ -37090,7 +37090,7 @@
"source_location": "L19",
"_origin": "ast",
"id": "logging_logpruneservice_logpruneservice_prunebyretention",
"community": 703,
"community": 16,
"norm_label": ".prunebyretention()"
},
{
@@ -43910,7 +43910,7 @@
"source_location": "L1",
"_origin": "ast",
"id": "billing_claimslistnplusonetest",
"community": 161,
"community": 397,
"norm_label": "claimslistnplusonetest.php"
},
{
@@ -43920,7 +43920,7 @@
"source_location": "L16",
"_origin": "ast",
"id": "billing_claimslistnplusonetest_claimslistnplusonetest",
"community": 161,
"community": 397,
"norm_label": "claimslistnplusonetest"
},
{
@@ -43930,7 +43930,7 @@
"source_location": "L19",
"_origin": "ast",
"id": "billing_claimslistnplusonetest_claimslistnplusonetest_maketenantwithclaims",
"community": 161,
"community": 397,
"norm_label": ".maketenantwithclaims()"
},
{
@@ -43940,7 +43940,7 @@
"source_location": "L41",
"_origin": "ast",
"id": "billing_claimslistnplusonetest_claimslistnplusonetest_testquerycountdoesnotgrowwithclaimcount",
"community": 161,
"community": 397,
"norm_label": ".testquerycountdoesnotgrowwithclaimcount()"
},
{
@@ -79410,7 +79410,7 @@
"source_location": "L144",
"_origin": "ast",
"id": "api_representation_delete_api_v1_representation_uuid",
"community": 229,
"community": 631,
"norm_label": "delete `/api/v1/representation/{uuid}`"
},
{
@@ -79420,7 +79420,7 @@
"source_location": "L150",
"_origin": "ast",
"id": "api_representation_response_200_150",
"community": 229,
"community": 631,
"norm_label": "response `200`"
},
{
@@ -79430,7 +79430,7 @@
"source_location": "L155",
"_origin": "ast",
"id": "api_representation_errors_155",
"community": 229,
"community": 631,
"norm_label": "errors"
},
{
@@ -79490,7 +79490,7 @@
"source_location": "L208",
"_origin": "ast",
"id": "api_representation_get_api_v1_representation_uuid_dashboard_yearly",
"community": 710,
"community": 229,
"norm_label": "get `/api/v1/representation/{uuid}/dashboard/yearly`"
},
{
@@ -79500,7 +79500,7 @@
"source_location": "L214",
"_origin": "ast",
"id": "api_representation_query_parameters_214",
"community": 710,
"community": 229,
"norm_label": "query parameters"
},
{
@@ -79510,7 +79510,7 @@
"source_location": "L219",
"_origin": "ast",
"id": "api_representation_response_200_219",
"community": 710,
"community": 229,
"norm_label": "response `200`"
},
{
@@ -79820,7 +79820,7 @@
"source_location": "L475",
"_origin": "ast",
"id": "api_representation_get_api_v1_representation_doctors",
"community": 694,
"community": 297,
"norm_label": "get `/api/v1/representation/doctors`"
},
{
@@ -79830,7 +79830,7 @@
"source_location": "L481",
"_origin": "ast",
"id": "api_representation_query_parameters_481",
"community": 694,
"community": 297,
"norm_label": "query parameters"
},
{
@@ -79840,7 +79840,7 @@
"source_location": "L488",
"_origin": "ast",
"id": "api_representation_response_200_488",
"community": 694,
"community": 297,
"norm_label": "response `200`"
},
{
@@ -79850,7 +79850,7 @@
"source_location": "L503",
"_origin": "ast",
"id": "api_representation_errors_503",
"community": 694,
"community": 297,
"norm_label": "errors"
},
{
@@ -179903,9 +179903,9 @@
"source_file": "tests/Shared/Captcha/AltchaServiceTest.php",
"source_location": "L97",
"weight": 1.0,
"confidence_score": 1.0,
"source": "captcha_altchaservicetest_altchaservicetest",
"target": "captcha_altchaservicetest_altchaservicetest_testadminoverridebeatsenv",
"confidence_score": 1.0
"target": "captcha_altchaservicetest_altchaservicetest_testadminoverridebeatsenv"
},
{
"relation": "method",
@@ -179985,9 +179985,9 @@
"source_file": "tests/Shared/Captcha/AltchaServiceTest.php",
"source_location": "L100",
"weight": 1.0,
"confidence_score": 1.0,
"source": "captcha_altchaservicetest_altchaservicetest_testadminoverridebeatsenv",
"target": "captcha_altchaservicetest_altchaservicetest_service",
"confidence_score": 1.0
"target": "captcha_altchaservicetest_altchaservicetest_service"
},
{
"relation": "calls",
@@ -206302,9 +206302,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1074",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin",
"target": "api_captcha",
"confidence_score": 1.0
"target": "api_captcha"
},
{
"relation": "references",
@@ -207452,9 +207452,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1185",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin_application_logs",
"target": "api_admin_query_parameters_1185",
"confidence_score": 1.0
"target": "api_admin_query_parameters_1185"
},
{
"relation": "contains",
@@ -207462,9 +207462,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1226",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin_application_logs",
"target": "api_admin_query_parameters_1226",
"confidence_score": 1.0
"target": "api_admin_query_parameters_1226"
},
{
"relation": "contains",
@@ -207472,9 +207472,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1197",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin_application_logs",
"target": "api_admin_response_200_1197",
"confidence_score": 1.0
"target": "api_admin_response_200_1197"
},
{
"relation": "contains",
@@ -207482,9 +207482,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1234",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin_query_parameters_1226",
"target": "api_admin_response_200_1234",
"confidence_score": 1.0
"target": "api_admin_response_200_1234"
},
{
"relation": "contains",
@@ -207492,9 +207492,9 @@
"source_file": "docs/api/admin.md",
"source_location": "L1245",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_admin_delete_api_v1_admin_logs",
"target": "api_admin_response_200_1245",
"confidence_score": 1.0
"target": "api_admin_response_200_1245"
},
{
"relation": "contains",
@@ -209482,9 +209482,9 @@
"source_file": "docs/api/captcha.md",
"source_location": "L38",
"weight": 1.0,
"confidence_score": 1.0,
"source": "api_captcha_get_api_v1_altcha_config",
"target": "api_captcha_response_200_38",
"confidence_score": 1.0
"target": "api_captcha_response_200_38"
},
{
"relation": "contains",
@@ -225628,5 +225628,5 @@
}
],
"hyperedges": [],
"built_at_commit": "c3c520801db3bcd55a339d2e5a1a05b228bac8fa"
"built_at_commit": "ec184dfcc80011e75d8e89aac7b08f2bf72aed59"
}
+6 -6
View File
@@ -3245,8 +3245,8 @@
"semantic_hash": ""
},
"docker-compose.yml": {
"mtime": 1783669690.2173707,
"ast_hash": "8ecc13cd82c69bd23b797d1d7bffaded",
"mtime": 1783671553.657398,
"ast_hash": "3a170be607662978092489b84c3f4b69",
"semantic_hash": ""
},
"docs/DEPLOY.md": {
@@ -3805,8 +3805,8 @@
"semantic_hash": ""
},
"assets/admin/components/ui/Altcha.tsx": {
"mtime": 1783669268.9603772,
"ast_hash": "7d54c6ce3a09652debabd3d8fdca8cfa",
"mtime": 1783671609.167859,
"ast_hash": "7ad01997a2ec14f7effc2c7fe2b7f341",
"semantic_hash": ""
},
"src/Shared/Captcha/AltchaService.php": {
@@ -3815,8 +3815,8 @@
"semantic_hash": ""
},
"src/Shared/Captcha/CaptchaController.php": {
"mtime": 1783669229.4041903,
"ast_hash": "4243706cbee22c8a57d27b48c55eeded",
"mtime": 1783671346.5659652,
"ast_hash": "909f0c12c83d9afdea4b19a15562e8d6",
"semantic_hash": ""
},
"src/Shared/Captcha/CaptchaGuard.php": {
+11 -2
View File
@@ -20,7 +20,13 @@ class CaptchaController extends BaseController
#[Route('/api/v1/altcha/challenge', methods: ['GET'])]
public function challenge(): JsonResponse
{
return new JsonResponse($this->altcha->createChallenge());
// هر challenge باید یکتا و تازه باشد؛ کش‌شدن توسط CDN/پراکسی (مثل ArvanCloud)
// هم چلنج را بین کاربران مشترک می‌کند (شکستن one-time) و هم ممکن است صفحه‌ی
// HTML کش‌شده برگرداند. با no-store کش کاملاً غیرفعال می‌شود.
$response = new JsonResponse($this->altcha->createChallenge());
$response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
return $response;
}
#[OA\Get(
@@ -31,6 +37,9 @@ class CaptchaController extends BaseController
#[Route('/api/v1/altcha/config', methods: ['GET'])]
public function config(): JsonResponse
{
return new JsonResponse(['enabled' => $this->altcha->enabled()]);
$response = new JsonResponse(['enabled' => $this->altcha->enabled()]);
$response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
return $response;
}
}
+1 -1
View File
@@ -559,7 +559,7 @@
{% if altcha_enabled %}
<!-- ALTCHA captcha — proof-of-work در پس‌زمینه (بدون تعامل کاربر) -->
<altcha-widget id="regAltcha" challengeurl="/api/v1/altcha/challenge" auto="onload" style="display:block;margin-top:16px" strings='{"label":"من ربات نیستم","verifying":"در حال بررسی...","verified":"تأیید شد","waitAlert":"در حال بررسی... لطفاً منتظر بمانید.","error":"احراز هویت ناموفق بود. کمی بعد دوباره تلاش کنید.","expired":"احراز هویت منقضی شد. دوباره تلاش کنید."}'></altcha-widget>
<altcha-widget id="regAltcha" challengeurl="/api/v1/altcha/challenge" auto="onload" language="fa" style="display:block;margin-top:16px"></altcha-widget>
{% endif %}
<!-- Error / Success -->