Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions backend/src/Taskdeck.Application/Services/BoardService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,12 @@ public async Task<Result<BoardDetailDto>> GetBoardDetailAsync(Guid id, Guid acti

var detail = await GetBoardDetailAsync(id, cancellationToken);
if (!detail.IsSuccess) return detail;
var writable = _authorizationService is null ? null : await _authorizationService.CanWriteBoardAsync(actingUserId, id);
return Result.Success(detail.Value with { CanWrite = writable is { IsSuccess: true, Value: true } });
var writable = _authorizationService is null
|| (await _authorizationService.CanWriteBoardAsync(actingUserId, id)) is { IsSuccess: true, Value: true };
// No authorization service configured (CLI / unauthenticated composition) means no
// authorization is being enforced at all, so the caller can write — the same
// convention ListBoardsPaginatedAsync and EnsureBoardPermissionAsync follow.
return Result.Success(detail.Value with { CanWrite = writable });
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,44 @@ public async Task CreateBoardAsync_ShouldStampCanWriteTrue_ForTheCreatingOwner()
result.IsSuccess.Should().BeTrue();
result.Value.CanWrite.Should().BeTrue();
}
[Fact]
public async Task GetBoardDetailAsync_ShouldStampCanWriteTrue_WhenNoAuthorizationService()
{
// Null authorization (CLI / unauthenticated composition) means no enforcement,
// so detail must agree with the list stamp: the caller can write.
var board = TestDataBuilder.CreateBoard("Detail Board");
_boardRepoMock.Setup(r => r.GetByIdWithDetailsAsync(board.Id, default))
.ReturnsAsync(board);

var result = await _service.GetBoardDetailAsync(board.Id, Guid.NewGuid());

result.IsSuccess.Should().BeTrue();
result.Value.CanWrite.Should().BeTrue();
}

[Fact]
public async Task ListBoardsPaginatedAsync_ShouldStampCanWriteTrue_WhenNoAuthorizationService()
{
// Parity lock for the detail stamp above: with no authorization service every
// visible board is writable.
var actingUserId = Guid.NewGuid();
var boards = new[]
{
new Board("Board A", "desc", actingUserId),
new Board("Board B", "desc", actingUserId)
};
var boardIds = boards.Select(b => b.Id).ToList();
_boardRepoMock.Setup(r => r.SearchIdsAsync(null, false, default))
.ReturnsAsync(boardIds);
_boardRepoMock.Setup(r => r.GetByIdsAsync(It.IsAny<IEnumerable<Guid>>(), default))
.ReturnsAsync(boards);

var result = await _service.ListBoardsPaginatedAsync(actingUserId);

result.IsSuccess.Should().BeTrue();
result.Value.Items.Should().HaveCount(2);
result.Value.Items.Should().OnlyContain(b => b.CanWrite);
}

#endregion
}
Loading