< Summary

Information
Class: Chronicis.Api.Controllers.WorldActiveContextController
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/CampaignsController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 13
Coverable lines: 13
Total lines: 168
Line coverage: 0%
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%210%
GetActiveContext()100%210%

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
 22    public CampaignsController(
 23        ICampaignService campaignService,
 24        ICurrentUserService currentUserService,
 25        ILogger<CampaignsController> logger)
 26    {
 27        _campaignService = campaignService;
 28        _currentUserService = currentUserService;
 29        _logger = logger;
 30    }
 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    {
 38        var user = await _currentUserService.GetRequiredUserAsync();
 39        _logger.LogDebug("Getting campaign {CampaignId} for user {UserId}", id, user.Id);
 40
 41        var campaign = await _campaignService.GetCampaignAsync(id, user.Id);
 42
 43        if (campaign == null)
 44        {
 45            return NotFound(new { error = "Campaign not found or access denied" });
 46        }
 47
 48        return Ok(campaign);
 49    }
 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    {
 57        var user = await _currentUserService.GetRequiredUserAsync();
 58
 59        if (dto == null || string.IsNullOrWhiteSpace(dto.Name))
 60        {
 61            return BadRequest(new { error = "Name is required" });
 62        }
 63
 64        if (dto.WorldId == Guid.Empty)
 65        {
 66            return BadRequest(new { error = "WorldId is required" });
 67        }
 68
 69        _logger.LogDebugSanitized("Creating campaign '{Name}' in world {WorldId} for user {UserId}",
 70            dto.Name, dto.WorldId, user.Id);
 71
 72        try
 73        {
 74            var campaign = await _campaignService.CreateCampaignAsync(dto, user.Id);
 75            return CreatedAtAction(nameof(GetCampaign), new { id = campaign.Id }, campaign);
 76        }
 77        catch (UnauthorizedAccessException ex)
 78        {
 79            return StatusCode(403, new { error = ex.Message });
 80        }
 81        catch (InvalidOperationException ex)
 82        {
 83            return BadRequest(new { error = ex.Message });
 84        }
 85    }
 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    {
 93        var user = await _currentUserService.GetRequiredUserAsync();
 94
 95        if (dto == null || string.IsNullOrWhiteSpace(dto.Name))
 96        {
 97            return BadRequest(new { error = "Name is required" });
 98        }
 99
 100        _logger.LogDebug("Updating campaign {CampaignId} for user {UserId}", id, user.Id);
 101
 102        var campaign = await _campaignService.UpdateCampaignAsync(id, dto, user.Id);
 103
 104        if (campaign == null)
 105        {
 106            return NotFound(new { error = "Campaign not found or access denied" });
 107        }
 108
 109        return Ok(campaign);
 110    }
 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    {
 118        var user = await _currentUserService.GetRequiredUserAsync();
 119
 120        _logger.LogDebug("Activating campaign {CampaignId} for user {UserId}", id, user.Id);
 121
 122        var success = await _campaignService.ActivateCampaignAsync(id, user.Id);
 123
 124        if (!success)
 125        {
 126            return BadRequest(new { error = "Unable to activate campaign. Campaign not found or you don't have permissio
 127        }
 128
 129        return NoContent();
 130    }
 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
 0145    public WorldActiveContextController(
 0146        ICampaignService campaignService,
 0147        ICurrentUserService currentUserService,
 0148        ILogger<WorldActiveContextController> logger)
 149    {
 0150        _campaignService = campaignService;
 0151        _currentUserService = currentUserService;
 0152        _logger = logger;
 0153    }
 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    {
 0161        var user = await _currentUserService.GetRequiredUserAsync();
 162
 0163        _logger.LogDebug("Getting active context for world {WorldId} for user {UserId}", worldId, user.Id);
 164
 0165        var activeContext = await _campaignService.GetActiveContextAsync(worldId, user.Id);
 0166        return Ok(activeContext);
 0167    }
 168}