Example #1
0
        /// <summary>
        /// Suspend the subscription
        /// </summary>
        /// <param name="subscriptionId"></param>
        /// <returns></returns>
        public async Task <Subscription> SuspendAsync(Guid subscriptionId, Guid operationId)
        {
            Subscription subscription;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscription = await GetAsync(subscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Suspend.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            CheckSubscriptionInReadyState(subscription);
            _logger.LogInformation($"Operation {operationId}: Suspend subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}.");

            // Soft delete the subscription from db
            subscription.OperationId        = operationId;
            subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending);
            subscription.ProvisioningType   = nameof(ProvisioningType.Suspend);
            subscription.LastUpdatedTime    = DateTime.UtcNow;

            _context.Subscriptions.Update(subscription);
            await _context._SaveChangesAsync();

            _logger.LogInformation($"Operation {operationId}: Subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is suspended.");

            return(subscription);
        }
Example #2
0
        /// <summary>
        /// Activate a subscription.
        /// </summary>
        /// <param name="subscriptionId">The id of the subscription to activate.</param>
        /// <param name="activatedBy">The id of the user who activated this subscription.</param>
        /// <returns>The activated subscription.</returns>
        public async Task <Subscription> ActivateAsync(Guid subscriptionId, string activatedBy = "system")
        {
            Subscription subscription;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscription = await GetAsync(subscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Activate.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            _logger.LogInformation($"Activate subscription {subscriptionId}.");
            subscription.Status        = nameof(FulfillmentState.Subscribed);
            subscription.ActivatedTime = DateTime.UtcNow;
            subscription.ActivatedBy   = activatedBy;

            _context.Subscriptions.Update(subscription);
            await _context._SaveChangesAsync();

            _logger.LogInformation($"Activated subscription {subscriptionId}. Activated by: {activatedBy}.");
            return(subscription);
        }
Example #3
0
        public void CheckSubscriptionInReadyState(Subscription subscription)
        {
            if (!subscription.Status.Equals(nameof(FulfillmentState.Subscribed)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb(), invalidFulfillmentState: nameof(subscription.Status)));
            }

            if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb(), invalidProvisioningState: true));
            }

            _logger.LogInformation($"Subscription {subscription.SubscriptionId} is in the Subscribed fulfillment state and Succeeded provisioining state.");
        }
Example #4
0
        /// <summary>
        /// Soft delete a subscription.
        /// </summary>
        /// <param name="subscriptionId">The id of the subscription to soft delete.</param>
        /// <returns>The subscription with updated status and unsubscribed_time.</returns>
        public async Task <Subscription> UnsubscribeAsync(Guid subscriptionId, Guid operationId)
        {
            Subscription subscription;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscription = await GetAsync(subscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Unsubscribe.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            CheckSubscriptionInReadyState(subscription);
            _logger.LogInformation($"Operation {operationId}: Unsubscribe subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}.");
            // Soft delete the subscription from db
            subscription.OperationId        = operationId;
            subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending);
            subscription.ProvisioningType   = nameof(ProvisioningType.Unsubscribe);
            subscription.LastUpdatedTime    = DateTime.UtcNow;

            using (var transaction = await _context.BeginTransactionAsync())
            {
                var subscriptionMeterUsages = await _context.SubscriptionCustomMeterUsages.Where(s => s.IsEnabled && s.SubscriptionId == subscriptionId).ToListAsync();

                foreach (var usage in subscriptionMeterUsages)
                {
                    usage.UnsubscribedTime = subscription.LastUpdatedTime.Value;
                    _context.SubscriptionCustomMeterUsages.Update(usage);
                }

                await _context._SaveChangesAsync();

                _context.Subscriptions.Update(subscription);
                await _context._SaveChangesAsync();

                transaction.Commit();
            }
            _logger.LogInformation($"Operation {operationId}: Subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is unsubscribed.");

            return(subscription);
        }
Example #5
0
        /// <summary>
        /// Delete data from a subscription
        /// </summary>
        /// <param name="subscriptionId">the subscription id</param>
        /// <returns>Purged subscription</returns>
        public async Task <Subscription> DeleteDataAsync(Guid subscriptionId)
        {
            Subscription subscription;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscription = await GetAsync(subscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            if (subscription == null)
            {
                throw new NotSupportedException($"Subscription {subscriptionId} doesn't exist or you don't have permission to access it.");
            }

            if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb(), invalidProvisioningState: true));
            }

            if (!subscription.Status.Equals(nameof(FulfillmentState.Unsubscribed)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.DeleteData.ToVerb(), requiredFulfillmentState: nameof(FulfillmentState.Unsubscribed)));
            }

            _logger.LogInformation($"Delete data for subscription {subscriptionId}.");
            subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending);
            subscription.ProvisioningType   = nameof(ProvisioningType.DeleteData);
            subscription.LastUpdatedTime    = DateTime.UtcNow;

            _context.Subscriptions.Update(subscription);
            await _context._SaveChangesAsync();

            _logger.LogInformation($"Data deleted for subscription {subscriptionId}.");
            return(subscription);
        }
