예제 #1
0
 /// <summary>
 /// Reports the status to digital fulfillment system. For each file, if
 ///  => If [titleid!=empty && airingid==* && mediaid==*]
 ///         do not report anything
 ///  => If [titleid==empty && airingid!=empty && mediaid!=empty]
 ///         report by AiringId
 ///  => If [titleid==empty && airingid==empty && mediaid!=empty]
 ///         For each airing/asset for the mediaid, report its status
 ///  => If [titleid==empty && airingid==empty && mediaid==empty]
 ///         do not report anything
 /// </summary>
 /// <param name="files">The files.</param>
 /// <param name="statusMessage">The status message.</param>
 private void ReportStatusToMonitoringSystem(List <RQModel.FileViewModel> files, String statusMessage)
 {
     foreach (var file in files)
     {
         if (!String.IsNullOrEmpty(file.AiringId))
         {
             reporter.Report(file.AiringId, airingSvc.IsAiringExists(file.AiringId), statusMessage);
         }
         else if (!String.IsNullOrWhiteSpace(file.MediaId))
         {
             // Report to all assets under mediaid
             List <BLAiringModel.Airing> airings = airingSvc.GetByMediaId(file.MediaId).ToList();
             foreach (var airing in airings)
             {
                 reporter.Report(airing.AssetId, true, statusMessage);
             }
         }
         else if (file.TitleId.HasValue)
         {
             // Report to all assets under titleid
             List <BLAiringModel.Airing> airings = airingSvc.GetNonExpiredBy(file.TitleId.Value, DateTime.MinValue).ToList();
             foreach (var airing in airings)
             {
                 reporter.Report(airing.AssetId, true, statusMessage);
             }
         }
     }
 }
예제 #2
0
        public EncodingFileContentValidator(IAiringService airingSvc)
        {
            _airingSvc = airingSvc;

            // Verify if the main field: media-id is provided
            RuleFor(request => request.MediaId).
            NotEmpty().WithMessage("media-id required");

            // Verify that airing id is provided
            // Verify that the given AiringId exist
            Func <String, bool> airingIdExistRule = new Func <String, bool>((airingId) =>
            {
                if (String.IsNullOrEmpty(airingId))
                {
                    return(false);
                }

                return((_airingSvc.GetBy(airingId) == null) ? false : true);
            });

            RuleFor(c => c.AiringId)
            .Must(airingIdExistRule)
            .WithMessage("AiringId {0} doesn't exist", c => c.AiringId);


            //Verify that required data points are provided
            RuleFor(request => request.RootId).NotEmpty().WithMessage("root-id required");

            // Only apply the remaining validation if mediaid is provided
            When(x => !String.IsNullOrWhiteSpace(x.MediaId), () =>
            {
                // Verify that the given MediaId exist
                Func <String, bool> mediaIdExistRule = new Func <String, bool>((mediaId) =>
                {
                    return((_airingSvc.GetByMediaId(mediaId).IsNullOrEmpty()) ? false : true);
                });
                RuleFor(c => c.MediaId)
                .Must(mediaIdExistRule)
                .WithMessage("MediaId {0} doesn't exist", c => c.MediaId);

                // Verify that outputs property is provided
                RuleFor(c => c.MediaCollection)
                .NotEmpty()
                .WithMessage("Output property required and cannot be empty");

                // Apply content segment validation if output is provided
                When(x => !x.MediaCollection.IsNullOrEmpty(), () =>
                {
                    // Apply content segment validation rule
                    SetContentSegmentsRule();
                });
            });
        }
예제 #3
0
        /// <summary>
        // Send notifications to all subscribed consumers
        /// </summary>
        private void SendNotification(BLFileModel.File file)
        {
            List <string> statusList = file.Contents.FirstOrDefault().MediaCollection.Select(c => c.Type.Replace("_", "").Replace("-", "").ToUpper()).ToList();
            List <Airing> airingIds  = _airingSvc.GetByMediaId(file.MediaId);

            // For each airing associated with the media id, do the following
            foreach (Airing airing in airingIds)
            {
                // Persist statuses
                foreach (string status in statusList)
                {
                    airing.Status[status] = true;
                }

                // Finally, persist the airing data
                _airingSvc.Save(airing, false, true);

                // Retrieve full list of notification changes
                List <ChangeNotification> notifications = GetNotificationList(airing, statusList);

                // Update the status notification
                _airingSvc.CreateNotificationForStatusChange(airing.AssetId, notifications);
            }
        }
