Skip to content

Commit

Permalink
Resolves #543
Browse files Browse the repository at this point in the history
  • Loading branch information
sei-bstein committed Nov 21, 2024
1 parent 85c483d commit 1379d9b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 31 deletions.
6 changes: 3 additions & 3 deletions src/Gameboard.Api/Features/Ticket/TicketController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2021 Carnegie Mellon University. All Rights Reserved.
// Released under a MIT (SEI)-style license. See LICENSE.md in the project root for license information.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
Expand Down Expand Up @@ -41,18 +40,19 @@ IMapper mapper
/// Gets ticket details
/// </summary>
/// <param name="id"></param>
/// <param name="sortDirection">The direction in which activity on this ticket will be ordered (by timestamp)</param>
/// <returns></returns>
[HttpGet("api/ticket/{id}")]
[Authorize]
public async Task<Ticket> Retrieve([FromRoute] int id)
public async Task<Ticket> Retrieve([FromRoute] int id, [FromQuery] SortDirection sortDirection)
{
await AuthorizeAny
(
() => _permissionsService.Can(PermissionKey.Support_ViewTickets),
() => TicketService.IsOwnerOrTeamMember(id, Actor.Id)
);

return await TicketService.Retrieve(id);
return await TicketService.Retrieve(id, sortDirection);
}


Expand Down
59 changes: 31 additions & 28 deletions src/Gameboard.Api/Features/Ticket/TicketService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ ITeamService teamService
public string GetFullKey(int key)
=> $"{(Options.KeyPrefix.IsEmpty() ? "GB" : Options.KeyPrefix)}-{key}";

public Task<Ticket> Retrieve(string id)
=> LoadTicketDto(id);
public Task<Ticket> Retrieve(string id, SortDirection activitySortDirection = SortDirection.Asc)
=> LoadTicketDto(id, activitySortDirection);

public Task<Ticket> Retrieve(int id)
=> LoadTicketDto(id);
public Task<Ticket> Retrieve(int id, SortDirection activitySortDirection = SortDirection.Asc)
=> LoadTicketDto(id, activitySortDirection);

public IQueryable<Data.Ticket> BuildTicketSearchQuery(string term)
{
Expand Down Expand Up @@ -384,14 +384,6 @@ public async Task<string[]> ListLabels(SearchFilter model)
return b;
}

public async Task<bool> UserIsEnrolled(string gameId, string userId)
{
return await _store.AnyAsync<Data.User>(u =>
u.Id == userId &&
u.Enrollments.Any(e => e.GameId == gameId)
, CancellationToken.None);
}

public async Task<bool> IsOwnerOrTeamMember(int ticketId, string userId)
{
var ticket = await _store
Expand Down Expand Up @@ -444,15 +436,6 @@ public async Task<bool> IsOwnerOrTeamMember(string ticketId, string userId)
, CancellationToken.None);
}

public async Task<bool> IsOwner(string ticketId, string userId)
{
return await _store
.WithNoTracking<Data.Ticket>()
.Where(t => t.Id == ticketId)
.Where(t => t.RequesterId == userId)
.AnyAsync();
}

public async Task<bool> UserCanUpdate(string ticketId, string userId)
{
var ticket = await BuildTicketSearchQuery(ticketId).SingleOrDefaultAsync();
Expand Down Expand Up @@ -551,25 +534,36 @@ private void AddActivity(Data.Ticket entity, string actorId, bool statusChanged,
}
}

private async Task<Ticket> LoadTicketDto(int ticketKey)
=> await BuildTicketDto(await BuildTicketQueryBase().SingleOrDefaultAsync(t => t.Key == ticketKey));
private async Task<Ticket> LoadTicketDto(int ticketKey, SortDirection activitySortDirection = SortDirection.Asc)
=> await BuildTicketDto(await BuildTicketQueryBase().SingleOrDefaultAsync(t => t.Key == ticketKey), activitySortDirection);

private async Task<Ticket> LoadTicketDto(string ticketId)
=> await BuildTicketDto(await BuildTicketQueryBase().SingleOrDefaultAsync(t => t.Id == ticketId));
private async Task<Ticket> LoadTicketDto(string ticketId, SortDirection activitySortDirection = SortDirection.Asc)
=> await BuildTicketDto(await BuildTicketQueryBase().SingleOrDefaultAsync(t => t.Id == ticketId), activitySortDirection);

private async Task<Ticket> BuildTicketDto(Data.Ticket ticketEntity)
private async Task<Ticket> BuildTicketDto(Data.Ticket ticketEntity, SortDirection activitySortDirection)
{
var ticket = Mapper.Map<Ticket>(ticketEntity);
ticket.FullKey = GetFullKey(ticket.Key);

ticket.Assignee = await BuildTicketUser(ticketEntity.Assignee);
ticket.Creator = await BuildTicketUser(ticketEntity.Creator);
ticket.Requester = await BuildTicketUser(ticketEntity.Requester);
ticket.TeamName = "(deleted team)";

if (ticket.TeamId.IsNotEmpty())
{
var team = await _teamService.GetTeam(ticket.TeamId);
ticket.TeamName = team.ApprovedName;
// have to do this delicately in case the team is deleted (reset)
// https://github.com/cmu-sei/Gameboard/issues/553 can't come soon enough
var captain = await _store
.WithNoTracking<Data.Player>()
.Where(p => p.TeamId == ticket.TeamId)
.OrderBy(p => p.Role == PlayerRole.Manager ? 0 : 1)
.FirstOrDefaultAsync();

if (captain is not null)
{
ticket.TeamName = captain.ApprovedName;
}
}

if (ticket.Player is not null)
Expand All @@ -582,6 +576,15 @@ private async Task<Ticket> BuildTicketDto(Data.Ticket ticketEntity)
ticket.IsTeamGame = ticket.Challenge.AllowTeam;
}

if (activitySortDirection == SortDirection.Asc)
{
ticket.Activity = [.. ticket.Activity.OrderBy(a => a.Timestamp)];
}
else
{
ticket.Activity = [.. ticket.Activity.OrderByDescending(a => a.Timestamp)];
}

return ticket;
}

Expand Down

0 comments on commit 1379d9b

Please sign in to comment.