public async Task <Response> TrackSucessRedirectionAsync(LinkTrackingRequest request)
        {
            try
            {
                using var conn = DbConnection;
                var lt = new LinkTracking
                {
                    Id             = Guid.NewGuid(),
                    IpAddress      = request.IpAddress,
                    LinkId         = request.LinkId,
                    RequestTimeUtc = DateTime.UtcNow,
                    UserAgent      = request.UserAgent
                };

                const string sqlInsertLt = @"INSERT INTO LinkTracking (Id, IpAddress, LinkId, RequestTimeUtc, UserAgent) 
                                                 VALUES (@Id, @IpAddress, @LinkId, @RequestTimeUtc, @UserAgent)";
                await conn.ExecuteAsync(sqlInsertLt, lt);

                return(new SuccessResponse());
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                return(new FailedResponse(e.Message));
            }
        }
Exemple #2
0
        public Task TrackSucessRedirectionAsync(LinkTrackingRequest request)
        {
            var lt = new LinkTracking
            {
                IpAddress      = request.IpAddress,
                LinkId         = request.LinkId,
                RequestTimeUtc = DateTime.UtcNow,
                UserAgent      = request.UserAgent
            };

            return(_connection.InsertAsync(lt));
        }
Exemple #3
0
        private async Task <IActionResult> PerformTokenRedirection(string token, string ip)
        {
            var isValid = _tokenGenerator.TryParseToken(token, out var validatedToken);

            if (!isValid)
            {
                return(BadRequest());
            }

            if (!_cache.TryGetValue(token, out Link linkEntry))
            {
                var flag = await _featureManager.IsEnabledAsync(nameof(FeatureFlags.AllowSelfRedirection));

                var link = await _linkForwarderService.GetLinkAsync(validatedToken);

                if (link is null)
                {
                    if (string.IsNullOrWhiteSpace(_appSettings.DefaultRedirectionUrl))
                    {
                        return(NotFound());
                    }

                    var result = _linkVerifier.Verify(_appSettings.DefaultRedirectionUrl, Url, Request, flag);
                    if (result == LinkVerifyResult.Valid)
                    {
                        return(Redirect(_appSettings.DefaultRedirectionUrl));
                    }

                    throw new UriFormatException("DefaultRedirectionUrl is not a valid URL.");
                }

                if (!link.IsEnabled)
                {
                    return(BadRequest("This link is disabled."));
                }

                var verifyOriginUrl = _linkVerifier.Verify(link.OriginUrl, Url, Request, flag);
                switch (verifyOriginUrl)
                {
                case LinkVerifyResult.Valid:
                    // cache valid link entity only.
                    if (link.TTL is not null)
                    {
                        _cache.Set(token, link, TimeSpan.FromSeconds(link.TTL.GetValueOrDefault()));
                    }
                    break;

                case LinkVerifyResult.InvalidFormat:
                    throw new UriFormatException(
                              $"OriginUrl '{link.OriginUrl}' is not a valid URL, link ID: {link.Id}.");

                case LinkVerifyResult.InvalidLocal:
                    _logger.LogWarning($"Local redirection is blocked. link: {JsonSerializer.Serialize(link)}");
                    return(BadRequest("Local redirection is blocked"));

                case LinkVerifyResult.InvalidSelfReference:
                    _logger.LogWarning(
                        $"Self reference redirection is blocked. link: {JsonSerializer.Serialize(link)}");
                    return(BadRequest("Self reference redirection is blocked"));

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            linkEntry ??= _cache.Get <Link>(token);

            var honorDNTFlag = await _featureManager.IsEnabledAsync(nameof(FeatureFlags.HonorDNT));

            if (!honorDNTFlag)
            {
                return(Redirect(linkEntry.OriginUrl));
            }

            // Check if browser sends "Do Not Track"
            var dntFlag = Request.Headers["DNT"];
            var dnt     = !string.IsNullOrWhiteSpace(dntFlag) && dntFlag == "1";

            if (dnt)
            {
                return(Redirect(linkEntry.OriginUrl));
            }

            try
            {
                var req = new LinkTrackingRequest(ip, UserAgent, linkEntry.Id);
                await _linkForwarderService.TrackSucessRedirectionAsync(req);
            }
            catch (Exception e)
            {
                // Eat exception, pretend everything is fine
                // Do not block workflow here
                _logger.LogError(e.Message, e);
            }

            return(Redirect(linkEntry.OriginUrl));
        }