Skip to content

Commit

Permalink
Appraiser moderation rules changed, review acceptance with comments a…
Browse files Browse the repository at this point in the history
…dded
  • Loading branch information
Space-tourist committed Oct 6, 2024
1 parent 1800624 commit ae0dc25
Show file tree
Hide file tree
Showing 29 changed files with 180 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Inc.TeamAssistant.Appraiser.Model.Commands.AcceptEstimate;
using MediatR;
using Inc.TeamAssistant.Appraiser.Application.Services;
using Inc.TeamAssistant.Primitives;
using Inc.TeamAssistant.Primitives.Commands;
using Inc.TeamAssistant.Primitives.Exceptions;

Expand All @@ -13,16 +14,19 @@ internal sealed class AcceptEstimateCommandHandler : IRequestHandler<AcceptEstim
private readonly IStoryRepository _storyRepository;
private readonly SummaryByStoryBuilder _summaryByStoryBuilder;
private readonly IMessagesSender _messagesSender;
private readonly ITeamAccessor _teamAccessor;

public AcceptEstimateCommandHandler(
IStoryRepository storyRepository,
SummaryByStoryBuilder summaryByStoryBuilder,
IMessagesSender messagesSender)
IMessagesSender messagesSender,
ITeamAccessor teamAccessor)
{
_storyRepository = storyRepository ?? throw new ArgumentNullException(nameof(storyRepository));
_summaryByStoryBuilder =
summaryByStoryBuilder ?? throw new ArgumentNullException(nameof(summaryByStoryBuilder));
_messagesSender = messagesSender ?? throw new ArgumentNullException(nameof(messagesSender));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task<CommandResult> Handle(AcceptEstimateCommand command, CancellationToken token)
Expand All @@ -32,8 +36,10 @@ public async Task<CommandResult> Handle(AcceptEstimateCommand command, Cancellat
var story = await _storyRepository.Find(command.StoryId, token);
if (story is null)
throw new TeamAssistantUserException(Messages.Appraiser_StoryNotFound, command.StoryId);

var hasManagerAccess = await _teamAccessor.HasManagerAccess(story.TeamId, command.MessageContext.Person.Id, token);

var totalEstimation = story.Accept(command.MessageContext.Person.Id, command.Value);
var totalEstimation = story.Accept(command.MessageContext.Person.Id, hasManagerAccess, command.Value);

await _storyRepository.Upsert(story, token);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Inc.TeamAssistant.Appraiser.Application.Converters;
using Inc.TeamAssistant.Appraiser.Application.Services;
using Inc.TeamAssistant.Appraiser.Model.Commands.FinishEstimate;
using Inc.TeamAssistant.Primitives;
using Inc.TeamAssistant.Primitives.Commands;
using Inc.TeamAssistant.Primitives.Exceptions;
using MediatR;
Expand All @@ -13,16 +14,19 @@ internal sealed class FinishEstimateCommandHandler : IRequestHandler<FinishEstim
private readonly IStoryRepository _storyRepository;
private readonly SummaryByStoryBuilder _summaryByStoryBuilder;
private readonly IMessagesSender _messagesSender;
private readonly ITeamAccessor _teamAccessor;

public FinishEstimateCommandHandler(
IStoryRepository storyRepository,
SummaryByStoryBuilder summaryByStoryBuilder,
IMessagesSender messagesSender)
IMessagesSender messagesSender,
ITeamAccessor teamAccessor)
{
_storyRepository = storyRepository ?? throw new ArgumentNullException(nameof(storyRepository));
_summaryByStoryBuilder =
summaryByStoryBuilder ?? throw new ArgumentNullException(nameof(summaryByStoryBuilder));
_messagesSender = messagesSender ?? throw new ArgumentNullException(nameof(messagesSender));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task<CommandResult> Handle(FinishEstimateCommand command, CancellationToken token)
Expand All @@ -32,8 +36,10 @@ public async Task<CommandResult> Handle(FinishEstimateCommand command, Cancellat
var story = await _storyRepository.Find(command.StoryId, token);
if (story is null)
throw new TeamAssistantUserException(Messages.Appraiser_StoryNotFound, command.StoryId);

var hasManagerAccess = await _teamAccessor.HasManagerAccess(story.TeamId, command.MessageContext.Person.Id, token);

story.Finish(command.MessageContext.Person.Id);
story.Finish(command.MessageContext.Person.Id, hasManagerAccess);

await _storyRepository.Upsert(story, token);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Inc.TeamAssistant.Appraiser.Model.Commands.ReVoteEstimate;
using MediatR;
using Inc.TeamAssistant.Appraiser.Application.Services;
using Inc.TeamAssistant.Primitives;
using Inc.TeamAssistant.Primitives.Commands;
using Inc.TeamAssistant.Primitives.Exceptions;

Expand All @@ -13,15 +14,18 @@ internal sealed class ReVoteEstimateCommandHandler : IRequestHandler<ReVoteEstim
private readonly IStoryRepository _storyRepository;
private readonly SummaryByStoryBuilder _summaryByStoryBuilder;
private readonly IMessagesSender _messagesSender;
private readonly ITeamAccessor _teamAccessor;

public ReVoteEstimateCommandHandler(
IStoryRepository storyRepository,
SummaryByStoryBuilder summaryByStoryBuilder,
IMessagesSender messagesSender)
IMessagesSender messagesSender,
ITeamAccessor teamAccessor)
{
_storyRepository = storyRepository ?? throw new ArgumentNullException(nameof(storyRepository));
_summaryByStoryBuilder = summaryByStoryBuilder ?? throw new ArgumentNullException(nameof(summaryByStoryBuilder));
_messagesSender = messagesSender ?? throw new ArgumentNullException(nameof(messagesSender));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task<CommandResult> Handle(ReVoteEstimateCommand command, CancellationToken token)
Expand All @@ -32,8 +36,10 @@ public async Task<CommandResult> Handle(ReVoteEstimateCommand command, Cancellat
var story = await _storyRepository.Find(command.StoryId, token);
if (story is null)
throw new TeamAssistantUserException(Messages.Appraiser_StoryNotFound, command.StoryId);

var hasManagerAccess = await _teamAccessor.HasManagerAccess(story.TeamId, command.MessageContext.Person.Id, token);

story.Reset(command.MessageContext.Person.Id);
story.Reset(command.MessageContext.Person.Id, hasManagerAccess);

await _storyRepository.Upsert(story, token);

Expand Down
12 changes: 6 additions & 6 deletions src/Inc.TeamAssistant.Appraiser.Domain/Story.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,24 @@ public void AddLink(string link)
Links.Add(link);
}

public void Reset(long participantId)
public void Reset(long participantId, bool hasManagerAccess)
{
if (Accepted)
return;

if (ModeratorId != participantId)
if (ModeratorId != participantId && !hasManagerAccess)
throw new TeamAssistantException("User has not rights for action.");

foreach (var storyForEstimate in _storyForEstimates)
storyForEstimate.Reset();
}

public void Finish(long participantId)
public void Finish(long participantId, bool hasManagerAccess)
{
if (Accepted)
return;

if (ModeratorId != participantId)
if (ModeratorId != participantId && !hasManagerAccess)
throw new TeamAssistantException("User has not rights for action.");

foreach (var storyForEstimate in _storyForEstimates)
Expand All @@ -109,9 +109,9 @@ public void Finish(long participantId)
public IEnumerable<Estimation> GetAssessments() => EstimationStrategy.GetValues();
public Estimation ToEstimation(int value) => EstimationStrategy.GetValue(value);

public Estimation Accept(long participantId, int value)
public Estimation Accept(long participantId, bool hasManagerAccess, int value)
{
if (ModeratorId != participantId)
if (ModeratorId != participantId && !hasManagerAccess)
throw new TeamAssistantException("User has not rights for action.");

var totalEstimation = ToEstimation(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ internal sealed class DisableIntegrationCommandHandler : IRequestHandler<Disable
{
private readonly ITeamRepository _teamRepository;
private readonly ICurrentPersonResolver _currentPersonResolver;
private readonly ITeamReader _teamReader;
private readonly ITeamAccessor _teamAccessor;

public DisableIntegrationCommandHandler(
ITeamRepository teamRepository,
ICurrentPersonResolver currentPersonResolver,
ITeamReader teamReader)
ITeamAccessor teamAccessor)
{
_teamRepository = teamRepository ?? throw new ArgumentNullException(nameof(teamRepository));
_currentPersonResolver =
currentPersonResolver ?? throw new ArgumentNullException(nameof(currentPersonResolver));
_teamReader = teamReader ?? throw new ArgumentNullException(nameof(teamReader));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task Handle(DisableIntegrationCommand command, CancellationToken token)
Expand All @@ -33,7 +33,7 @@ public async Task Handle(DisableIntegrationCommand command, CancellationToken to
throw new TeamAssistantUserException(Messages.Connector_TeamNotFound, command.TeamId);

var currentPerson = _currentPersonResolver.GetCurrentPerson();
if (!await _teamReader.HasManagerAccess(team.Id, currentPerson.Id, token))
if (!await _teamAccessor.HasManagerAccess(team.Id, currentPerson.Id, token))
throw new ApplicationException(
$"User {currentPerson.DisplayName} has not rights to remove teammate from team {command.TeamId}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ namespace Inc.TeamAssistant.Connector.Application.CommandHandlers.RemoveTeammate
internal sealed class RemoveTeammateCommandHandler : IRequestHandler<RemoveTeammateCommand>
{
private readonly IPersonRepository _personRepository;
private readonly ITeamReader _teamReader;
private readonly ICurrentPersonResolver _currentPersonProvider;
private readonly ITeamAccessor _teamAccessor;

public RemoveTeammateCommandHandler(
IPersonRepository personRepository,
ITeamReader teamReader,
ICurrentPersonResolver currentPersonProvider)
ICurrentPersonResolver currentPersonProvider,
ITeamAccessor teamAccessor)
{
_personRepository = personRepository ?? throw new ArgumentNullException(nameof(personRepository));
_teamReader = teamReader ?? throw new ArgumentNullException(nameof(teamReader));
_currentPersonProvider = currentPersonProvider ?? throw new ArgumentNullException(nameof(currentPersonProvider));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task Handle(RemoveTeammateCommand command, CancellationToken token)
{
ArgumentNullException.ThrowIfNull(command);

var currentPerson = _currentPersonProvider.GetCurrentPerson();
var hasManagerAccess = await _teamReader.HasManagerAccess(command.TeamId, currentPerson.Id, token);
var hasManagerAccess = await _teamAccessor.HasManagerAccess(command.TeamId, currentPerson.Id, token);

if (!hasManagerAccess)
throw new ApplicationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ internal sealed class SetIntegrationPropertiesCommandHandler : IRequestHandler<S
{
private readonly ITeamRepository _teamRepository;
private readonly ICurrentPersonResolver _currentPersonResolver;
private readonly ITeamReader _teamReader;
private readonly ITeamAccessor _teamAccessor;

public SetIntegrationPropertiesCommandHandler(
ITeamRepository teamRepository,
ICurrentPersonResolver currentPersonResolver,
ITeamReader teamReader)
ITeamAccessor teamAccessor)
{
_teamRepository = teamRepository ?? throw new ArgumentNullException(nameof(teamRepository));
_currentPersonResolver =
currentPersonResolver ?? throw new ArgumentNullException(nameof(currentPersonResolver));
_teamReader = teamReader ?? throw new ArgumentNullException(nameof(teamReader));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task Handle(SetIntegrationPropertiesCommand command, CancellationToken token)
Expand All @@ -33,7 +33,7 @@ public async Task Handle(SetIntegrationPropertiesCommand command, CancellationTo
throw new TeamAssistantUserException(Messages.Connector_TeamNotFound, command.TeamId);

var currentPerson = _currentPersonResolver.GetCurrentPerson();
if (!await _teamReader.HasManagerAccess(team.Id, currentPerson.Id, token))
if (!await _teamAccessor.HasManagerAccess(team.Id, currentPerson.Id, token))
throw new ApplicationException(
$"User {currentPerson.DisplayName} has not rights to remove teammate from team {command.TeamId}");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ namespace Inc.TeamAssistant.Connector.Application.Contracts;

public interface ITeamReader
{
Task<bool> HasManagerAccess(Guid teamId, long personId, CancellationToken token);

Task<IReadOnlyCollection<TeammateDto>> GetTeammates(Guid teamId, CancellationToken token);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public interface ITeamRepository
Task Upsert(Team team, CancellationToken token);

Task Remove(Guid teamId, CancellationToken token);

Task<bool> HasManagerAccess(Guid teamId, long personId, CancellationToken token);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ internal sealed class GetIntegrationPropertiesQueryHandler
{
private readonly ITeamRepository _teamRepository;
private readonly ICurrentPersonResolver _currentPersonResolver;
private readonly ITeamReader _teamReader;
private readonly ITeamAccessor _teamAccessor;

public GetIntegrationPropertiesQueryHandler(
ITeamRepository teamRepository,
ICurrentPersonResolver currentPersonResolver,
ITeamReader teamReader)
ITeamAccessor teamAccessor)
{
_teamRepository = teamRepository ?? throw new ArgumentNullException(nameof(teamRepository));
_currentPersonResolver =
currentPersonResolver ?? throw new ArgumentNullException(nameof(currentPersonResolver));
_teamReader = teamReader ?? throw new ArgumentNullException(nameof(teamReader));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task<GetIntegrationPropertiesResult> Handle(
Expand All @@ -36,7 +36,7 @@ public async Task<GetIntegrationPropertiesResult> Handle(
throw new TeamAssistantUserException(Messages.Connector_TeamNotFound, query.TeamId);

var currentPerson = _currentPersonResolver.GetCurrentPerson();
var hasManagerAccess = await _teamReader.HasManagerAccess(team.Id, currentPerson.Id, token);
var hasManagerAccess = await _teamAccessor.HasManagerAccess(team.Id, currentPerson.Id, token);
var scrumMaster = team.Properties.GetPropertyValueOrDefault(ConnectorProperties.ScrumMaster);
var scrumMasterId = long.TryParse(scrumMaster, out var value)
? value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@ internal sealed class GetTeammatesQueryHandler : IRequestHandler<GetTeammatesQue
{
private readonly ITeamReader _teamReader;
private readonly ICurrentPersonResolver _currentPersonProvider;
private readonly ITeamAccessor _teamAccessor;

public GetTeammatesQueryHandler(ITeamReader teamReader, ICurrentPersonResolver currentPersonProvider)
public GetTeammatesQueryHandler(
ITeamReader teamReader,
ICurrentPersonResolver currentPersonProvider,
ITeamAccessor teamAccessor)
{
_teamReader = teamReader ?? throw new ArgumentNullException(nameof(teamReader));
_currentPersonProvider = currentPersonProvider ?? throw new ArgumentNullException(nameof(currentPersonProvider));
_teamAccessor = teamAccessor ?? throw new ArgumentNullException(nameof(teamAccessor));
}

public async Task<GetTeammatesResult> Handle(GetTeammatesQuery query, CancellationToken token)
{
ArgumentNullException.ThrowIfNull(query);

var currentPerson = _currentPersonProvider.GetCurrentPerson();
var hasManagerAccess = await _teamReader.HasManagerAccess(query.TeamId, currentPerson.Id, token);
var hasManagerAccess = await _teamAccessor.HasManagerAccess(query.TeamId, currentPerson.Id, token);
var teammates = await _teamReader.GetTeammates(query.TeamId, token);

return new GetTeammatesResult(hasManagerAccess, teammates);
Expand Down
5 changes: 5 additions & 0 deletions src/Inc.TeamAssistant.Connector.DataAccess/TeamAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,9 @@ public async Task<LanguageId> GetClientLanguage(Guid botId, long personId, Cance
{
return await _clientLanguageRepository.Get(botId, personId, token);
}

public async Task<bool> HasManagerAccess(Guid teamId, long personId, CancellationToken token)
{
return await _teamRepository.HasManagerAccess(teamId, personId, token);
}
}
25 changes: 0 additions & 25 deletions src/Inc.TeamAssistant.Connector.DataAccess/TeamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,6 @@ public TeamReader(IConnectionFactory connectionFactory)
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
}

public async Task<bool> HasManagerAccess(Guid teamId, long personId, CancellationToken token)
{
var command = new CommandDefinition(
"""
SELECT true
FROM connector.teams AS t
JOIN connector.bots AS b ON t.bot_id = b.id
WHERE t.id = @team_id AND (t.owner_id = @person_id OR b.owner_id = @person_id)
LIMIT 1;
""",
new
{
team_id = teamId,
person_id = personId
},
flags: CommandFlags.None,
cancellationToken: token);

await using var connection = _connectionFactory.Create();

var hasManagerAccess = await connection.QuerySingleOrDefaultAsync<bool>(command);

return hasManagerAccess;
}

public async Task<IReadOnlyCollection<TeammateDto>> GetTeammates(Guid teamId, CancellationToken token)
{
var command = new CommandDefinition(@"
Expand Down
Loading

0 comments on commit ae0dc25

Please sign in to comment.