예제 #4
0
        public AiringStatusRoutes(
            IAiringService airingSvc,
            IStatusSerivce statusService,
            IQueueService queueService,
            Serilog.ILogger logger
            )
            : base("v1")
        {
            this.RequiresAuthentication();

            _statusService = statusService;

            #region "POST Operations"


            Post("/airingstatus/{airingid}", _ =>
            {
                // Verify that the user has permission to POST
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());

                var airingId = (string)_.airingid;

                try
                {
                    if (!airingSvc.IsAiringExists(airingId))
                    {
                        var airingErrorMessage = string.IsNullOrWhiteSpace(airingId) ?
                                                 "AiringId is required." : "Provided AiringId does not exists or expired.";

                        // Return's NOT found status if airing not exists in current collection.
                        return(Negotiate.WithModel(airingErrorMessage)
                               .WithStatusCode(!string.IsNullOrWhiteSpace(airingId) ? HttpStatusCode.NotFound : HttpStatusCode.BadRequest));
                    }

                    // Bind POST request to data contract
                    var request = this.Bind <VMAiringRequestModel.AiringStatusRequest>();

                    //Validates the airing status request
                    var validationResults = ValidateRequest(request);

                    if (validationResults.Any())
                    {
                        //returns validation results if there is any
                        return(Negotiate.WithModel(validationResults)
                               .WithStatusCode(HttpStatusCode.BadRequest));
                    }

                    var airing = airingSvc.GetBy(airingId, AiringCollection.CurrentCollection);


                    //Updates the airing status with the POST request
                    foreach (var status in request.Status)
                    {
                        airing.Status[status.Key] = status.Value;
                    }

                    //Set the user name who updates the status
                    airing.UserName = Context.User().UserName;

                    // get all active queues
                    var statusQueues = queueService.GetByStatus(true);

                    // Finally, persist the airing data
                    airingSvc.Save(airing, false, true);

                    //update the status notification
                    airingSvc.CreateNotificationForStatusChange(airing.AssetId, ResetDeliveryQueue(statusQueues, airing));

                    return(new { Result = "Successfully updated the airing status." });
                }
                catch (Exception e)
                {
                    logger.Error(e, "Failure ingesting status to airing. Airingid:{@airingId}", airingId);
                    throw;
                }
            });


            Post("/airingstatus/mediaId/{mediaid}", _ =>
            {
                // Verify that the user has permission to POST
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());

                var mediaId = (string)_.mediaid;

                if (string.IsNullOrWhiteSpace(mediaId))
                {
                    return(Negotiate.WithModel("MediaId is required.")
                           .WithStatusCode(HttpStatusCode.BadRequest));
                }

                var airingsByMediaId = airingSvc.GetByMediaId(mediaId);

                try
                {
                    // Bind POST request to data contract
                    var request = this.Bind <VMAiringRequestModel.AiringStatusRequest>();

                    //Validates the airing status request
                    var validationResults = ValidateRequest(request);

                    if (validationResults.Any())
                    {
                        //returns validation results if there is any
                        return(Negotiate.WithModel(validationResults)
                               .WithStatusCode(HttpStatusCode.BadRequest));
                    }

                    //Updates the airing status with the POST request

                    foreach (var airing in airingsByMediaId)
                    {
                        foreach (var status in request.Status)
                        {
                            airing.Status[status.Key] = status.Value;
                        }

                        //Set the user name who updates the status
                        airing.UserName = Context.User().UserName;

                        // get all active queues
                        var statusQueues = queueService.GetByStatus(true);

                        // Finally, persist the airing data
                        airingSvc.Save(airing, false, true);

                        //update the status notification
                        airingSvc.CreateNotificationForStatusChange(airing.AssetId, ResetDeliveryQueue(statusQueues, airing));

                        logger.Information("Successfully updated the airing status. AiringId : {AiringId}", airing.AssetId);
                    }

                    return(new { Result = "Successfully updated the airings status." });
                }
                catch (Exception e)
                {
                    logger.Error(e, "Failure ingesting status to airings by mediaid. Mediaid:{@mediaId}", mediaId);
                    throw;
                }
            });


            #endregion
        }
