Exemplo n.º 1
0
        public static async Task <IActionResult> RedirectDelete(
            [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_api/v1/redirect/{key}")] HttpRequest req,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            string key,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            RedirectEntity entity = await RedirectEntity.get(redirectTable, claimsPrincipal.Identity.Name, key);

            if (entity == null)
            {
                return(new NotFoundResult());
            }

            if (entity.Recycled)
            {
                bool deleteSuccess = await RedirectEntity.delete(redirectTable, entity);

                return(deleteSuccess ? (IActionResult) new OkObjectResult(entity) : new BadRequestResult());
            }

            entity.Recycled = true;
            bool success = await RedirectEntity.put(redirectTable, entity);

            return(success ? (IActionResult) new OkObjectResult(entity) : new BadRequestResult());
        }
Exemplo n.º 2
0
        public static async Task <IActionResult> RedirectsGet(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "_api/v1/redirects")] HttpRequest req,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            [Table(TableNames.Users)] CloudTable userTable,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            UserEntity currentUser = await UserEntity.get(userTable, claimsPrincipal.Identity.Name);

            if (!currentUser.HasPermission(Permissions.SessionAdministrator))
            {
                return(new UnauthorizedResult());
            }

            RedirectEntity[] entities = await RedirectEntity.getAll(redirectTable);

            if (entities == null)
            {
                return(new NotFoundResult());
            }

            return(new OkObjectResult(entities));
        }
Exemplo n.º 3
0
        public static async Task <IActionResult> RedirectDelete(
            [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "_api/v1/redirect/{key}")] HttpRequest req,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            [Table(TableNames.Users)] CloudTable userTable,
            string key,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            UserEntity currentUser = await UserEntity.get(userTable, claimsPrincipal.Identity.Name);

            if (!currentUser.HasPermission(Permissions.SessionAdministrator))
            {
                return(new UnauthorizedResult());
            }

            RedirectEntity entity = await RedirectEntity.get(redirectTable, key);

            if (entity == null)
            {
                return(new NotFoundResult());
            }

            bool deleteSuccess = await RedirectEntity.delete(redirectTable, entity);

            return(deleteSuccess ? (IActionResult) new OkObjectResult(entity) : new BadRequestResult());
        }
Exemplo n.º 4
0
        public static async Task <IActionResult> RedirectAndHostGet(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "_api/v1/host/redirect/{host}/{key}")] HttpRequest req,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            [Table(TableNames.Domains)] CloudTable domainTable,
            string host,
            string key,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            List <DomainEntity> domainEntity = await DomainEntity.get(domainTable, host);

            if (domainEntity == null)
            {
                return(new NotFoundResult());
            }

            RedirectEntity entity = await RedirectEntity.get(redirectTable, domainEntity.First().Account, key);

            if (entity == null)
            {
                return(new NotFoundResult());
            }

            if (entity.Recycled)
            {
                return(new NotFoundResult());
            }

            return(new OkObjectResult(new RedirectEntity(entity.PartitionKey, entity.RowKey, entity.RedirectTo, 0, new Dictionary <string, int>(), DateTime.Now, false)));
        }
Exemplo n.º 5
0
        public static async Task <IActionResult> RedirectsDashboardGet(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "_api/v1/redirects/dashboard")] HttpRequest req,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            List <RedirectEntity> entities = (await RedirectEntity.get(redirectTable, claimsPrincipal.Identity.Name));

            if (entities == null)
            {
                return(new NotFoundResult());
            }

            RedirectEntity[] filteredEntities = entities.Where(redirect => redirect.Recycled == true).ToArray();
            if (filteredEntities == null || filteredEntities.Length == 0)
            {
                return(new OkObjectResult(new RedirectEntity[] {}));
            }

            return(new OkObjectResult(filteredEntities));
        }
