< Summary

Information
Class: Chronicis.Api.Controllers.CampaignsController
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/CampaignsController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 45
Coverable lines: 45
Total lines: 168
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 16
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetCampaign()0%620%
CreateCampaign()0%4260%
UpdateCampaign()0%4260%
ActivateCampaign()0%620%

File(s)

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

#LineLine coverage
 1using Chronicis.Api.Infrastructure;
 2using Chronicis.Api.Services;
 3using Chronicis.Shared.DTOs;
 4using Chronicis.Shared.Extensions;
 5using Microsoft.AspNetCore.Authorization;
 6using Microsoft.AspNetCore.Mvc;
 7
 8namespace Chronicis.Api.Controllers;
 9
 10/// <summary>
 11/// API endpoints for Campaign management.
 12/// </summary>
 13[ApiController]
 14[Route("campaigns")]
 15[Authorize]
 16public class CampaignsController : ControllerBase
 17{
 18    private readonly ICampaignService _campaignService;
 19    private readonly ICurrentUserService _currentUserService;
 20    private readonly ILogger<CampaignsController> _logger;
 21
 022    public CampaignsController(
 023        ICampaignService campaignService,
 024        ICurrentUserService currentUserService,
 025        ILogger<CampaignsController> logger)
 26    {
 027        _campaignService = campaignService;
 028        _currentUserService = currentUserService;
 029        _logger = logger;
 030    }
 31
 32    /// <summary>
 33    /// GET /api/campaigns/{id} - Get a specific campaign.
 34    /// </summary>
 35    [HttpGet("{id:guid}")]
 36    public async Task<ActionResult<CampaignDto>> GetCampaign(Guid id)
 37    {
 038        var user = await _currentUserService.GetRequiredUserAsync();
 039        _logger.LogDebug("Getting campaign {CampaignId} for user {UserId}", id, user.Id);
 40
 041        var campaign = await _campaignService.GetCampaignAsync(id, user.Id);
 42
 043        if (campaign == null)
 44        {
 045            return NotFound(new { error = "Campaign not found or access denied" });
 46        }
 47
 048        return Ok(campaign);
 049    }
 50
 51    /// <summary>
 52    /// POST /api/campaigns - Create a new campaign.
 53    /// </summary>
 54    [HttpPost]
 55    public async Task<ActionResult<CampaignDto>> CreateCampaign([FromBody] CampaignCreateDto dto)
 56    {
 057        var user = await _currentUserService.GetRequiredUserAsync();
 58
 059        if (dto == null || string.IsNullOrWhiteSpace(dto.Name))
 60        {
 061            return BadRequest(new { error = "Name is required" });
 62        }
 63
 064        if (dto.WorldId == Guid.Empty)
 65        {
 066            return BadRequest(new { error = "WorldId is required" });
 67        }
 68
 069        _logger.LogDebugSanitized("Creating campaign '{Name}' in world {WorldId} for user {UserId}",
 070            dto.Name, dto.WorldId, user.Id);
 71
 72        try
 73        {
 074            var campaign = await _campaignService.CreateCampaignAsync(dto, user.Id);
 075            return CreatedAtAction(nameof(GetCampaign), new { id = campaign.Id }, campaign);
 76        }
 077        catch (UnauthorizedAccessException ex)
 78        {
 079            return StatusCode(403, new { error = ex.Message });
 80        }
 081        catch (InvalidOperationException ex)
 82        {
 083            return BadRequest(new { error = ex.Message });
 84        }
 085    }
 86
 87    /// <summary>
 88    /// PUT /api/campaigns/{id} - Update a campaign.
 89    /// </summary>
 90    [HttpPut("{id:guid}")]
 91    public async Task<ActionResult<CampaignDto>> UpdateCampaign(Guid id, [FromBody] CampaignUpdateDto dto)
 92    {
 093        var user = await _currentUserService.GetRequiredUserAsync();
 94
 095        if (dto == null || string.IsNullOrWhiteSpace(dto.Name))
 96        {
 097            return BadRequest(new { error = "Name is required" });
 98        }
 99
 0100        _logger.LogDebug("Updating campaign {CampaignId} for user {UserId}", id, user.Id);
 101
 0102        var campaign = await _campaignService.UpdateCampaignAsync(id, dto, user.Id);
 103
 0104        if (campaign == null)
 105        {
 0106            return NotFound(new { error = "Campaign not found or access denied" });
 107        }
 108
 0109        return Ok(campaign);
 0110    }
 111
 112    /// <summary>
 113    /// POST /api/campaigns/{id}/activate - Activate a campaign.
 114    /// </summary>
 115    [HttpPost("{id:guid}/activate")]
 116    public async Task<IActionResult> ActivateCampaign(Guid id)
 117    {
 0118        var user = await _currentUserService.GetRequiredUserAsync();
 119
 0120        _logger.LogDebug("Activating campaign {CampaignId} for user {UserId}", id, user.Id);
 121
 0122        var success = await _campaignService.ActivateCampaignAsync(id, user.Id);
 123
 0124        if (!success)
 125        {
 0126            return BadRequest(new { error = "Unable to activate campaign. Campaign not found or you don't have permissio
 127        }
 128
 0129        return NoContent();
 0130    }
 131}
 132
 133/// <summary>
 134/// Active context endpoints - nested under worlds but related to campaigns.
 135/// </summary>
 136[ApiController]
 137[Route("worlds/{worldId:guid}")]
 138[Authorize]
 139public class WorldActiveContextController : ControllerBase
 140{
 141    private readonly ICampaignService _campaignService;
 142    private readonly ICurrentUserService _currentUserService;
 143    private readonly ILogger<WorldActiveContextController> _logger;
 144
 145    public WorldActiveContextController(
 146        ICampaignService campaignService,
 147        ICurrentUserService currentUserService,
 148        ILogger<WorldActiveContextController> logger)
 149    {
 150        _campaignService = campaignService;
 151        _currentUserService = currentUserService;
 152        _logger = logger;
 153    }
 154
 155    /// <summary>
 156    /// GET /api/worlds/{worldId}/active-context - Get the active context for a world.
 157    /// </summary>
 158    [HttpGet("active-context")]
 159    public async Task<ActionResult<ActiveContextDto>> GetActiveContext(Guid worldId)
 160    {
 161        var user = await _currentUserService.GetRequiredUserAsync();
 162
 163        _logger.LogDebug("Getting active context for world {WorldId} for user {UserId}", worldId, user.Id);
 164
 165        var activeContext = await _campaignService.GetActiveContextAsync(worldId, user.Id);
 166        return Ok(activeContext);
 167    }
 168}