Example #1
0
        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
            });
        }
Example #2
0
        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
            });
        }
Example #3
0
        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
        });
    }