Example #6
0
        /// <summary>
        /// Reinstate the subscription
        /// </summary>
        /// <param name="subscriptionId"></param>
        /// <returns></returns>
        public async Task <Subscription> ReinstateAsync(Guid subscriptionId, Guid operationId)
        {
            Subscription subscription;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscription = await GetAsync(subscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            if (!subscription.ProvisioningStatus.Equals(nameof(ProvisioningState.Succeeded)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb(), invalidProvisioningState: true));
            }

            if (!subscription.Status.Equals(nameof(FulfillmentState.Suspended)))
            {
                throw new NotSupportedException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscriptionId, SubscriptionAction.Reinstate.ToVerb(), requiredFulfillmentState: nameof(FulfillmentState.Suspended)));
            }
            _logger.LogInformation($"Operation {operationId}: Reinstate subscription {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName}.");

            // Soft delete the subscription from db
            subscription.OperationId        = operationId;
            subscription.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending);
            subscription.ProvisioningType   = nameof(ProvisioningType.Reinstate);
            subscription.LastUpdatedTime    = DateTime.UtcNow;

            _context.Subscriptions.Update(subscription);
            await _context._SaveChangesAsync();

            _logger.LogInformation($"Operation {operationId}: Reinstate {subscriptionId} with offer {subscription.OfferName} and plan {subscription.PlanName} is suspended.");

            return(subscription);
        }
Example #7
0
        /// <summary>
        /// Updates a subscription.
        /// </summary>
        /// <param name="subscription">The updated subscription.</param>
        /// <returns>The updated subscription.</returns>
        public async Task <Subscription> UpdateAsync(Subscription subscription, Guid operationId)
        {
            if (subscription is null)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Subscription).Name),
                                                      UserErrorCode.PayloadNotProvided);
            }
            _logger.LogInformation(LoggingUtils.ComposeUpdateResourceMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName, payload: JsonSerializer.Serialize(subscription)));
            var newPlanName = subscription.PlanName;
            var newQuantity = subscription.Quantity;

            Subscription subscriptionDb;

            try
            {
                // Get the subscription that matches the subscriptionId provided
                subscriptionDb = await GetAsync(subscription.SubscriptionId);
            }
            catch (Exception)
            {
                throw new LunaBadRequestUserException(LoggingUtils.ComposeSubscriptionActionErrorMessage(subscription.SubscriptionId, SubscriptionAction.Update.ToVerb()), UserErrorCode.ResourceNotFound);
            }

            CheckSubscriptionInReadyState(subscriptionDb);

            // Get the offer and plan associated with the subscriptionId provided
            var offer = await _context.Offers.FindAsync(subscriptionDb.OfferId);

            var plan = await _context.Plans.FindAsync(subscriptionDb.PlanId);

            if (newPlanName != plan.PlanName && subscriptionDb.Quantity != newQuantity)
            {
                throw new ArgumentException("Cannot update plan and quantity at the same time.");
            }

            // Check if the plan has been upgraded or downgraded
            if (newPlanName != plan.PlanName)
            {
                _logger.LogInformation($"Updating subscription {subscription.SubscriptionId} from plan {plan.PlanName} to {newPlanName}.");
                // Get the new plan to change to
                var newPlan = await _planService.GetAsync(offer.OfferName, newPlanName);

                // Update the FK to the new plan
                subscription.OperationId          = operationId;
                subscriptionDb.PlanId             = newPlan.Id;
                subscriptionDb.ProvisioningStatus = nameof(ProvisioningState.ArmTemplatePending);
                subscriptionDb.ProvisioningType   = nameof(ProvisioningType.Update);
            }
            else if (subscriptionDb.Quantity != subscription.Quantity)
            {
                _logger.LogInformation($"Updating subscription {subscription.SubscriptionId} from quantity {subscriptionDb.Quantity} to {subscription.Quantity}");
                subscriptionDb.Quantity = newQuantity;
                //TODO: what to do?
            }

            // Set the updated time
            subscriptionDb.LastUpdatedTime = DateTime.UtcNow;

            // Update subscriptionDb values and save changes in db
            _context.Subscriptions.Update(subscriptionDb);
            await _context._SaveChangesAsync();

            _logger.LogInformation(LoggingUtils.ComposeResourceUpdatedMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName));

            return(subscriptionDb);
        }