Wave 1 — 6 parallel agents fixing P0 issues from code audit: Auth (18 services secured): - Added JWT Bearer auth + [Authorize] to all unprotected controllers - Webhook endpoints (Facebook/WhatsApp/Zalo/X) stay [AllowAnonymous] - Health checks remain public for Docker/K8s probes - Services: catalog, order, booking, fnb-engine, inventory, social, ads-manager, ads-serving, ads-billing, ads-tracking, ads-analytics, mkt-facebook, mkt-whatsapp, mkt-x, mkt-zalo, promotion Template artifacts (4 services): - mission-service: myservice_db → mission_service - mkt-facebook: Dockerfile MyService.API → FacebookService.API - mkt-whatsapp: MyServiceContext.cs → WhatsAppServiceContext.cs - promotion: UserSecretsId fixed Critical handler bugs (7 fixes): - ads-tracking: TrackPixelEventHandler now persists to DB - ads-tracking: RecordConversion endpoint exposed via controller - booking: UpdateResource now applies Name + Capacity changes - ads-manager: ListPendingAds uses correct enum (pending_review) - mining: BanMiner calls Ban() not Suspend() - mining: ResetMinerStreak now actually resets streak - mkt-x: 8 missing repository DI registrations added Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
61 lines
1.9 KiB
C#
61 lines
1.9 KiB
C#
using AdsManagerService.API.Application.Commands;
|
|
using AdsManagerService.API.Application.Queries;
|
|
using MediatR;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace AdsManagerService.API.Controllers;
|
|
|
|
/// <summary>
|
|
/// EN: API Controller for managing ad sets.
|
|
/// VI: API Controller quản lý ad sets.
|
|
/// </summary>
|
|
[ApiController]
|
|
[Authorize]
|
|
[Route("api/v1/ads-manager/adsets")]
|
|
[Produces("application/json")]
|
|
public class AdSetsController : ControllerBase
|
|
{
|
|
private readonly IMediator _mediator;
|
|
private readonly ILogger<AdSetsController> _logger;
|
|
|
|
public AdSetsController(IMediator mediator, ILogger<AdSetsController> logger)
|
|
{
|
|
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Create a new ad set.
|
|
/// VI: Tạo ad set mới.
|
|
/// </summary>
|
|
[HttpPost]
|
|
[ProducesResponseType(StatusCodes.Status201Created)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
public async Task<ActionResult<Guid>> CreateAdSet([FromBody] CreateAdSetCommand command)
|
|
{
|
|
_logger.LogInformation("Creating ad set for campaign {CampaignId}", command.CampaignId);
|
|
|
|
var adSetId = await _mediator.Send(command);
|
|
|
|
return CreatedAtAction(nameof(GetAdSetById), new { id = adSetId }, adSetId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// EN: Get ad set by ID (placeholder).
|
|
/// VI: Lấy ad set theo ID (placeholder).
|
|
/// </summary>
|
|
[HttpGet("{id}")]
|
|
[ProducesResponseType(typeof(AdSetDto), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<ActionResult<AdSetDto>> GetAdSetById(Guid id)
|
|
{
|
|
var adSet = await _mediator.Send(new GetAdSetByIdQuery { AdSetId = id });
|
|
|
|
if (adSet == null)
|
|
return NotFound();
|
|
|
|
return Ok(adSet);
|
|
}
|
|
}
|