Example #1
0
        public async Task <IActionResult> PublicationSubscribeFunc(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "publication/subscribe/")]
            HttpRequest req,
            ILogger logger,
            ExecutionContext context)
        {
            logger.LogInformation("{FunctionName} triggered", context.FunctionName);

            var config                    = LoadAppSettings(context);
            var baseUrl                   = config.GetValue <string>(BaseUrlName);
            var emailTemplateId           = config.GetValue <string>(VerificationEmailTemplateIdName);
            var tokenSecretKey            = config.GetValue <string>(TokenSecretKeyName);
            var subscriptionsTable        = GetCloudTable(_storageTableService, config, SubscriptionsTblName);
            var pendingSubscriptionsTable = GetCloudTable(_storageTableService, config, PendingSubscriptionsTblName);
            var client                    = GetNotifyClient(config);

            string?id    = req.Query["id"];
            string?email = req.Query["email"];
            string?slug  = req.Query["slug"];
            string?title = req.Query["title"];

            var     subscriptionPending = false;
            var     requestBody         = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic?data = JsonConvert.DeserializeObject(requestBody);

            id ??= data?.id;
            email ??= data?.email;
            slug ??= data?.slug;
            title ??= data?.title;

            if (id == null || email == null || slug == null || title == null)
            {
                return(new BadRequestObjectResult("Please pass a valid email & publication"));
            }

            try
            {
                subscriptionPending =
                    _storageTableService
                    .RetrieveSubscriber(pendingSubscriptionsTable, new SubscriptionEntity(id, email)).Result !=
                    null;

                logger.LogDebug("Pending subscription found?: {PendingSubscription}", subscriptionPending);

                // If already existing and pending then don't send another one
                if (!subscriptionPending)
                {
                    // Now check if already subscribed

                    var activeSubscriber = _storageTableService
                                           .RetrieveSubscriber(subscriptionsTable, new SubscriptionEntity(id, email)).Result;
                    if (activeSubscriber != null)
                    {
                        var unsubscribeToken =
                            _tokenService.GenerateToken(tokenSecretKey, activeSubscriber.RowKey,
                                                        DateTime.UtcNow.AddYears(1));

                        var confirmationEmailTemplateId = config.GetValue <string>(ConfirmationEmailTemplateIdName);
                        var confirmationValues          = new Dictionary <string, dynamic>
                        {
                            { "publication_name", activeSubscriber.Title },
                            {
                                "unsubscribe_link",
                                $"{baseUrl}{activeSubscriber.PartitionKey}/unsubscribe/{unsubscribeToken}"
                            }
                        };
                        _emailService.SendEmail(client, email, confirmationEmailTemplateId, confirmationValues);
                        return(new OkResult());
                    }

                    // Verification Token expires in 1 hour
                    var expiryDateTime = DateTime.UtcNow.AddHours(1);
                    var activationCode = _tokenService.GenerateToken(tokenSecretKey, email, expiryDateTime);

                    await _storageTableService.UpdateSubscriber(pendingSubscriptionsTable,
                                                                new SubscriptionEntity(id, email, title, slug, expiryDateTime));

                    var values = new Dictionary <string, dynamic>
                    {
                        { "publication_name", title },
                        { "verification_link", $"{baseUrl}{id}/verify-subscription/{activationCode}" },
                    };

                    _emailService.SendEmail(client, email, emailTemplateId, values);
                }

                return(new OkResult());
            }
            catch (NotifyClientException e)
            {
                logger.LogError(e, "Caught exception sending email");

                // Remove the subscriber from storage if we could not successfully send the email & just added it
                if (!subscriptionPending)
                {
                    await _storageTableService.RemoveSubscriber(pendingSubscriptionsTable,
                                                                new SubscriptionEntity(id, email));
                }

                return(new BadRequestResult());
            }
            catch (Exception e)
            {
                logger.LogError(e, "Caught exception storing subscription");
                return(new BadRequestResult());
            }
        }