< Summary

Information
Class: Chronicis.Api.Controllers.CampaignSummaryController
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/EntitySummaryControllers.cs
Line coverage
100%
Covered lines: 10
Uncovered lines: 0
Coverable lines: 10
Total lines: 419
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/EntitySummaryControllers.cs

#LineLine coverage
 1using Chronicis.Api.Infrastructure;
 2using Chronicis.Api.Services;
 3using Chronicis.Shared.DTOs;
 4using Microsoft.AspNetCore.Authorization;
 5using Microsoft.AspNetCore.Mvc;
 6
 7namespace Chronicis.Api.Controllers;
 8
 9/// <summary>
 10/// API endpoints for Article Summary operations.
 11/// These are nested under /api/articles/{id}/summary/* as expected by the client.
 12/// </summary>
 13[ApiController]
 14[Route("articles/{articleId:guid}/summary")]
 15[Authorize]
 16public class ArticleSummaryController : ControllerBase
 17{
 18    private readonly ISummaryService _summaryService;
 19    private readonly ISummaryAccessService _summaryAccessService;
 20    private readonly ICurrentUserService _currentUserService;
 21    private readonly ILogger<ArticleSummaryController> _logger;
 22
 23    public ArticleSummaryController(
 24        ISummaryService summaryService,
 25        ISummaryAccessService summaryAccessService,
 26        ICurrentUserService currentUserService,
 27        ILogger<ArticleSummaryController> logger)
 28    {
 29        _summaryService = summaryService;
 30        _summaryAccessService = summaryAccessService;
 31        _currentUserService = currentUserService;
 32        _logger = logger;
 33    }
 34
 35    /// <summary>
 36    /// GET /api/articles/{articleId}/summary - Get the current summary for an article.
 37    /// </summary>
 38    [HttpGet]
 39    public async Task<ActionResult<ArticleSummaryDto>> GetSummary(Guid articleId)
 40    {
 41        var user = await _currentUserService.GetRequiredUserAsync();
 42
 43        // Verify user has access
 44        if (!await HasAccessAsync(articleId, user.Id))
 45        {
 46            return NotFound(new { error = "Article not found or access denied" });
 47        }
 48
 49        _logger.LogTraceSanitized("Getting summary for article {ArticleId}", articleId);
 50
 51        var summary = await _summaryService.GetArticleSummaryAsync(articleId);
 52
 53        if (summary == null)
 54        {
 55            return NoContent();
 56        }
 57
 58        return Ok(summary);
 59    }
 60
 61    /// <summary>
 62    /// GET /api/articles/{articleId}/summary/preview - Get a lightweight summary preview for tooltip display.
 63    /// </summary>
 64    [HttpGet("preview")]
 65    public async Task<ActionResult<SummaryPreviewDto>> GetSummaryPreview(Guid articleId)
 66    {
 67        var user = await _currentUserService.GetRequiredUserAsync();
 68
 69        // Verify user has access
 70        if (!await HasAccessAsync(articleId, user.Id))
 71        {
 72            return NotFound(new { error = "Article not found or access denied" });
 73        }
 74
 75        _logger.LogTraceSanitized("Getting summary preview for article {ArticleId}", articleId);
 76
 77        var preview = await _summaryService.GetArticleSummaryPreviewAsync(articleId);
 78
 79        if (preview == null)
 80        {
 81            return NoContent();
 82        }
 83
 84        return Ok(preview);
 85    }
 86
 87    /// <summary>
 88    /// GET /api/articles/{articleId}/summary/estimate - Estimate the cost of generating a summary.
 89    /// </summary>
 90    [HttpGet("estimate")]
 91    public async Task<ActionResult<SummaryEstimateDto>> GetEstimate(Guid articleId)
 92    {
 93        var user = await _currentUserService.GetRequiredUserAsync();
 94
 95        // Verify user has access
 96        if (!await HasAccessAsync(articleId, user.Id))
 97        {
 98            return NotFound(new { error = "Article not found or access denied" });
 99        }
 100
 101        _logger.LogTraceSanitized("Getting summary estimate for article {ArticleId}", articleId);
 102
 103        var estimate = await _summaryService.EstimateArticleSummaryAsync(articleId);
 104        return Ok(estimate);
 105    }
 106
 107    /// <summary>
 108    /// POST /api/articles/{articleId}/summary/generate - Generate a summary for an article.
 109    /// </summary>
 110    [HttpPost("generate")]
 111    public async Task<ActionResult<SummaryGenerationDto>> GenerateSummary(
 112        Guid articleId,
 113        [FromBody] GenerateSummaryRequestDto? request)
 114    {
 115        var user = await _currentUserService.GetRequiredUserAsync();
 116
 117        // Verify user has access
 118        if (!await HasAccessAsync(articleId, user.Id))
 119        {
 120            return NotFound(new { error = "Article not found or access denied" });
 121        }
 122
 123        _logger.LogTraceSanitized("Generating summary for article {ArticleId}", articleId);
 124
 125        var result = await _summaryService.GenerateArticleSummaryAsync(articleId, request);
 126
 127        if (!result.Success)
 128        {
 129            return BadRequest(new { error = result.ErrorMessage });
 130        }
 131
 132        return Ok(result);
 133    }
 134
 135    /// <summary>
 136    /// DELETE /api/articles/{articleId}/summary - Clear the summary for an article.
 137    /// </summary>
 138    [HttpDelete]
 139    public async Task<IActionResult> ClearSummary(Guid articleId)
 140    {
 141        var user = await _currentUserService.GetRequiredUserAsync();
 142
 143        // Verify user has access
 144        if (!await HasAccessAsync(articleId, user.Id))
 145        {
 146            return NotFound(new { error = "Article not found or access denied" });
 147        }
 148
 149        _logger.LogTraceSanitized("Clearing summary for article {ArticleId}", articleId);
 150
 151        var success = await _summaryService.ClearArticleSummaryAsync(articleId);
 152
 153        if (!success)
 154        {
 155            return NotFound(new { error = "Article not found" });
 156        }
 157
 158        return NoContent();
 159    }
 160
 161    private async Task<bool> HasAccessAsync(Guid articleId, Guid userId)
 162    {
 163        return await _summaryAccessService.CanAccessArticleAsync(articleId, userId);
 164    }
 165}
 166
 167/// <summary>
 168/// API endpoints for Campaign Summary operations.
 169/// </summary>
 170[ApiController]
 171[Route("campaigns/{campaignId:guid}/summary")]
 172[Authorize]
 173public class CampaignSummaryController : ControllerBase
 174{
 175    private readonly ISummaryService _summaryService;
 176    private readonly ISummaryAccessService _summaryAccessService;
 177    private readonly ICurrentUserService _currentUserService;
 178    private readonly ILogger<CampaignSummaryController> _logger;
 179
 1180    public CampaignSummaryController(
 1181        ISummaryService summaryService,
 1182        ISummaryAccessService summaryAccessService,
 1183        ICurrentUserService currentUserService,
 1184        ILogger<CampaignSummaryController> logger)
 185    {
 1186        _summaryService = summaryService;
 1187        _summaryAccessService = summaryAccessService;
 1188        _currentUserService = currentUserService;
 1189        _logger = logger;
 1190    }
 191
 192    /// <summary>
 193    /// GET /api/campaigns/{campaignId}/summary - Get the current summary for a campaign.
 194    /// </summary>
 195    [HttpGet]
 196    public async Task<ActionResult<EntitySummaryDto>> GetSummary(Guid campaignId)
 197    {
 198        var user = await _currentUserService.GetRequiredUserAsync();
 199
 200        if (!await HasAccessAsync(campaignId, user.Id))
 201        {
 202            return NotFound(new { error = "Campaign not found or access denied" });
 203        }
 204
 205        _logger.LogTraceSanitized("Getting summary for campaign {CampaignId}", campaignId);
 206
 207        var summary = await _summaryService.GetCampaignSummaryAsync(campaignId);
 208
 209        if (summary == null)
 210        {
 211            return NoContent();
 212        }
 213
 214        return Ok(summary);
 215    }
 216
 217    /// <summary>
 218    /// GET /api/campaigns/{campaignId}/summary/estimate - Estimate the cost of generating a summary.
 219    /// </summary>
 220    [HttpGet("estimate")]
 221    public async Task<ActionResult<SummaryEstimateDto>> GetEstimate(Guid campaignId)
 222    {
 223        var user = await _currentUserService.GetRequiredUserAsync();
 224
 225        if (!await HasAccessAsync(campaignId, user.Id))
 226        {
 227            return NotFound(new { error = "Campaign not found or access denied" });
 228        }
 229
 230        _logger.LogTraceSanitized("Getting summary estimate for campaign {CampaignId}", campaignId);
 231
 232        var estimate = await _summaryService.EstimateCampaignSummaryAsync(campaignId);
 233        return Ok(estimate);
 234    }
 235
 236    /// <summary>
 237    /// POST /api/campaigns/{campaignId}/summary/generate - Generate a summary for a campaign.
 238    /// </summary>
 239    [HttpPost("generate")]
 240    public async Task<ActionResult<SummaryGenerationDto>> GenerateSummary(
 241        Guid campaignId,
 242        [FromBody] GenerateSummaryRequestDto? request)
 243    {
 244        var user = await _currentUserService.GetRequiredUserAsync();
 245
 246        if (!await HasAccessAsync(campaignId, user.Id))
 247        {
 248            return NotFound(new { error = "Campaign not found or access denied" });
 249        }
 250
 251        _logger.LogTraceSanitized("Generating summary for campaign {CampaignId}", campaignId);
 252
 253        var result = await _summaryService.GenerateCampaignSummaryAsync(campaignId, request);
 254
 255        if (!result.Success)
 256        {
 257            return BadRequest(new { error = result.ErrorMessage });
 258        }
 259
 260        return Ok(result);
 261    }
 262
 263    /// <summary>
 264    /// DELETE /api/campaigns/{campaignId}/summary - Clear the summary for a campaign.
 265    /// </summary>
 266    [HttpDelete]
 267    public async Task<IActionResult> ClearSummary(Guid campaignId)
 268    {
 269        var user = await _currentUserService.GetRequiredUserAsync();
 270
 271        if (!await HasAccessAsync(campaignId, user.Id))
 272        {
 273            return NotFound(new { error = "Campaign not found or access denied" });
 274        }
 275
 276        _logger.LogTraceSanitized("Clearing summary for campaign {CampaignId}", campaignId);
 277
 278        var success = await _summaryService.ClearCampaignSummaryAsync(campaignId);
 279
 280        if (!success)
 281        {
 282            return NotFound(new { error = "Campaign not found" });
 283        }
 284
 285        return NoContent();
 286    }
 287
 288    private async Task<bool> HasAccessAsync(Guid campaignId, Guid userId)
 289    {
 290        return await _summaryAccessService.CanAccessCampaignAsync(campaignId, userId);
 291    }
 292}
 293
 294/// <summary>
 295/// API endpoints for Arc Summary operations.
 296/// </summary>
 297[ApiController]
 298[Route("arcs/{arcId:guid}/summary")]
 299[Authorize]
 300public class ArcSummaryController : ControllerBase
 301{
 302    private readonly ISummaryService _summaryService;
 303    private readonly ISummaryAccessService _summaryAccessService;
 304    private readonly ICurrentUserService _currentUserService;
 305    private readonly ILogger<ArcSummaryController> _logger;
 306
 307    public ArcSummaryController(
 308        ISummaryService summaryService,
 309        ISummaryAccessService summaryAccessService,
 310        ICurrentUserService currentUserService,
 311        ILogger<ArcSummaryController> logger)
 312    {
 313        _summaryService = summaryService;
 314        _summaryAccessService = summaryAccessService;
 315        _currentUserService = currentUserService;
 316        _logger = logger;
 317    }
 318
 319    /// <summary>
 320    /// GET /api/arcs/{arcId}/summary - Get the current summary for an arc.
 321    /// </summary>
 322    [HttpGet]
 323    public async Task<ActionResult<EntitySummaryDto>> GetSummary(Guid arcId)
 324    {
 325        var user = await _currentUserService.GetRequiredUserAsync();
 326
 327        if (!await HasAccessAsync(arcId, user.Id))
 328        {
 329            return NotFound(new { error = "Arc not found or access denied" });
 330        }
 331
 332        _logger.LogTraceSanitized("Getting summary for arc {ArcId}", arcId);
 333
 334        var summary = await _summaryService.GetArcSummaryAsync(arcId);
 335
 336        if (summary == null)
 337        {
 338            return NoContent();
 339        }
 340
 341        return Ok(summary);
 342    }
 343
 344    /// <summary>
 345    /// GET /api/arcs/{arcId}/summary/estimate - Estimate the cost of generating a summary.
 346    /// </summary>
 347    [HttpGet("estimate")]
 348    public async Task<ActionResult<SummaryEstimateDto>> GetEstimate(Guid arcId)
 349    {
 350        var user = await _currentUserService.GetRequiredUserAsync();
 351
 352        if (!await HasAccessAsync(arcId, user.Id))
 353        {
 354            return NotFound(new { error = "Arc not found or access denied" });
 355        }
 356
 357        _logger.LogTraceSanitized("Getting summary estimate for arc {ArcId}", arcId);
 358
 359        var estimate = await _summaryService.EstimateArcSummaryAsync(arcId);
 360        return Ok(estimate);
 361    }
 362
 363    /// <summary>
 364    /// POST /api/arcs/{arcId}/summary/generate - Generate a summary for an arc.
 365    /// </summary>
 366    [HttpPost("generate")]
 367    public async Task<ActionResult<SummaryGenerationDto>> GenerateSummary(
 368        Guid arcId,
 369        [FromBody] GenerateSummaryRequestDto? request)
 370    {
 371        var user = await _currentUserService.GetRequiredUserAsync();
 372
 373        if (!await HasAccessAsync(arcId, user.Id))
 374        {
 375            return NotFound(new { error = "Arc not found or access denied" });
 376        }
 377
 378        _logger.LogTraceSanitized("Generating summary for arc {ArcId}", arcId);
 379
 380        var result = await _summaryService.GenerateArcSummaryAsync(arcId, request);
 381
 382        if (!result.Success)
 383        {
 384            return BadRequest(new { error = result.ErrorMessage });
 385        }
 386
 387        return Ok(result);
 388    }
 389
 390    /// <summary>
 391    /// DELETE /api/arcs/{arcId}/summary - Clear the summary for an arc.
 392    /// </summary>
 393    [HttpDelete]
 394    public async Task<IActionResult> ClearSummary(Guid arcId)
 395    {
 396        var user = await _currentUserService.GetRequiredUserAsync();
 397
 398        if (!await HasAccessAsync(arcId, user.Id))
 399        {
 400            return NotFound(new { error = "Arc not found or access denied" });
 401        }
 402
 403        _logger.LogTraceSanitized("Clearing summary for arc {ArcId}", arcId);
 404
 405        var success = await _summaryService.ClearArcSummaryAsync(arcId);
 406
 407        if (!success)
 408        {
 409            return NotFound(new { error = "Arc not found" });
 410        }
 411
 412        return NoContent();
 413    }
 414
 415    private async Task<bool> HasAccessAsync(Guid arcId, Guid userId)
 416    {
 417        return await _summaryAccessService.CanAccessArcAsync(arcId, userId);
 418    }
 419}