Ejemplo n.º 1
0
        private async Task UpdateAliasNew(string originalName, int?ip, Data.Models.Client.EFClient entity,
                                          DatabaseContext context)
        {
            var name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH);

            var existingAliases = await context.Aliases
                                  .Where(alias => alias.Name == name && alias.LinkId == entity.AliasLinkId ||
                                         alias.Name == name && alias.IPAddress != null && alias.IPAddress == ip)
                                  .ToListAsync();

            var defaultAlias       = existingAliases.FirstOrDefault(alias => alias.IPAddress == null);
            var existingExactAlias =
                existingAliases.FirstOrDefault(alias => alias.IPAddress != null && alias.IPAddress == ip);

            if (defaultAlias != null && existingExactAlias == null)
            {
                defaultAlias.IPAddress = ip;
                entity.CurrentAlias    = defaultAlias;
                entity.CurrentAliasId  = defaultAlias.AliasId;
                await context.SaveChangesAsync();

                return;
            }

            if (existingExactAlias != null && entity.AliasLinkId == existingExactAlias.LinkId)
            {
                entity.CurrentAlias   = existingExactAlias;
                entity.CurrentAliasId = existingExactAlias.AliasId;
                await context.SaveChangesAsync();

                _logger.LogDebug("[{Method}] client {Client} already has an existing exact alias, so we are not making changes", nameof(UpdateAliasNew), entity.ToString());
                return;
            }

            _logger.LogDebug("[{Method}] {Entity} is using a new alias", nameof(UpdateAliasNew), entity.ToString());

            var newAlias = new EFAlias()
            {
                DateAdded      = DateTime.UtcNow,
                IPAddress      = ip,
                LinkId         = entity.AliasLinkId,
                Name           = name,
                SearchableName = name.StripColors().ToLower(),
                Active         = true,
            };

            entity.CurrentAlias = newAlias;
            await context.SaveChangesAsync();

            entity.CurrentAliasId = newAlias.AliasId;
        }
Ejemplo n.º 2
0
        private async Task UpdateAlias(string originalName, int?ip, Data.Models.Client.EFClient entity, DatabaseContext context)
        {
            {
                string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH);

                // entity is the tracked db context item
                // get all aliases by IP address and LinkId
                var iqAliases = context.Aliases
                                .Include(a => a.Link)
                                // we only want alias that have the same IP address or share a link
                                .Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId));

                var aliases = await iqAliases.ToListAsync();

                var currentIPs        = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct();
                var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress))
                                        .ToListAsync();

                aliases.AddRange(floatingIPAliases);

                // see if they have a matching IP + Name but new NetworkId
                var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId)
                                         .FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
                bool hasExactAliasMatch = existingExactAlias != null;

                // if existing alias matches link them
                var newAliasLink = existingExactAlias?.Link;
                // if no exact matches find the first IP or LinkId that matches
                newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link;
                // if no matches are found, use our current one ( it will become permanent )
                newAliasLink = newAliasLink ?? entity.AliasLink;

                bool hasExistingAlias   = aliases.Count > 0;
                bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;

                await context.SaveChangesAsync();

                int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count();
                // this happens when the link we found is different than the one we create before adding an IP
                if (isAliasLinkUpdated || distinctLinkCount > 1)
                {
                    _logger.LogDebug(
                        "[updatealias] found a link for {entity} so we are updating link from {oldAliasLinkId} to {newAliasLinkId}",
                        entity.ToString(), entity.AliasLink.AliasLinkId, newAliasLink.AliasLinkId);

                    var completeAliasLinkIds = aliases.Select(_item => _item.LinkId)
                                               .Append(entity.AliasLinkId)
                                               .Distinct()
                                               .ToList();

                    _logger.LogDebug("[updatealias] updating aliasLinks {links} for IP {ip} to {linkId}",
                                     string.Join(',', completeAliasLinkIds), ip, newAliasLink.AliasLinkId);

                    // update all the clients that have the old alias link
                    await context.Clients
                    .Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId))
                    .ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);

                    // we also need to update all the penalties or they get deleted
                    // scenario
                    // link1 joins with ip1
                    // link2 joins with ip2,
                    // link2 receives penalty
                    // link2 joins with ip1
                    // pre existing link for link2 detected
                    // link2 is deleted
                    // link2 penalties are orphaned
                    await context.Penalties
                    .Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId))
                    .ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId);

                    entity.AliasLink   = newAliasLink;
                    entity.AliasLinkId = newAliasLink.AliasLinkId;

                    // update all previous aliases
                    await context.Aliases
                    .Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId))
                    .ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId);

                    await context.SaveChangesAsync();

                    // we want to delete the now inactive alias
                    if (newAliasLink.AliasLinkId != entity.AliasLinkId)
                    {
                        context.AliasLinks.Remove(entity.AliasLink);
                        await context.SaveChangesAsync();
                    }
                }

                // the existing alias matches ip and name, so we can just ignore the temporary one
                if (hasExactAliasMatch)
                {
                    _logger.LogDebug("[updatealias] {entity} has exact alias match", entity.ToString());

                    var oldAlias = entity.CurrentAlias;
                    entity.CurrentAliasId = existingExactAlias.AliasId;
                    entity.CurrentAlias   = existingExactAlias;
                    await context.SaveChangesAsync();

                    // the alias is the same so we can just remove it
                    if (oldAlias.AliasId != existingExactAlias.AliasId && oldAlias.AliasId > 0)
                    {
                        await context.Clients
                        .Where(_client => _client.CurrentAliasId == oldAlias.AliasId)
                        .ForEachAsync(_client => _client.CurrentAliasId = existingExactAlias.AliasId);

                        await context.SaveChangesAsync();

                        if (context.Entry(oldAlias).State != EntityState.Deleted)
                        {
                            _logger.LogDebug(
                                "[updatealias] {entity} has exact alias match, so we're going to try to remove aliasId {aliasId} with linkId {linkId}",
                                entity.ToString(), oldAlias.AliasId, oldAlias.LinkId);
                            context.Aliases.Remove(oldAlias);
                            await context.SaveChangesAsync();
                        }
                    }
                }

                // theres no exact match, but they've played before with the GUID or IP
                else
                {
                    _logger.LogDebug("[updatealias] {entity} is using a new alias", entity.ToString());

                    var newAlias = new EFAlias()
                    {
                        DateAdded      = DateTime.UtcNow,
                        IPAddress      = ip,
                        LinkId         = newAliasLink.AliasLinkId,
                        Name           = name,
                        SearchableName = name.StripColors().ToLower(),
                        Active         = true,
                    };

                    entity.CurrentAlias   = newAlias;
                    entity.CurrentAliasId = 0;
                    await context.SaveChangesAsync();
                }
            }
        }