예제 #5
0
        public AiringRoutes(
            IIdDistributor airingIdDistributorSvc,
            IAiringIdService airingIdSvc,
            IAiringService airingSvc,
            IReportingService reporterSvc,
            IProductService productSvc,
            AiringValidator _validator,
            IQueueService queueSvc,
            Serilog.ILogger logger,
            IDestinationService destinationSvc
            )
            : base("v1")
        {
            this.RequiresAuthentication();



            #region "GET Operations"
            Get("/airing/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var options = GetOptionsFromQueryString();

                // These timers are added for instrumentation and will be removed
                // in the future
                Dictionary <string, object> routeStats = new Dictionary <string, object>();
                long start = Stopwatch.GetTimestamp();
                var airing = airingSvc.GetBy((string)_.airingId);
                routeStats.Add("rtAiring_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                var user = Context.User();
                FilterDestinations(airing, user.Destinations.ToList());
                ValidateRequest(airing, user.Brands);

                var airingLong = airing.ToBusinessModel <BLAiringModel.Airing, BLAiringLongModel.Airing>();

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.File.ToString().ToLower()))
                {
                    airingSvc.AppendFile(ref airingLong);
                }
                routeStats.Add("appendFile_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Title.ToString().ToLower()))
                {
                    airingSvc.AppendTitle(ref airingLong);
                }
                routeStats.Add("appendTitle_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                if (options.Contains(Appenders.Series.ToString().ToLower()) &&
                    (options.Contains(Appenders.File.ToString().ToLower())))
                {
                    airingSvc.AppendSeries(ref airingLong);
                }
                else if (options.Contains(Appenders.Series.ToString().ToLower()))
                {
                    airingSvc.AppendSeries(ref airingLong);
                    airingSvc.AppendFileBySeriesId(ref airingLong);
                }

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Destination.ToString().ToLower()))
                {
                    airingSvc.AppendDestinations(ref airingLong);
                }
                routeStats.Add("appendDestination_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Change.ToString().ToLower()))
                {
                    airingSvc.AppendChanges(ref airingLong);
                }
                routeStats.Add("appendChanges_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                // Append status information if requested
                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Status.ToString().ToLower()))
                {
                    airingSvc.AppendStatus(ref airingLong);
                }
                routeStats.Add("appendStatus_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Package.ToString().ToLower()))
                {
                    airingSvc.AppendPackage(ref airingLong, Request.Headers.Accept);
                }
                routeStats.Add("appendPackage_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Premiere.ToString().ToLower()))
                {
                    airingSvc.AppendPremiere(ref airingLong);
                }
                routeStats.Add("appendPremiere_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start = Stopwatch.GetTimestamp();
                if (options.Contains(Appenders.Version.ToString().ToLower()))
                {
                    airingSvc.AppendVersion(ref airingLong);
                }
                routeStats.Add("appendVersion_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                start     = Stopwatch.GetTimestamp();
                var model = airingLong.ToViewModel <BLAiringLongModel.Airing, VMAiringLongModel.Airing>();
                routeStats.Add("BLtoVM_ElapsedMS", GetElapsedMilliseconds(start, Stopwatch.GetTimestamp()));

                if (!options.Contains(Appenders.Package.ToString().ToLower()))
                {
                    model.Options.Packages = null;
                }

                routeStats.Add("context", "Instrumentation-GET-Airing-Route");
                routeStats.Add("requestMethod", this.Request.Method);
                routeStats.Add("path", this.Request.Path);
                logger.Information("Request -" + this.Request.Path + "{@info}", routeStats);

                return(model);
            });


            Get("/airings/titleId/{titleId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((int)_.titleId, DateTime.UtcNow)
                              .ToList();

                var user = Context.User();
                airings  = FilterDestinations(airings, user.Destinations.ToList());
                airings  = FilterBrands(airings, user.Brands.ToList());

                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/seriesId/{seriesId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((int)_.seriesId, DateTime.UtcNow, true)
                              .ToList();

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/mediaId/{mediaId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                List <BLAiringModel.Airing> airings;
                DateTime startDate;
                DateTime endDate;
                if ((Request.Query.ContainsKey("startDate")) && (Request.Query.ContainsKey("endDate")))
                {
                    // validate
                    ValidationResult results = new ValidationResult();
                    results = validateRequestDate(Request.Query["startDate"], Request.Query["endDate"]);
                    if (results.Errors.Any())  // Verify if there are any validation errors. If so, return error
                    {
                        return(Negotiate.WithModel(results.Errors.Select(c => c.ErrorMessage))
                               .WithStatusCode(HttpStatusCode.BadRequest));       // Return status
                    }
                    startDate = getDate(Request.Query["startDate"]);
                    endDate   = getDate(Request.Query["endDate"]);

                    if (startDate > endDate)
                    {
                        return(Negotiate.WithModel("Start date should be smaller than the end date")
                               .WithStatusCode(HttpStatusCode.PreconditionFailed));
                    }

                    airings = airingSvc.GetAiringsByMediaId((string)_.mediaId, startDate, endDate);
                }
                else
                {
                    airings = new List <BLAiringModel.Airing>(airingSvc.GetByMediaId((string)_.mediaId));
                }

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/destination/{destination}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                var airings = airingSvc
                              .GetNonExpiredBy((string)_.destination, DateTime.UtcNow)
                              .ToList();

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });

            Get("/airings/brand/{brand}/destination/{destination}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Get.Verb());
                List <BLAiringModel.Airing> airings = airingSvc
                                                      .GetBy((string)_.brand, (string)_.destination, (DateTime)Request.Query["startDate"],
                                                             (DateTime)Request.Query["endDate"], Request.Query["airingStatus"]);

                var user       = Context.User();
                airings        = FilterDestinations(airings, user.Destinations.ToList());
                airings        = FilterBrands(airings, user.Brands.ToList());
                var viewModels = airings.Select(a => a.ToViewModel <BLAiringModel.Airing, VMAiringShortModel.Airing>()).ToList();
                return(viewModels);
            });
            #endregion

            #region "POST Operations"
            Post("/airing/task", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request = this.Bind <TaskViewModel>();

                airingSvc.UpdateTask(request.AiringIds, request.Tasks);

                return(new
                {
                    request.AiringIds,
                    Message = "updated successfully"
                });
            });

            Post("/airing/send/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                if (!airingSvc.IsAiringExists((string)_.airingId))
                {
                    return(Negotiate.WithModel("airingId not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                airingSvc.PushToQueues(new List <string> {
                    (string)_.airingId
                });

                return(new
                {
                    AiringId = (string)_.airingId,
                    Message = "AiringId flagged for delivery for valid queues"
                });
            });

            Post("/airing/deliver/{airingId}", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                if (!airingSvc.IsAiringExists((string)_.airingId))
                {
                    return(Negotiate.WithModel("airingId not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                airingSvc.PushToQueues(new List <string> {
                    (string)_.airingId
                });

                return(new
                {
                    AiringId = (string)_.airingId,
                    Message = "AiringId flagged for delivery for valid queues"
                });
            });

            Post("/airing/send", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request   = this.Bind <QueuePushViewModel>();
                var queueName = queueSvc.GetByApiKey(request.QueueName);

                if (queueName == null)
                {
                    return(Negotiate.WithModel("Queue not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                if (!queueName.Active)
                {
                    return(Negotiate.WithModel("Inactive queue")
                           .WithStatusCode(HttpStatusCode.PreconditionFailed));
                }

                var invalidAirings = new List <string>();
                var validAiringIds = new List <string>();

                foreach (string airingId in request.AiringIds)
                {
                    if (!airingSvc.IsAiringExists(airingId))
                    {
                        invalidAirings.Add(airingId);
                    }
                    else
                    {
                        validAiringIds.Add(airingId);
                    }
                }

                if (validAiringIds.Any())
                {
                    airingSvc.PushToQueue(request.QueueName, request.AiringIds);
                }

                return(new
                {
                    validAiringIds = validAiringIds,
                    invalidAiringsIds = invalidAirings,
                    Message = "validAiringIds are flagged for delivery and delivered based on enabled options of the queue"
                });
            });

            Post("/airing/deliver", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());
                var request   = this.Bind <QueuePushViewModel>();
                var queueName = queueSvc.GetByApiKey(request.QueueName);

                if (queueName == null)
                {
                    return(Negotiate.WithModel("Queue not found")
                           .WithStatusCode(HttpStatusCode.NotFound));
                }

                if (!queueName.Active)
                {
                    return(Negotiate.WithModel("Inactive queue")
                           .WithStatusCode(HttpStatusCode.PreconditionFailed));
                }

                var invalidAirings = new List <string>();
                var validAiringIds = new List <string>();
                foreach (string airingId in request.AiringIds)
                {
                    if (!airingSvc.IsAiringExists(airingId))
                    {
                        invalidAirings.Add(airingId);
                    }
                    else
                    {
                        validAiringIds.Add(airingId);
                    }
                }

                if (validAiringIds.Any())
                {
                    airingSvc.PushToQueue(request.QueueName, request.AiringIds);
                }

                return(new
                {
                    AiringIds = validAiringIds,
                    invalidAiringsIds = invalidAirings,
                    Message = "AiringIds are flagged for delivery and delivered based on enabled options of the queue"
                });
            });

            Post("/airing/{prefix}", _ =>
            {
                // Verify that the user has permission to POST
                this.RequiresClaims(c => c.Type == HttpMethod.Post.Verb());

                var user = Context.User();

                // Bind POST request to data contract
                var request = this.Bind <VMAiringRequestModel.AiringRequest>();
                try
                {
                    // If the Airing provided in the request doesn't have an
                    // AiringId, create new one.
                    CurrentAiringId currentAiringId = null;
                    if (string.IsNullOrEmpty(request.AiringId))
                    {
                        currentAiringId  = airingIdDistributorSvc.Distribute((string)_.prefix);
                        request.AiringId = currentAiringId.AiringId;
                    }
                    else
                    {
                        try
                        {
                            var assetDetails = airingSvc.GetBy(request.AiringId);

                            if (assetDetails.SequenceNumber != 0)
                            {
                                currentAiringId = new CurrentAiringId
                                {
                                    SequenceNumber = assetDetails.SequenceNumber,
                                    BillingNumber  = new BillingNumber
                                    {
                                        Current = assetDetails.BillingNumber.Current,
                                        Lower   = assetDetails.BillingNumber.Lower,
                                        Upper   = assetDetails.BillingNumber.Upper
                                    }
                                };
                            }
                        }
                        catch (AiringNotFoundException e)
                        {
                            logger.Information("Airing released from other systems like turniverse");
                        }
                    }

                    // Translate data contract to airing business model
                    var airing = Mapper.Map <BLAiringModel.Airing>(request);

                    // validate
                    List <ValidationResult> results = new List <ValidationResult>();
                    results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.PostAiring.ToString()));

                    // Verify if there are any validation errors. If so, return error
                    if (results.Where(c => (!c.IsValid)).Count() > 0)
                    {
                        var message = results.Where(c => (!c.IsValid))
                                      .Select(c => c.Errors.Select(d => d.ErrorMessage));


                        logger.Error("Failure ingesting released asset: {AssetId}", new Dictionary <string, object>()
                        {
                            { "airingid", request.AiringId }, { "mediaid", airing.MediaId }, { "error", message }
                        });

                        // Return status
                        return(Negotiate.WithModel(message)
                               .WithStatusCode(HttpStatusCode.BadRequest));
                    }

                    // Now that the validation is succesful, proceed to
                    // persisting the data. But first, populate remaining
                    // properties for the airing business model.
                    if (currentAiringId != null)
                    {
                        airing.SequenceNumber        = currentAiringId.SequenceNumber;
                        airing.BillingNumber.Lower   = currentAiringId.BillingNumber.Lower;
                        airing.BillingNumber.Current = currentAiringId.BillingNumber.Current;
                        airing.BillingNumber.Upper   = currentAiringId.BillingNumber.Upper;
                    }
                    else
                    {
                        airing.BillingNumber = null;
                    }

                    airing.ReleaseOn = DateTime.UtcNow;
                    airing.UserName  = user.UserName; //Get the username

                    // If flight information is provided in the airing, create
                    // the corresponding product to destination mapping as defined
                    // in ODT
                    if (airing.Flights.SelectMany(f => f.Products).Any())
                    {
                        productSvc.ProductDestinationConverter(ref airing);
                        destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing);
                    }
                    else
                    {
                        // Retrieve destination related data - properties, deliverables and categories - lsand
                        // augment it to airing
                        destinationSvc.GetAiringDestinationRelatedData(ref airing);
                        destinationSvc.FilterDestinationPropertiesDeliverablesAndCategoriesAndTransformTokens(ref airing);
                    }

                    // If the versions exist, create a mediaid based on the
                    // provided version informtion,playlists and the network to which this
                    // asset/airing belongs
                    if (airing.Versions.Any())
                    {
                        airingSvc.AugmentMediaId(ref airing);
                    }


                    // Finally, persist the airing data
                    var savedAiring = airingSvc.Save(airing, request.Instructions.DeliverImmediately, true);

                    // If immediate deliver requested, force push the airing to the
                    // respective queues (based on: product=>destination=>queue relationship)
                    if (request.Instructions.DeliverImmediately)
                    {
                        airingSvc.PushToQueues(new List <string> {
                            savedAiring.AssetId
                        });
                    }

                    // Report status of this airing to monitoring system (digital fulfillment/logzio)
                    reporterSvc.Report(savedAiring, airingSvc.IsAiringExists(savedAiring.AssetId));
                    logger.Information("Successfully ingested released asset: {Asset}", GeneratePostAiringpropertiesForLogzIO(savedAiring, user));

                    // Return airing model
                    return(savedAiring.ToViewModel <BLAiringModel.Airing, VMAiringPostResponseModel.PostResponseAiring>());
                }
                catch (Exception e)
                {
                    logger.Error(e, "Failure ingesting released asset. AssetId:{@assetId}", request.AiringId);
                    throw e;
                }
            });

            #endregion

            #region "DELETE Operations"
            Delete("/airing", _ =>
            {
                this.RequiresClaims(c => c.Type == HttpMethod.Delete.Verb());
                var request = this.Bind <VMAiringRequestModel.AiringRequest>();
                var airing  = Mapper.Map <BLAiringModel.Airing>(request);

                // validate
                List <ValidationResult> results = new List <ValidationResult>();
                results.Add(_validator.Validate(airing, ruleSet: AiringValidationRuleSet.DeleteAiring.ToString()));

                // Verify if there are any validation errors. If so, return error
                if (results.Where(c => (!c.IsValid)).Count() > 0)
                {
                    // Return status
                    return(Negotiate.WithModel(results.Where(c => (!c.IsValid))
                                               .Select(c => c.Errors.Select(d => d.ErrorMessage)))
                           .WithStatusCode(HttpStatusCode.BadRequest));
                }


                var existingAiring = airingSvc.GetBy(airing.AssetId);
                ValidateRequest(existingAiring, Context.User().Brands);

                existingAiring.ReleaseBy = airing.ReleaseBy;
                existingAiring.ReleaseOn = DateTime.UtcNow;
                existingAiring.UserName  = Context.User().UserName;
                existingAiring.DeliveredTo.Clear();

                airingSvc.Delete(existingAiring);

                //Delete related packages of airing
                airingSvc.DeleteAiringMappedPackages(airing.AssetId);

                if (request.Instructions.DeliverImmediately)
                {
                    airingSvc.PushToQueues(new List <string> {
                        existingAiring.AssetId
                    });
                }

                reporterSvc.Report(existingAiring, false);

                return(new VMAiringLongModel.AiringMessage
                {
                    AiringId = airing.AssetId,
                    Message = "deleted successfully"
                });
            });
            #endregion
        }