Exemplo n.º 6
0
        public static async void ProcessClicks(
            [QueueTrigger(QueueNames.ProcessClicks)] string queuedHttpRequestString,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            [Table(TableNames.Domains)] CloudTable domainTable,
            [Queue(QueueNames.ProcessClicksGeo), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processClicksGeoQueue,
            ILogger log,
            ExecutionContext context)
        {
            HttpRequestEntity queuedHttpRequest = JsonConvert.DeserializeObject <HttpRequestEntity>(queuedHttpRequestString);

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string nodeMaster = config["NODE_SYNC_MASTER_CONN"];

            if (nodeMaster != null)
            {
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(nodeMaster);
                CloudQueueClient    queueClient    = storageAccount.CreateCloudQueueClient();
                CloudQueue          destinationProcessClicksQueue = queueClient.GetQueueReference(QueueNames.ProcessClicks);

                await destinationProcessClicksQueue.AddMessageAsync(new CloudQueueMessage(JsonConvert.SerializeObject(queuedHttpRequest)));

                return;
            }


            List <DomainEntity> domains = await DomainEntity.get(domainTable, queuedHttpRequest.Host);

            if (domains == null)
            {
                throw new Exception($"Unable to process Geo lookup - domain {queuedHttpRequest.Host} wasn't found");
            }

            string path = queuedHttpRequest.Path.Value.Substring(1);

            RedirectEntity redirect = await RedirectEntity.get(redirectTable, domains.First().Account, path);

            if (redirect != null)
            {
                redirect.ClickCount++;
                await RedirectEntity.put(redirectTable, redirect);

                processClicksGeoQueue.Add(queuedHttpRequest);

                log.LogInformation($"Successfully processed click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                return;
            }

            log.LogError($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled hosts");
            throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled hosts");
        }
        public ActionResult Create(RedirectEntity entity)
        {
            if (!ModelState.IsValid)
            {
                return(View(entity));
            }

            _redirectService.Create(entity.Url, entity.Alias);

            return(RedirectToAction("Index"));
        }
        public ActionResult Edit(string id)
        {
            var model = _redirectService.GetById(int.Parse(id));

            var entity = new RedirectEntity();

            entity.Id    = id;
            entity.Alias = model.Alias;
            entity.Url   = model.Url;

            return(View(entity));
        }
Exemplo n.º 9
0
        public static async Task <dynamic[]?> All(CloudTable redirectTable)
        {
            RedirectEntity[] redirectData = await RedirectEntity.getAll(redirectTable);

            if (redirectData != null)
            {
                return(redirectData
                       .Where(redirect => redirect.VideoLink != null && redirect.VideoLink != "")
                       .Select((redirectData, index) => new { RowKey = redirectData.RowKey, VideoLink = redirectData.VideoLink }).ToArray());
            }

            return(null);
        }
        private static Document CreateDocumentForRedirect(RedirectEntity redirect)
        {
            var document = new Document();

            document.Add(new Field("_type", "redirect", Field.Store.NO, Field.Index.NOT_ANALYZED));
            document.Add(new Field("redirect_key", redirect.Id, Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("redirect_tagPk", redirect.TagPartitionKey, Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("redirect_tagRk", redirect.TagRowKey, Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("redirect_media", redirect.Media ?? String.Empty, Field.Store.YES, Field.Index.NO));
            document.Add(new Field("redirect_type", redirect.MediaType ?? String.Empty, Field.Store.YES, Field.Index.NO));
            document.Add(new Field("redirect_uri", redirect.Uri, Field.Store.YES, Field.Index.NO));

            return(document);
        }
Exemplo n.º 11
0
        private static IEnumerable <RedirectEntity> UpdateInstallationMediaLinksInSoftwareIdentityAndReturnWithRedirects(string tagPartitionKey, string tagRowKey, SoftwareIdentity swidtag)
        {
            foreach (var installationLink in swidtag.Links.Where(l => l.Relationship == FearTheCowboy.Iso19770.Schema.Relationship.InstallationMedia))
            {
                var redirect = new RedirectEntity(tagPartitionKey, tagRowKey, installationLink.HRef.AbsoluteUri, installationLink.MediaType, installationLink.Media, null);

                swidtag.RemoveLink(installationLink.HRef);

                var redirectUri = new Uri(redirect.RedirectUri);

                swidtag.AddLink(redirectUri, FearTheCowboy.Iso19770.Schema.Relationship.InstallationMedia);

                yield return(redirect);
            }
        }
        public ActionResult Edit(RedirectEntity entity)
        {
            if (!ModelState.IsValid)
            {
                return(View(entity));
            }

            var model = _redirectService.GetById(int.Parse(entity.Id));

            model.Alias = entity.Alias;
            model.Url   = entity.Url;

            _redirectService.Update(model);

            return(RedirectToAction("Index"));
        }
Exemplo n.º 13
0
        public static async Task <IActionResult> RunRedirectVideo(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "redirect/video/{id}/")] HttpRequest req,
            [Table(TableNames.Cache)] CloudTable cacheTable,
            [Table(TableNames.RedirectSessions)] CloudTable sessionRedirectTable,
            [Queue(QueueNames.ProcessRedirectClicks), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processRedirectQueue,
            string id,
            ILogger log,
            ExecutionContext context)
        {
            id = id ?? req.Query["id"];

            int numericId = 0;

            int.TryParse(id, out numericId);
            if (numericId > 0)
            {
                id = numericId.ToString();
            }

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            RedirectEntity redirect = await RedirectEntity.get(sessionRedirectTable, id);

            if (redirect != null && redirect.VideoLink != null)
            {
                if (req.QueryString.ToString().IndexOf("check") < 0)
                {
                    processRedirectQueue.Add(new HttpRequestEntity(req));

                    if (redirect.VideoLink.StartsWith("/") && redirect.VideoLink.Substring(1, 1) != "/")
                    {
                        return(new RedirectResult($"{config["REDIRECT_DESTINATION_HOST"]}{redirect.VideoLink}", false));
                    }

                    return(new RedirectResult($"{redirect.VideoLink}", false));
                }

                return(new AcceptedResult());
            }

            return(new NotFoundResult());
        }
Exemplo n.º 14
0
        public static async Task <IActionResult> RedirectPatch(
            [HttpTrigger(AuthorizationLevel.Anonymous, "patch", Route = "_api/v1/redirect/{key}")] HttpRequest req,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            [Table(TableNames.Users)] CloudTable userTable,
            string key,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            UserEntity currentUser = await UserEntity.get(userTable, claimsPrincipal.Identity.Name);

            if (!currentUser.HasPermission(Permissions.SessionAdministrator))
            {
                return(new UnauthorizedResult());
            }

            string  requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic entity      = JsonConvert.DeserializeObject <dynamic>(requestBody);

            log.LogInformation($"Getting Redirect row for values {claimsPrincipal.Identity.Name} and {entity.RowKey}");
            RedirectEntity existingEntity = await RedirectEntity.get(redirectTable, key);

            if (existingEntity == null)
            {
                return(new BadRequestObjectResult($"Redirect with {key} doesn't exist for {claimsPrincipal.Identity.Name}"));
            }

            existingEntity.RedirectTo = entity.redirectTo ??= existingEntity.RedirectTo;
            existingEntity.StartRedirectingMinutes = entity.startRedirectingMinutes ??= existingEntity.StartRedirectingMinutes;
            existingEntity.VideoLink = entity.videoLink ??= existingEntity.VideoLink;

            bool success = await RedirectEntity.put(redirectTable, existingEntity);

            if (!success)
            {
                return(new BadRequestObjectResult($"Error occurred updating {key} for {claimsPrincipal.Identity.Name}"));
            }

            return(new OkResult());
        }
Exemplo n.º 15
0
        public static async Task <IActionResult> RedirectPost(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "_api/v1/redirect")] HttpRequest req,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            [Table(TableNames.Users)] CloudTable userTable,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            UserEntity currentUser = await UserEntity.get(userTable, claimsPrincipal.Identity.Name);

            if (!currentUser.HasPermission(Permissions.SessionAdministrator))
            {
                return(new UnauthorizedResult());
            }

            string         requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            RedirectEntity entity      = JsonConvert.DeserializeObject <RedirectEntity>(requestBody);

            if (entity.RowKey == null || entity.RedirectTo == null)
            {
                return(new BadRequestObjectResult($"Please specify the key and redirectTo parameters in the request body"));
            }

            log.LogInformation($"Getting Redirect row for values {claimsPrincipal.Identity.Name} and {entity.RowKey}");
            RedirectEntity existingEntity = await RedirectEntity.get(redirectTable, entity.RowKey);

            if (existingEntity != null)
            {
                return(new BadRequestObjectResult($"Redirect with {entity.RowKey} already exists for {claimsPrincipal.Identity.Name}"));
            }

            bool success = await RedirectEntity.put(redirectTable, entity.RowKey, entity.RedirectTo, entity.VideoLink, -10, 0, 0, 0, "{}", "{}", "{}");

            if (!success)
            {
                return(new BadRequestObjectResult($"Error occurred creating {entity.RowKey} already exists for {claimsPrincipal.Identity.Name}"));
            }

            return(new OkResult());
        }
Exemplo n.º 16
0
        public static async void ProcessRedirectsSync(
            [QueueTrigger(QueueNames.SynchroniseRedirects)] string node,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            ILogger log,
            ExecutionContext context)
        {
            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string connectionString = config[$"NODE_SYNC_CONNECTION_{node}"];

            if (connectionString == null)
            {
                throw new Exception($"No connection string found for node [{node}]. Aborting.");
            }

            CloudStorageAccount storageAccount           = CloudStorageAccount.Parse(connectionString);
            CloudTableClient    tableClient              = storageAccount.CreateCloudTableClient();
            CloudTable          destinationRedirectTable = tableClient.GetTableReference(TableNames.RedirectSessions);

            await destinationRedirectTable.CreateIfNotExistsAsync();


            RedirectEntity[] redirects = await RedirectEntity.getAll(redirectTable);

            foreach (RedirectEntity redirect in redirects)
            {
                await RedirectEntity.put(destinationRedirectTable, redirect);
            }

            RedirectEntity[] destinationRedirects = await RedirectEntity.getAll(destinationRedirectTable);

            foreach (RedirectEntity destinationRedirect in destinationRedirects)
            {
                if (redirects.Where(checkRedirect => checkRedirect.RowKey == destinationRedirect.RowKey).Count() == 0)
                {
                    await RedirectEntity.delete(destinationRedirectTable, destinationRedirect);
                }
            }
        }
Exemplo n.º 17
0
        public static async Task <IActionResult> RedirectGet(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "_api/v1/redirect/{key}")] HttpRequest req,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            string key,
            ILogger log,
            ExecutionContext context,
            ClaimsPrincipal claimsPrincipal)
        {
            if (!claimsPrincipal.Identity.IsAuthenticated)
            {
                return(new UnauthorizedResult());
            }

            RedirectEntity entity = await RedirectEntity.get(redirectTable, claimsPrincipal.Identity.Name, key);

            if (entity == null)
            {
                return(new NotFoundResult());
            }

            return(new OkObjectResult(entity));
        }
Exemplo n.º 18
0
        public static async void ProcessRedirectsSync(
            [QueueTrigger(QueueNames.SynchroniseRedirects)] string node,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            [Table(TableNames.Domains)] CloudTable domainTable,
            [Queue(QueueNames.ProcessClicksGeo), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processClicksGeoQueue,
            ILogger log,
            ExecutionContext context)
        {
            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string connectionString = config[$"NODE_SYNC_CONNECTION_{node}"];

            if (connectionString == null)
            {
                throw new Exception($"No connection string found for node [{node}]. Aborting.");
            }

            CloudStorageAccount storageAccount           = CloudStorageAccount.Parse(connectionString);
            CloudTableClient    tableClient              = storageAccount.CreateCloudTableClient();
            CloudTable          destinationRedirectTable = tableClient.GetTableReference(TableNames.Redirects);
            CloudTable          destinationDomainTable   = tableClient.GetTableReference(TableNames.Domains);

            await destinationRedirectTable.CreateIfNotExistsAsync();

            await destinationDomainTable.CreateIfNotExistsAsync();

            List <DomainEntity> domains = await DomainEntity.get(domainTable, null);

            List <string> uniqueAccounts = new List <string>();

            foreach (DomainEntity domain in domains)
            {
                await DomainEntity.put(destinationDomainTable, domain);

                if (uniqueAccounts.FindIndex(checkAccount => checkAccount == domain.Account) == -1)
                {
                    uniqueAccounts.Add(domain.Account);
                }
            }

            List <DomainEntity> destinationDomains = await DomainEntity.get(destinationDomainTable, null);

            foreach (DomainEntity destinationDomain in destinationDomains)
            {
                if (domains.FindIndex(checkDomain => checkDomain.RowKey == destinationDomain.RowKey) == -1)
                {
                    await DomainEntity.delete(destinationRedirectTable, destinationDomain);
                }
            }


            foreach (string account in uniqueAccounts)
            {
                List <RedirectEntity> redirects = await RedirectEntity.get(redirectTable, account);

                foreach (RedirectEntity redirect in redirects)
                {
                    await RedirectEntity.put(destinationRedirectTable, redirect);
                }

                List <RedirectEntity> destinationRedirects = await RedirectEntity.get(destinationRedirectTable, account);

                foreach (RedirectEntity destinationRedirect in destinationRedirects)
                {
                    if (redirects.FindIndex(checkRedirect => checkRedirect.RowKey == destinationRedirect.RowKey) == -1)
                    {
                        await RedirectEntity.delete(destinationRedirectTable, destinationRedirect);
                    }
                }
            }
        }
Exemplo n.º 19
0
        public static async Task <IActionResult> ShortNameGet(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "{shortName:regex([\\w\\d]+)}")] HttpRequest req,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            [Table(TableNames.Domains)] CloudTable domainTable,
            [Queue(QueueNames.ProcessClicks), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processClicksQueue,
            [Queue(QueueNames.NotFoundClicks), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> notFoundClicksQueue,
            string shortName,
            ILogger log,
            ExecutionContext context)
        {
            List <DomainEntity> domains = await DomainEntity.get(domainTable, req.Host.Value);

            if (domains == null)
            {
                notFoundClicksQueue.Add(new NotFoundEntity(req, "Domain not handled"));
                return(new NotFoundResult());
            }

            RedirectEntity redirect = await RedirectEntity.get(redirectTable, domains.First().Account, shortName);

            if (redirect == null)
            {
                var config = new ConfigurationBuilder()
                             .SetBasePath(context.FunctionAppDirectory)
                             .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                             .AddEnvironmentVariables()
                             .Build();

                string nodeMaster = config["NODE_SYNC_MASTER_HOST"];

                if (nodeMaster == null)
                {
                    notFoundClicksQueue.Add(new NotFoundEntity(req, "Node master not found"));
                    return(new NotFoundResult());
                }

                string nodeMasterLookupUri = $"https://{nodeMaster}/_api/v1/host/redirect/{req.Host.Value}/{shortName}";
                var    client      = new HttpClient();
                var    getResponse = await client.GetAsync(nodeMasterLookupUri);

                if (getResponse.StatusCode != HttpStatusCode.OK)
                {
                    notFoundClicksQueue.Add(new NotFoundEntity(req, "Node master returned not found"));
                    return(new NotFoundResult());
                }

                string masterResponseString = await getResponse.Content.ReadAsStringAsync();

                redirect = JsonConvert.DeserializeObject <RedirectEntity>(masterResponseString);
                await RedirectEntity.put(redirectTable, redirect);
            }

            if (redirect.Recycled)
            {
                notFoundClicksQueue.Add(new NotFoundEntity(req, "Short name has been recycled"));
                return(new NotFoundResult());
            }

            req.HttpContext.Response.Headers.Add("Cache-Control", "no-cache,no-store");
            req.HttpContext.Response.Headers.Add("Expires", DateTime.Now.AddMinutes(5).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss G\\MT"));
            req.HttpContext.Response.Headers.Add("Vary", "Origin");

            processClicksQueue.Add(new HttpRequestEntity(req));
            return(new RedirectResult(redirect.RedirectTo, true));
        }
Exemplo n.º 20
0
        public static async void ProcessClicksForGeo(
            [QueueTrigger(QueueNames.ProcessClicksGeo)] string queuedHttpRequestString,
            [Table(TableNames.Redirects)] CloudTable redirectTable,
            [Table(TableNames.Domains)] CloudTable domainTable,
            [Table(TableNames.Geos)] CloudTable geoTable,
            ILogger log,
            ExecutionContext context)
        {
            HttpRequestEntity queuedHttpRequest = JsonConvert.DeserializeObject <HttpRequestEntity>(queuedHttpRequestString);

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string ipLookupUrl = $"{config["FREEGEOIP_HOST"] ??= "https://freegeoip.app"}/json/{queuedHttpRequest.RemoteIpAddress}";

            log.LogInformation($"Looking up freegeoip: {ipLookupUrl}.");


            var client      = new HttpClient();
            var getResponse = await client.GetAsync(ipLookupUrl);

            if (getResponse.StatusCode == HttpStatusCode.OK)
            {
                List <DomainEntity> domains = await DomainEntity.get(domainTable, queuedHttpRequest.Host);

                if (domains == null)
                {
                    throw new Exception($"Unable to process Geo lookup - domain {queuedHttpRequest.Host} wasn't found");
                }

                string path = queuedHttpRequest.Path.Value.Substring(1);

                RedirectEntity redirect = await RedirectEntity.get(redirectTable, domains.First().Account, path);

                if (redirect != null)
                {
                    string ipResponseString = await getResponse.Content.ReadAsStringAsync();

                    dynamic   ipResponse = JsonConvert.DeserializeObject <dynamic>(ipResponseString);
                    GeoEntity geoEntity  = new GeoEntity(ipResponse);
                    await GeoEntity.put(geoTable, geoEntity);

                    Dictionary <string, int> _geoCount = JsonConvert.DeserializeObject <Dictionary <string, int> >(redirect.GeoCount ??= "{}");
                    if (_geoCount.ContainsKey(geoEntity.RowKey))
                    {
                        log.LogInformation($"Incrementing GeoCount for redirect entity {queuedHttpRequest.Path}");

                        _geoCount[geoEntity.RowKey] = _geoCount[geoEntity.RowKey] + 1;
                    }
                    else
                    {
                        log.LogInformation($"Creating GeoCount for redirect entity {queuedHttpRequest.Path}");
                        _geoCount.Add(geoEntity.RowKey, 1);
                    }

                    redirect.GeoCount = JsonConvert.SerializeObject(_geoCount);
                    await RedirectEntity.put(redirectTable, redirect);

                    return;
                }


                log.LogError($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled path");
                throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled path");
            }

            log.LogError($"Free geo ip lookup for IP {queuedHttpRequest.RemoteIpAddress} failed with status code {getResponse.StatusCode}");
            throw new System.Exception($"Free geo ip lookup for IP {queuedHttpRequest.RemoteIpAddress} failed with status code {getResponse.StatusCode}");
        }
        public ActionResult Delete(RedirectEntity entity)
        {
            _redirectService.Delete(int.Parse(entity.Id));

            return(RedirectToAction("Index"));
        }
Exemplo n.º 22
0
        public static async Task <IActionResult> RunRedirectSession(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "redirect/session/{id}/")] HttpRequest req,
            [Table(TableNames.Cache)] CloudTable cacheTable,
            [Table(TableNames.RedirectSessions)] CloudTable sessionRedirectTable,
            [Queue(QueueNames.ProcessRedirectClicks), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processRedirectQueue,
            string id,
            ILogger log,
            ExecutionContext context)
        {
            id = id ?? req.Query["id"];

            int numericId = 0;

            int.TryParse(id, out numericId);
            if (numericId > 0)
            {
                id = numericId.ToString();
            }

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            RedirectEntity redirect = await RedirectEntity.get(sessionRedirectTable, id);

            Session foundSession = GetSession.ById(await GetSession.GetAllSessions(cacheTable, log, context), id, req, true);

            if (redirect != null && redirect.RedirectTo != null)
            {
                int startRedirectingMinutes = (redirect.StartRedirectingMinutes == null) ? -5 : redirect.StartRedirectingMinutes.Value;

                if (foundSession != null && foundSession.startsAt != null)
                {
                    DateTime startRedirecting = foundSession.startsAt.Value.ToUniversalTime().AddMinutes(startRedirectingMinutes);
                    DateTime now = DateTime.Now;

                    if (DateTime.Compare(now, startRedirecting) >= 0)
                    {
                        log.LogInformation($"Start redirecting condition met for {req.Path} - redirect time was {startRedirecting} (current time {now})");

                        if (req.QueryString.ToString().IndexOf("check") < 0)
                        {
                            processRedirectQueue.Add(new HttpRequestEntity(req));

                            if (redirect.RedirectTo.StartsWith("/") && redirect.RedirectTo.Substring(1, 1) != "/")
                            {
                                return(new RedirectResult($"{config["REDIRECT_DESTINATION_HOST"]}{redirect.RedirectTo}", false));
                            }

                            return(new RedirectResult($"{redirect.RedirectTo}", false));
                        }

                        return(new AcceptedResult());
                    }
                    else
                    {
                        log.LogInformation($"Start redirecting condition not met for {req.Path} - waiting until {startRedirecting} (current time {now})");

                        if (req.QueryString.ToString().IndexOf("check") >= 0)
                        {
                            return(new OkObjectResult($"Session found, waiting until {startRedirecting} before redirecting (current time {now})"));
                        }
                    }
                }
                else
                {
                    log.LogInformation($"Start redirecting condition not met for {req.Path} - session has no start time)");

                    if (req.QueryString.ToString().IndexOf("check") >= 0)
                    {
                        return(new OkObjectResult($"Session found, but has no start time in sessionize"));
                    }
                }
            }

            if (foundSession != null)
            {
                if (req.QueryString.ToString().IndexOf("check") >= 0)
                {
                    return(new OkObjectResult($"Session found, wait for redirect"));
                }

                string holdingPageUrl = $"{config["HOLDPAGE_SESSION"]}";
                holdingPageUrl = holdingPageUrl.Replace("{id}", foundSession.id ??= string.Empty);

                int  holdpageCacheMinutes = 0;
                bool foundConfig          = int.TryParse(config["HOLDPAGE_CACHE_MINUTES"], out holdpageCacheMinutes);
                if (!foundConfig)
                {
                    holdpageCacheMinutes = 10;
                }

                CacheEntity cachedSessionPage = await CacheEntity.get(cacheTable, CacheType.Session, $"session-{id}", new TimeSpan(0, holdpageCacheMinutes, 0));

                if (cachedSessionPage != null)
                {
                    string value = cachedSessionPage.GetValue();

                    return(new ContentResult {
                        ContentType = "text/html; charset=UTF-8",
                        Content = value
                    });
                }

                log.LogInformation($"Looking up holding page content: {holdingPageUrl}.");

                var client      = new HttpClient();
                var getResponse = await client.GetAsync(holdingPageUrl);

                if (getResponse.IsSuccessStatusCode)
                {
                    string value = await getResponse.Content.ReadAsStringAsync();

                    int  redirectDelay      = 10;
                    bool foundRedirectDelay = int.TryParse(config["REDIRECT_DELAY"], out redirectDelay);
                    if (!foundRedirectDelay)
                    {
                        redirectDelay = 10;
                    }

                    value = value.Replace("{title}", foundSession.title ??= string.Empty);
                    value = value.Replace("{description}", foundSession.description ??= string.Empty);
                    value = value.Replace("{id}", foundSession.id ??= string.Empty);
                    value = value.Replace("{url}", foundSession.url ??= string.Empty);
                    value = value.Replace("{ical}", foundSession.ical ??= string.Empty);
                    value = value.Replace("{speakers}", string.Join(", ", foundSession.speakers.Select(speaker => speaker.name)));
                    value = value.Replace("{redirect-js}", Constants.REDIRECT_JS.Replace("{url}", $"{req.Path}?check")).Replace("{redirect-delay}", (redirectDelay * 1000).ToString());
                    value = value.Replace("{embed-js}", EMBED_JS);

                    if (value.IndexOf("{speaker-profiles}") >= 0)
                    {
                        string speakerData = await GetSpeaker.GetAllSpeakers(cacheTable, log, context);

                        value = value.Replace("{speaker-profiles}", string.Join("", foundSession.speakers.Select(speaker => {
                            SpeakerInformation foundSpeaker = GetSpeaker.ById(speakerData, speaker.id, req, false);
                            return(SpeakerInformation.ProcessSpeakerTokens(Constants.SPEAKER_HTML, foundSpeaker));
                        })));
                    }

                    await CacheEntity.put(cacheTable, CacheType.Session, $"session-{id}", value, 600);

                    return(new ContentResult {
                        ContentType = "text/html; charset=UTF-8",
                        Content = value
                    });
                }
                else
                {
                    return(new NotFoundObjectResult($"{config["HOLDPAGE_SESSION"]} template page not found"));
                }
            }

            return(new NotFoundResult());
        }
Exemplo n.º 23
0
        public static async void ProcessRedirectClicksForGeo(
            [QueueTrigger(QueueNames.ProcessRedirectClicksForGeo)] string queuedHttpRequestString,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            ILogger log,
            ExecutionContext context)
        {
            HttpRequestEntity queuedHttpRequest = JsonConvert.DeserializeObject <HttpRequestEntity>(queuedHttpRequestString);

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string ipLookupUrl = $"{config["FREEGEOIP_HOST"] ??= "https://freegeoip.app"}/json/{queuedHttpRequest.RemoteIpAddress}";

            log.LogInformation($"Looking up freegeoip: {ipLookupUrl}.");

            var client      = new HttpClient();
            var getResponse = await client.GetAsync(ipLookupUrl);

            if (getResponse.StatusCode == HttpStatusCode.OK)
            {
                MatchCollection matches = Regex.Matches(queuedHttpRequest.Path, "/redirect/session/(\\d+)/", RegexOptions.IgnoreCase);
                if (matches.Count > 0)
                {
                    string ipResponseString = await getResponse.Content.ReadAsStringAsync();

                    dynamic   ipResponse      = JsonConvert.DeserializeObject(ipResponseString);
                    GeoEntity geoEntity       = new GeoEntity(ipResponse);
                    string    geoEntityString = JsonConvert.SerializeObject(geoEntity);

                    RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, matches[0].Groups[1].Value);

                    if (redirectEntity != null)
                    {
                        if (redirectEntity.GeoCount == null)
                        {
                            log.LogInformation($"Adding GeoCount property to redirect entity {queuedHttpRequest.Path}");
                            // redirectEntity.GeoCount = new Dictionary<string, int>();
                        }

                        Dictionary <string, int> _geoCount = JsonConvert.DeserializeObject <Dictionary <string, int> >(redirectEntity.GeoCount ??= "{}");
                        if (_geoCount.ContainsKey(geoEntityString))
                        {
                            log.LogInformation($"Incrementing GeoCount for redirect entity {queuedHttpRequest.Path}");

                            _geoCount[geoEntityString] = _geoCount[geoEntityString] + 1;
                        }
                        else
                        {
                            log.LogInformation($"Creating GeoCount for redirect entity {queuedHttpRequest.Path}");
                            _geoCount.Add(geoEntityString, 1);
                        }

                        log.LogInformation($" GeoCount property value: {JsonConvert.SerializeObject(redirectEntity.GeoCount)}");

                        await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, JsonConvert.SerializeObject(_geoCount), redirectEntity.CalendarGeoCount, redirectEntity.VideoGeoCount);

                        log.LogInformation($"Successfully processed geo ip click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                        return;
                    }
                    else
                    {
                        log.LogError($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                        throw new System.Exception($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                    }
                }

                MatchCollection calendarMatches = Regex.Matches(queuedHttpRequest.Path, "/calendar/session/(\\d+)", RegexOptions.IgnoreCase);
                if (calendarMatches.Count > 0)
                {
                    string ipResponseString = await getResponse.Content.ReadAsStringAsync();

                    dynamic   ipResponse      = JsonConvert.DeserializeObject(ipResponseString);
                    GeoEntity geoEntity       = new GeoEntity(ipResponse);
                    string    geoEntityString = JsonConvert.SerializeObject(geoEntity);

                    RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, calendarMatches[0].Groups[1].Value);

                    if (redirectEntity != null)
                    {
                        Dictionary <string, int> _calendarGeoCount = JsonConvert.DeserializeObject <Dictionary <string, int> >(redirectEntity.CalendarGeoCount ??= "{}");
                        if (_calendarGeoCount.ContainsKey(geoEntityString))
                        {
                            log.LogInformation($"Incrementing CalendarGeoCount for redirect entity {queuedHttpRequest.Path}");

                            _calendarGeoCount[geoEntityString] = _calendarGeoCount[geoEntityString] + 1;
                        }
                        else
                        {
                            log.LogInformation($"Creating CalendarGeoCount for redirect entity {queuedHttpRequest.Path}");
                            _calendarGeoCount.Add(geoEntityString, 1);
                        }

                        log.LogInformation($" CalendarGeoCount property value: {JsonConvert.SerializeObject(redirectEntity.GeoCount)}");

                        await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, redirectEntity.GeoCount, JsonConvert.SerializeObject(_calendarGeoCount), redirectEntity.VideoGeoCount);

                        log.LogInformation($"Successfully processed calendar geo ip click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                        return;
                    }
                    else
                    {
                        log.LogError($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                        throw new System.Exception($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                    }
                }

                MatchCollection videoMatches = Regex.Matches(queuedHttpRequest.Path, "/redirect/video/(\\d+)/", RegexOptions.IgnoreCase);
                if (videoMatches.Count > 0)
                {
                    string ipResponseString = await getResponse.Content.ReadAsStringAsync();

                    dynamic   ipResponse      = JsonConvert.DeserializeObject(ipResponseString);
                    GeoEntity geoEntity       = new GeoEntity(ipResponse);
                    string    geoEntityString = JsonConvert.SerializeObject(geoEntity);

                    RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, videoMatches[0].Groups[1].Value);

                    if (redirectEntity != null)
                    {
                        Dictionary <string, int> _videoGeoCount = JsonConvert.DeserializeObject <Dictionary <string, int> >(redirectEntity.VideoGeoCount ??= "{}");
                        if (_videoGeoCount.ContainsKey(geoEntityString))
                        {
                            log.LogInformation($"Incrementing VideoGeoCount for redirect entity {queuedHttpRequest.Path}");

                            _videoGeoCount[geoEntityString] = _videoGeoCount[geoEntityString] + 1;
                        }
                        else
                        {
                            log.LogInformation($"Creating VideoGeoCount for redirect entity {queuedHttpRequest.Path}");
                            _videoGeoCount.Add(geoEntityString, 1);
                        }

                        log.LogInformation($" VideoGeoCount property value: {JsonConvert.SerializeObject(redirectEntity.GeoCount)}");

                        await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, redirectEntity.GeoCount, redirectEntity.CalendarGeoCount, JsonConvert.SerializeObject(_videoGeoCount));

                        log.LogInformation($"Successfully processed video geo ip click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                        return;
                    }
                    else
                    {
                        log.LogError($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                        throw new System.Exception($"Http request {queuedHttpRequest.Path} for click geo handling failed to match a redirect session");
                    }
                }

                log.LogError($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled paths");
                throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled paths");
            }

            log.LogError($"Free geo ip lookup for IP {queuedHttpRequest.RemoteIpAddress} failed with status code {getResponse.StatusCode}");
            throw new System.Exception($"Free geo ip lookup for IP {queuedHttpRequest.RemoteIpAddress} failed with status code {getResponse.StatusCode}");
        }
Exemplo n.º 24
0
        public static async void ProcessRedirectClicks(
            [QueueTrigger(QueueNames.ProcessRedirectClicks)] string queuedHttpRequestString,
            [Table(TableNames.RedirectSessions)] CloudTable redirectTable,
            [Queue(QueueNames.ProcessRedirectClicksForGeo), StorageAccount("AzureWebJobsStorage")] ICollector <HttpRequestEntity> processRedirectQueueForGeo,
            ILogger log,
            ExecutionContext context)
        {
            HttpRequestEntity queuedHttpRequest = JsonConvert.DeserializeObject <HttpRequestEntity>(queuedHttpRequestString);

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            string nodeMaster = config["NODE_SYNC_MASTER_CONN"];

            if (nodeMaster != null)
            {
                try {
                    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(nodeMaster);
                    CloudQueueClient    queueClient    = storageAccount.CreateCloudQueueClient();
                    CloudQueue          destinationProcessClicksQueue = queueClient.GetQueueReference(QueueNames.ProcessRedirectClicks);

                    await destinationProcessClicksQueue.AddMessageAsync(new CloudQueueMessage(queuedHttpRequestString));
                }
                catch (Exception ex) {
                    log.LogError(ex.Message);
                    throw ex;
                }

                return;
            }

            MatchCollection matches = Regex.Matches(queuedHttpRequest.Path, "/redirect/session/(\\d+)/", RegexOptions.IgnoreCase);

            if (matches.Count > 0)
            {
                RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, matches[0].Groups[1].Value);

                if (redirectEntity != null)
                {
                    redirectEntity.ClickCount++;
                    await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, redirectEntity.GeoCount, redirectEntity.CalendarGeoCount, redirectEntity.VideoGeoCount);

                    processRedirectQueueForGeo.Add(queuedHttpRequest);

                    log.LogInformation($"Successfully processed click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                    return;
                }
                else
                {
                    log.LogError($"Http request {queuedHttpRequest.Path} for click handling failed to match a redirect session");
                    throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled paths");
                }
            }

            MatchCollection sessionMatches = Regex.Matches(queuedHttpRequest.Path, "/calendar/session/(\\d+)", RegexOptions.IgnoreCase);

            if (sessionMatches.Count > 0)
            {
                RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, sessionMatches[0].Groups[1].Value);

                if (redirectEntity != null)
                {
                    redirectEntity.CalendarClickCount++;
                    await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, redirectEntity.GeoCount, redirectEntity.CalendarGeoCount, redirectEntity.VideoGeoCount);

                    processRedirectQueueForGeo.Add(queuedHttpRequest);

                    log.LogInformation($"Successfully processed click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                    return;
                }
                else
                {
                    log.LogError($"Http request {queuedHttpRequest.Path} for click handling failed to match a redirect session");
                    throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling failed to match a redirect session");
                }
            }

            MatchCollection videoMatches = Regex.Matches(queuedHttpRequest.Path, "/redirect/video/(\\d+)/", RegexOptions.IgnoreCase);

            if (videoMatches.Count > 0)
            {
                RedirectEntity redirectEntity = await RedirectEntity.get(redirectTable, videoMatches[0].Groups[1].Value);

                if (redirectEntity != null)
                {
                    redirectEntity.VideoClickCount++;
                    await RedirectEntity.put(redirectTable, redirectEntity.RowKey, redirectEntity.RedirectTo, redirectEntity.VideoLink, redirectEntity.StartRedirectingMinutes ??= 0, redirectEntity.ClickCount, redirectEntity.CalendarClickCount, redirectEntity.VideoClickCount, redirectEntity.GeoCount, redirectEntity.CalendarGeoCount, redirectEntity.VideoGeoCount);

                    processRedirectQueueForGeo.Add(queuedHttpRequest);

                    log.LogInformation($"Successfully processed click for redirect query {queuedHttpRequest.Path} from {queuedHttpRequest.RemoteIpAddress}");

                    return;
                }
                else
                {
                    log.LogError($"Http request {queuedHttpRequest.Path} for click handling failed to match a redirect session");
                    throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling failed to match a redirect session");
                }
            }

            log.LogError($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled paths");
            throw new System.Exception($"Http request {queuedHttpRequest.Path} for click handling doesn't match handled paths");
        }
 public DownloadCount(RedirectEntity redirect)
 {
     this.Redirect = redirect;
 }