Quote REST surface — staff management and public share links

FeatureSecurityService
Shipped
2026年8月3日 3:21 UTC
Author
Kamo
Commit
d1f1544

Staff endpoints at /api/security/commerce/quotes and an unauthenticated resolver at /api/security/public/quotes. QuoteController extends BaseLosController rather than copying POSController's preamble: CallerSessionResolver accepts the X-OTK attribute, the X-***-Token header AND the *** cookie, where POSController's private getOrgId reads only the OTK attribute. Every handler is rights-gated (VIEW/MANAGE/SEND_QUOTES). Most of the commerce surface is session-only — any authenticated member of any org can mutate orders — and that is deliberately not repeated here, because a quote commits the org to a price in front of a customer. QuotePublicController needs no security-config carve-out: the Spring chain is anyRequest().permitAll() and OTKPreAuthFilter only acts on an X-OTK header, which a browser following an emailed link never sends. Design points: - The token arrives in the POST body, never a URL. APIApp.forward() logs request lines, and a bearer credential in a path would land in those logs. - Not an enumeration oracle: unknown, revoked and org-mismatched tokens all return one indistinguishable generic failure. Only EXPIRED gets a specific, honest answer, which is safe because the caller already proved possession of a 256-bit token. - The org derived from the request host is cross-checked against the org on the link row. Without it, a valid link for org A opened under org B's host would render A's pricing wearing B's branding — a phishing primitive. - no-store / Referrer-Policy: no-referrer / X-Robots-Tag: noindex on every response. The page loads logos from theme.<org>, and a Referer would carry the token off-origin. PublicLinkRateLimiter is Redis-backed because SecurityService is multi-replica — in-process counters would be a limiter in name only. It is explicitly DoS and log-hygiene protection, NOT the anti-guessing control: 256 bits of entropy is. Failures are counted far more harshly than successes, since one office opening a forwarded quote fifty times is normal while fifty misses is not. It fails open, so a Redis outage cannot take the quote page down. QuoteEmailClient reuses the EmailService transactional path (X-Internal-Auth, QUOTE_SENT template) and sends only the headline figure plus the link — never the itemised pricing, so a forwarded email is not itself the disclosure. Pre-existing test failures unchanged by this commit (verified by stashing this work and re-running on clean HEAD): **************** NPE on a null EntityManager, and the legacy com.retval SecurityServiceApplicationTests missing a @SpringBootConfiguration. REQUIRES a KamoInitializerService run before these endpoints work: the quote tables are new and ddl-auto is none here, so the service boots normally and only the quote endpoints 500 on a missing relation until KI has run.

All changes

配送を見るのが好きですか?

これらのアップデートは、自動的にワークスペースに埋め込まれます。 週1回無料スタートし、週1回生育する.

永遠に無料で始める料金を見る