예제 #6
0
        public FileValidator(IAiringService airingSvc)
        {
            this.airingSvc = airingSvc;

            // Apply video specific file validation
            RuleSet("Video", () =>
            {
                /// <summary>
                /// This validation checks if content segment(s) specified
                /// in the payload (# of entries in 'contents' array) should match that of the airing.
                /// That is, # of elements in 'contents' array should match with the # of elements in ‘version’ array for the airing
                /// </summary>
                int contentSegmentsCount = default(int);
                Func <FileViewModel, List <FileContentViewModel>, bool> contentSegmentsMatchRule = new Func <FileViewModel, List <FileContentViewModel>, bool>((request, filec) =>
                {
                    // If the mediaid is provided then do content segment validation using that. If the provided mediaid doesn't exist
                    // then set content segment count to 0
                    if (!request.MediaId.IsNullOrEmpty())
                    {
                        var query            = this.airingSvc.GetByMediaId(request.MediaId);
                        contentSegmentsCount = (query.IsNullOrEmpty()) ? 0 : query.FirstOrDefault().Versions.Count();
                        return((filec.Count() != contentSegmentsCount) ? false : true);
                    }
                    else if (!request.AiringId.IsNullOrEmpty())
                    {
                        try
                        {
                            var airing           = this.airingSvc.GetBy(request.AiringId);
                            contentSegmentsCount = (airing == null) ? 0 : airing.Versions.Count();
                            return((filec.Count() != contentSegmentsCount) ? false : true);
                        }
                        catch (Exception)
                        {
                            //if it throws and exception during Get, throw a validation error
                            return(false);
                        }
                    }
                    else if (request.TitleId.HasValue)
                    {
                        //var airing = airingSvc.GetNonExpiredBy(request.TitleId.Value, DateTime.MinValue);
                        //contentSegmentsCount = (airing == null) ? 0 : airing.FirstOrDefault().Versions.Count();
                        //return ((filec.Count() != contentSegmentsCount) ? false : true);
                        return(true);
                    }
                    // return false if none of the above criteria matches
                    return(false);
                });

                Func <FileViewModel, List <FileContentViewModel>, object> contentCount = new Func <FileViewModel, List <FileContentViewModel>, object>((request, filec) =>
                {
                    return(contentSegmentsCount);
                });

                // Verify that required data points are provided
                RuleFor(c => c)
                .Cascade(CascadeMode.StopOnFirstFailure)
                .Must(c => !(string.IsNullOrEmpty(c.AiringId) && string.IsNullOrEmpty(c.MediaId) && !c.TitleId.HasValue))
                .WithMessage("AiringId, MediaId or TitleId is required")
                .Must(c => OnlyOneTrue(new bool[]
                {
                    !string.IsNullOrEmpty(c.AiringId),
                    !string.IsNullOrEmpty(c.MediaId),
                    c.TitleId.HasValue
                }))
                .WithMessage("Either provide AiringId, MediaId or TitleId but not more than one")
                .DependentRules(dr =>
                {
                    // Apply the following validation if AiringId is not empty and MediaId is empty
                    dr.When(x => (!String.IsNullOrWhiteSpace(x.AiringId) && String.IsNullOrWhiteSpace(x.MediaId)), () =>
                    {
                        // Verify that the given AiringId exist
                        Func <String, bool> airingIdExistRule = new Func <String, bool>((airingId) =>
                        {
                            return(this.airingSvc.IsAiringExists(airingId));
                        });

                        dr.RuleFor(c => c.AiringId)
                        .Cascade(CascadeMode.StopOnFirstFailure)
                        .Must(airingIdExistRule)
                        .WithMessage("AiringId {0} doesn't exist/expired.", c => c.MediaId)
                        .DependentRules(o =>
                        {
                            o.RuleFor(ox => ox.Contents)
                            .Cascade(CascadeMode.StopOnFirstFailure)
                            .NotEmpty()
                            .WithMessage("Contents property required and cannot be empty when posting video payload by airing-id")
                            .Must(contentSegmentsMatchRule)
                            .WithMessage("Content segments provided in payload doesn't match with that of media/airing. Payload contains {0} content segments (# of items in 'contents' array), while media/airing contains {1} content segments",
                                         (request, mediac) => mediac.Count(),
                                         contentCount)
                            .DependentRules(ox =>
                            {
                                ox.RuleForEach(xo => xo.Contents)
                                .SetValidator(new FileContentValidator());
                            });
                        });
                    });
                    // Apply the following validation if MediaId is provided
                    dr.When(x => !String.IsNullOrWhiteSpace(x.MediaId), () =>
                    {
                        // Verify that the given MediaId exist
                        Func <String, bool> mediaIdExistRule = new Func <String, bool>((mediaId) =>
                        {
                            return((airingSvc.GetByMediaId(mediaId).IsNullOrEmpty()) ? false : true);
                        });

                        dr.RuleFor(c => c.MediaId)
                        .Cascade(CascadeMode.StopOnFirstFailure)
                        .Must(mediaIdExistRule)
                        .WithMessage("MediaId {0} doesn't exist", c => c.MediaId)
                        .DependentRules(oxx =>
                        {
                            oxx.RuleFor(ox => ox.Contents)
                            .Cascade(CascadeMode.StopOnFirstFailure)
                            .NotEmpty()
                            .WithMessage("Contents property required and cannot be empty when posting video payload by media-id")
                            .Must(contentSegmentsMatchRule)
                            .WithMessage("Content segments provided in payload doesn't match with that of media/airing. Payload contains {0} content segments (# of items in 'contents' array), while media/airing contains {1} content segments",
                                         (request, mediac) => mediac.Count(),
                                         contentCount)
                            .DependentRules(o =>
                            {
                                o.RuleForEach(xo => xo.Contents)
                                .SetValidator(new FileContentValidator());
                            });
                        });
                    });

                    // Apply the following validation if TitleId is provided
                    dr.When(x => x.TitleId.HasValue, () =>
                    {
                        // Verify that the given MediaId exist
                        Func <int, bool> titleIdExistRule = new Func <int, bool>((titleId) =>
                        {
                            //return (airingSvc.GetNonExpiredBy(titleId, DateTime.MinValue).IsNullOrEmpty()) ? false : true;
                            return(true);
                        });

                        dr.RuleFor(c => c.TitleId.Value)
                        .Cascade(CascadeMode.StopOnFirstFailure)
                        .Must(titleIdExistRule)
                        .WithMessage("TitleId {0} doesn't exist", c => c.TitleId.Value)
                        .DependentRules(oxx =>
                        {
                            oxx.RuleFor(ox => ox.Contents)
                            .Cascade(CascadeMode.StopOnFirstFailure)
                            .NotEmpty()
                            .WithMessage("Contents property required and cannot be empty when posting video payload by title-id")
                            .Must(contentSegmentsMatchRule)
                            .WithMessage("Content segments provided in payload doesn't match with that of media/airing. Payload contains {0} content segments (# of items in 'contents' array), while media/airing contains {1} content segments",
                                         (request, mediac) => mediac.Count(),
                                         contentCount)
                            .DependentRules(o =>
                            {
                                o.RuleForEach(xo => xo.Contents)
                                .SetValidator(new FileContentValidator());
                            });
                        });
                    });
                });
            });


            // Apply non-video specific file validation
            RuleSet("NonVideo", () =>
            {
                // Verify that TitleId is provided
                RuleFor(c => c)
                .Cascade(CascadeMode.StopOnFirstFailure)
                .Must(c => c.TitleId.HasValue)
                .WithMessage("Title Id Required")
                .Must(c => c.TitleId > 0)
                .WithMessage("Title Id must be greater than zero");

                RuleFor(c => c)
                .Must(c => String.IsNullOrEmpty(c.AiringId) && String.IsNullOrEmpty(c.MediaId))
                .WithMessage("Registering non video assets by Airing Id or Media Id not currently supported");


                // Verify that other required fileds are provided
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Path))
                .WithMessage("Path required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Name))
                .WithMessage("Name required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Type))
                .WithMessage("Type required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Domain))
                .WithMessage("Domain required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.AspectRatio))
                .WithMessage("Aspect ratio required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Category))
                .WithMessage("Category required");
                RuleFor(c => c)
                .Must(c => !String.IsNullOrEmpty(c.Match))
                .WithMessage("Match required");
            });
        }