public async Task <ActionResult <TimestampDto> > PostLock(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.FindAsync(characterId, phase); if (list is null) { return(NotFound()); } var character = await _context.Characters.FindAsync(characterId); if (character is null) { return(NotFound()); } var auth = await _authorizationService.AuthorizeAsync(User, character.TeamId, AppPolicies.RaidLeaderOrAdmin); if (!auth.Succeeded) { return(Unauthorized()); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("Loot list has been changed. Refresh before trying to update the status again.")); } if (list.Status != LootListStatus.Approved) { return(Problem("Loot list must be approved before locking.")); } list.Status = LootListStatus.Locked; await _context.SaveChangesAsync(); _telemetry.TrackEvent("LootListStatusChanged", User, props => { props["CharacterId"] = list.CharacterId.ToString(); props["Phase"] = list.Phase.ToString(); props["Status"] = list.Status.ToString(); props["Method"] = "Lock"; }); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > PostUnlock(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.FindAsync(characterId, phase); if (list is null) { return(NotFound()); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("Loot list has been changed. Refresh before trying to update the status again.")); } if (list.Status != LootListStatus.Locked) { return(Problem("Loot list is already unlocked.")); } list.Status = LootListStatus.Approved; await _context.SaveChangesAsync(); var cname = await _context.Characters .AsNoTracking() .Where(c => c.Id == characterId) .Select(c => c.Name) .FirstAsync(); _telemetry.TrackEvent("LootListStatusChanged", User, props => { props["CharacterId"] = list.CharacterId.ToString(); props["CharacterName"] = cname; props["Phase"] = list.Phase.ToString(); props["Status"] = list.Status.ToString(); props["Method"] = "Unlock"; }); //await dcp.SendAsync(635355896020729866, m => //{ // var userId = (ulong)User.GetDiscordId().GetValueOrDefault(); // var request = Url.ActionContext.HttpContext.Request; // var link = request.Scheme + "://" + request.Host + Url.Content($"~/characters/{cname}/phase/{list.Phase}"); // m.WithContent($"<@!{userId}> has just unlocked [{cname}'s Phase {list.Phase} Loot List]({link}).") // .WithAllowedMention(new UserMention(userId)); //}); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > PostSetEditable(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.FindAsync(characterId, phase); if (list is null) { return(NotFound()); } AuthorizationResult auth; if (list.Status == LootListStatus.Submitted || list.Status == LootListStatus.Approved) { auth = await _authorizationService.AuthorizeAsync(User, list.CharacterId, AppPolicies.CharacterOwnerOrAdmin); } else { auth = await _authorizationService.AuthorizeAsync(User, AppPolicies.Administrator); } if (!auth.Succeeded) { if (list.Status == LootListStatus.Approved) { var character = await _context.Characters.FindAsync(characterId); if (character?.TeamId > 0) { auth = await _authorizationService.AuthorizeAsync(User, character.TeamId.Value, AppPolicies.RaidLeader); } } if (!auth.Succeeded) { return(Unauthorized()); } } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("Loot list has been changed. Refresh before trying to update the status again.")); } if (list.Status == LootListStatus.Editing) { return(Problem("Loot list is already editable.")); } var submissions = await _context.LootListTeamSubmissions .AsTracking() .Where(s => s.LootListCharacterId == list.CharacterId && s.LootListPhase == list.Phase) .ToListAsync(); _context.LootListTeamSubmissions.RemoveRange(submissions); list.ApprovedBy = null; list.Status = LootListStatus.Editing; await _context.SaveChangesAsync(); _telemetry.TrackEvent("LootListStatusChanged", User, props => { props["CharacterId"] = list.CharacterId.ToString(); props["Phase"] = list.Phase.ToString(); props["Status"] = list.Status.ToString(); props["Method"] = "SetEditable"; }); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > Unlock(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.AsTracking() .Where(ll => ll.CharacterId == characterId && ll.Phase == phase) .Include(ll => ll.Character) .SingleOrDefaultAsync(); if (list is null) { return(NotFound()); } if (list.Character.Deactivated) { return(Problem("Character has been deactivated.")); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("The loot list has been changed. Refresh before trying again.")); } if (list.Status != LootListStatus.Locked) { return(Problem("Loot list is already unlocked.")); } list.Status = LootListStatus.Approved; await _context.SaveChangesAsync(); TrackListStatusChange(list); //await dcp.SendAsync(635355896020729866, m => //{ // var userId = (ulong)User.GetDiscordId().GetValueOrDefault(); // var request = Url.ActionContext.HttpContext.Request; // var link = request.Scheme + "://" + request.Host + Url.Content($"~/characters/{cname}/phase/{list.Phase}"); // m.WithContent($"<@!{userId}> has just unlocked [{cname}'s Phase {list.Phase} Loot List]({link}).") // .WithAllowedMention(new UserMention(userId)); //}); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > Lock(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.AsTracking() .Where(ll => ll.CharacterId == characterId && ll.Phase == phase) .Include(ll => ll.Character) .ThenInclude(c => c.Team) .SingleOrDefaultAsync(); if (list is null) { return(NotFound()); } if (list.Character.Team is null) { return(Problem("This action is only available for characters on a raid team.")); } if (!await AuthorizeTeamAsync(list.Character.Team, AppPolicies.RaidLeaderOrAdmin)) { return(Unauthorized()); } if (list.Character.Deactivated) { return(Problem("Character has been deactivated.")); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("The loot list has been changed. Refresh before trying again.")); } if (list.Status != LootListStatus.Approved) { return(Problem("Loot list must be approved before locking.")); } if (!await _context.PhaseActiveAsync(list.Phase)) { return(Problem("Phase is not yet active.")); } list.Status = LootListStatus.Locked; await _context.SaveChangesAsync(); TrackListStatusChange(list); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > Revoke(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.AsTracking() .Where(ll => ll.CharacterId == characterId && ll.Phase == phase) .Include(ll => ll.Character) .ThenInclude(c => c.Team) .SingleOrDefaultAsync(); if (list is null) { return(NotFound()); } if (!await AuthorizeCharacterAsync(list.Character, AppPolicies.CharacterOwnerOrAdmin)) { if (list.Character.Team is null || !await AuthorizeTeamAsync(list.Character.Team, AppPolicies.RaidLeaderOrAdmin)) { return(Unauthorized()); } } if (list.Character.Deactivated) { return(Problem("Character has been deactivated.")); } if (list.Character.Team is null) { return(Problem("This action is only available for characters on a raid team.")); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("The loot list has been changed. Refresh before trying again.")); } list.ApprovedBy = null; switch (list.Status) { case LootListStatus.Editing: return(Problem("The loot list has not been submitted yet.")); case LootListStatus.Submitted: case LootListStatus.Approved: list.Status = LootListStatus.Editing; break; case LootListStatus.Locked: return(Problem("The loot list is locked.")); } var submissions = await _context.LootListTeamSubmissions .AsTracking() .Where(s => s.LootListCharacterId == characterId && s.LootListPhase == phase) .ToListAsync(); _context.LootListTeamSubmissions.RemoveRange(submissions); await _context.SaveChangesAsync(); TrackListStatusChange(list); return(new TimestampDto { Timestamp = list.Timestamp }); }
public async Task <ActionResult <TimestampDto> > Submit(long characterId, byte phase, [FromBody] TimestampDto dto) { var list = await _context.CharacterLootLists.AsTracking() .Where(ll => ll.CharacterId == characterId && ll.Phase == phase) .Include(ll => ll.Character) .ThenInclude(c => c.Team) .SingleOrDefaultAsync(); if (list is null) { return(NotFound()); } if (!await AuthorizeCharacterAsync(list.Character, AppPolicies.CharacterOwnerOrAdmin)) { return(Unauthorized()); } if (list.Character.Deactivated) { return(Problem("Character has been deactivated.")); } if (list.Character.Team is null) { return(Problem("This action is only available for characters on a raid team.")); } if (!ValidateTimestamp(list, dto.Timestamp)) { return(Problem("The loot list has been changed. Refresh before trying again.")); } long teamId = list.Character.Team.Id; list.ApprovedBy = null; switch (list.Status) { case LootListStatus.Editing: list.Status = LootListStatus.Submitted; break; case LootListStatus.Submitted: return(Problem("The loot list has already been submitted.")); case LootListStatus.Approved: return(Problem("The loot list has already been approved.")); case LootListStatus.Locked: break; } var submissions = await _context.LootListTeamSubmissions .AsTracking() .Where(s => s.LootListCharacterId == characterId && s.LootListPhase == phase) .ToListAsync(); if (submissions.Find(s => s.TeamId == teamId) is null) { _context.LootListTeamSubmissions.Add(new() { LootListCharacterId = characterId, LootListPhase = phase, TeamId = teamId }); _context.LootListTeamSubmissions.RemoveRange(submissions); } else if (submissions.Count > 1) { _context.LootListTeamSubmissions.RemoveRange(submissions.Where(s => s.TeamId != teamId)); } await _context.SaveChangesAsync(); TrackListStatusChange(list); var dm = $"{list.Character.Name} ({list.Character.Race.GetDisplayName()} {list.MainSpec.GetDisplayName(includeClassName: true)}) has submitted a new phase {phase} loot list for team {list.Character.Team.Name}."; await foreach (var leaderId in _context.RaidTeamLeaders .AsNoTracking() .Where(rtl => rtl.RaidTeamId == teamId) .Select(rtl => rtl.UserId) .AsAsyncEnumerable()) { await _discordClientProvider.SendDmAsync(leaderId, dm); } return(new TimestampDto { Timestamp = list.Timestamp }); }