using EntitlementBLL.Onboarding; using EntitlementDAL.DTOs; using EntitlementSL.Common; using FastEndpoints; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ResponseStandard; using GB5Shared.FastEndPoint; using Microsoft.AspNetCore.RateLimiting; using static GB5Shared.GB5Constant.Constant; namespace EntitlementSL.Endpoints.Onboarding; // Genuinely public/anonymous — QuickStart Step 4's real backend, closing the gap // step4.component.ts's own doc comment flags as an "HONEST LEAD-CAPTURE STUB". Deliberately // NOT [MenuRights]-gated like OnboardClient.cs: this is the one Entitlement endpoint meant to be // called by an unauthenticated website visitor, not staff. Anti-abuse is per-IP rate limiting // (ClientAuthRateLimitPolicies.SelfProvisionTrial — tightest ceiling in this options class, // since each successful call creates a real MCLIENT/MUSER row and submits a real // database-provisioning ChangeRequest) plus server-derived ClientCode/AdminUserCode/PlanId (see // SelfProvisionTrialRequestDTO's own doc comment) so a visitor can never spoof another client's // code or claim a paid plan tier for free. public class SelfProvisionTrial : BaseEndpoint> { private readonly IClientOnboardingOrchestratorBLL _Orchestrator; public SelfProvisionTrial(IClientOnboardingOrchestratorBLL orchestrator) => _Orchestrator = orchestrator; public override void Configure() { Post("/Onboarding/SelfProvisionTrial"); AllowAnonymous(); Options(x => x.RequireRateLimiting(ClientAuthRateLimitPolicies.SelfProvisionTrial)); } public record Params( [property: FromHeader] string Login, [property: FromBody] SelfProvisionTrialRequestDTO SelfProvisionTrialRequestDTO ); /// NOT_REQUIRED — a one-time creation action, never cached. protected override string? GetCacheKey(Params req, LoginDTO loginDTO) => null; protected override async Task> ExecuteAsync(Params req, LoginDTO loginDTO, CancellationToken ct) { var result = await _Orchestrator.StartSelfServiceTrialAsync(req.SelfProvisionTrialRequestDTO, ct); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(result, CacheKeyLevel.NOT_REQUIRED, loginDTO); } }