private void SetSubscription(string callbackEndpoint, string uvid, Identity identity,
                                     Common.Services.Internal.Interfaces.Notification notification, List <KeyValuePair <string, string> > paramList)
        {
            VisSubscription newSub = new VisSubscription();

            newSub.CallbackEndpoint          = callbackEndpoint;
            newSub.MessageID                 = uvid;
            newSub.MessageType               = _messageTypeService.Get(x => x.Name.ToLower() == "rtz").First();
            newSub.SubscriberIdentity        = identity;
            newSub.TimeOfSubscriptionRequest = DateTime.UtcNow;
            newSub.IsAuthorized              = true;
            _subscriptionService.Insert(newSub);

            // Send message to new subscriber
            var message = _publishedMessageService.Get(x => x.MessageID == uvid).FirstOrDefault();

            if (message != null)
            {
                _publishedMessageService.SendMessage(System.Text.Encoding.Default.GetString(message.Message),
                                                     uvid, newSub.CallbackEndpoint,
                                                     new Identity {
                    Name = identity.Name, UID = identity.UID
                });
            }

            // Save to DB
            _context.SaveChanges();

            _logEventService.LogSuccess(EventNumber.VIS_subscribeToVoyagePlan_response, EventDataType.Other,
                                        paramList,
                                        newSub.MessageID);
        }
        public virtual Models.ResponseObj UploadVoyagePlan([FromBody] string voyagePlan, [FromUri] string deliveryAckEndPoint = null,
                                                           [FromUri] string callbackEndpoint = null)
        {
            log.Info("Incoming request to " + GetCurrentMethod());

            var messageType = _messageTypeService.Get(x => x.Name.ToLower() == "rtz").First();

            var request = Request;
            var headers = request.Headers;

            var paramList = new List <KeyValuePair <string, string> >();
            var param     = new KeyValuePair <string, string>("deliveryAckEndPoint", deliveryAckEndPoint);

            paramList.Add(param);
            param = new KeyValuePair <string, string>("callbackEndpoint", callbackEndpoint);
            paramList.Add(param);

            //First, validate that we have mandatory in-parameters
            var parser = RtzParserFactory.Create(voyagePlan);

            var uvid = parser.VesselVoyage;

            if (string.IsNullOrEmpty(uvid))
            {
                log.Debug("UVID is empty");

                throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required parameter UVID is missing.");
            }

            if (!FormatValidation.IsValidUvid(uvid))
            {
                throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Invalid UVID format");
            }

            if (voyagePlan == null)
            {
                log.Debug("VoyagePlan is empty");

                throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required parameter VoyagePlan is missing.");
            }

            try
            {
                if (string.IsNullOrEmpty(InstanceContext.CallerOrgId))
                {
                    log.Debug("Calling organization identity missing in header.");

                    throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required header incomingOrganizationId is missing.");
                }

                //Write to log table
                _logEventService.LogInfo(EventNumber.VIS_uploadVoyagePlan_request, EventDataType.RTZ, paramList, voyagePlan);
                // Get identity ether from internal id talbe or from id registry
                var identity = _identityService.GetCallerIdentity();

                var result = new UploadedMessage();
                result.AckDelivered        = false;
                result.DeliveryAckEndpoint = deliveryAckEndPoint;
                result.DeliveryAckReqested = string.IsNullOrEmpty(deliveryAckEndPoint) ? false : true;
                result.FetchedByShip       = false;
                result.FetchTime           = null;
                result.FromOrg             = identity;
                result.FromServiceId       = InstanceContext.CallerServiceId;
                result.Message             = Serialization.StrToByteArray(voyagePlan);
                result.MessageType         = _messageTypeService.Get(x => x.Name.ToLower() == "rtz").First();
                result.Notified            = false;
                result.ReceiveTime         = DateTime.UtcNow;
                result.MessageID           = uvid;
                result.CallbackEndpoint    = string.IsNullOrEmpty(callbackEndpoint) ? string.Empty : callbackEndpoint;

                _uploadedMessageService.InsertRTZ(result);

                //Save to DB
                _context.SaveChanges();

                //Notify STM module
                var notification = new Common.Services.Internal.Interfaces.Notification();
                notification.FromOrgName        = identity.Name;
                notification.FromOrgId          = identity.UID;
                notification.FromServiceId      = InstanceContext.CallerServiceId;
                notification.NotificationType   = EnumNotificationType.MESSAGE_WAITING;
                notification.Subject            = "New voyageplan uploaded.";
                notification.NotificationSource = EnumNotificationSource.VIS;

                var notified = _notificationService.Notify(notification);

                if (notified)
                {
                    _context.Entry(result).Reload();
                    result.Notified = true;
                    _uploadedMessageService.Update(result);
                }

                var responsObj = new ResponseObj("Success store message");

                //Save to DB
                _context.SaveChanges();

                _logEventService.LogSuccess(EventNumber.VIS_uploadVoyagePlan_response, EventDataType.Other, null,
                                            JsonConvert.SerializeObject(responsObj, Formatting.Indented));

                return(responsObj);
            }

            catch (HttpResponseException ex)
            {
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.VIS_uploadVoyagePlan_request, EventType.Error_internal, paramList,
                                          JsonConvert.SerializeObject(ex.Response, Formatting.Indented));
                throw;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.VIS_uploadVoyagePlan_request, EventType.Error_internal, paramList,
                                          ex.Message);

                string msg = "VIS internal server error. " + ex.Message;
                throw CreateHttpResponseException(HttpStatusCode.InternalServerError, msg);
            }
        }
        private GetVoyagePlanResponse GetPublishedVoyagePlans(Identity identity, List <KeyValuePair <string, string> > paramList,
                                                              string uvid = null, int?routeStatusInt = null)
        {
            bool accessToAnyUVID = false;

            var result = new Models.GetVoyagePlanResponse(DateTime.UtcNow);

            result.VoyagePlans = new List <Models.VoyagePlan>();
            List <PublishedRtzMessage> publishedVoyagePlans = null;

            //Get all published voyageplans based on parameter values
            if (uvid == null && routeStatusInt == null)
            {
                publishedVoyagePlans = _publishedMessageService.Get(x => (int)x.MessageStatus != 8).
                                       OrderByDescending(x => x.PublishTime).ToList();
            }
            else if (uvid != null && routeStatusInt == null)
            {
                publishedVoyagePlans = _publishedMessageService.Get(x => x.MessageID == uvid &&
                                                                    (int)x.MessageStatus != 8).
                                       OrderByDescending(x => x.PublishTime).ToList();
            }
            else if (uvid == null && routeStatusInt != null)
            {
                publishedVoyagePlans = _publishedMessageService.Get(x => (int)x.MessageStatus != 8 &&
                                                                    (int)x.MessageStatus == routeStatusInt).
                                       OrderByDescending(x => x.PublishTime).ToList();
            }
            else
            {
                publishedVoyagePlans = _publishedMessageService.Get(x => x.MessageID == uvid &&
                                                                    (int)x.MessageStatus == routeStatusInt).
                                       OrderByDescending(x => x.PublishTime).ToList();
            }

            //Need to loop in order to distinguish the VP's with no access from the ones with access
            if (publishedVoyagePlans != null && publishedVoyagePlans.Count() > 0)
            {
                foreach (var publishedVoyagePlan in publishedVoyagePlans)
                {
                    // Now look up if orgId is authorized to this voyageplan
                    var aclObject = _aclObjectService.Get(x => x.Subscriber.ID == identity.ID && x.MessageID == publishedVoyagePlan.MessageID);
                    if (aclObject == null || aclObject.Count() == 0)
                    {
                        //No access to this one, send notification to STM module
                        var msg = "Authorization failed: ACL";
                        log.Debug(msg);

                        //Notify STM Module
                        var notification = new Common.Services.Internal.Interfaces.Notification();
                        notification.FromOrgName        = identity.Name;
                        notification.FromOrgId          = identity.UID;
                        notification.FromServiceId      = InstanceContext.CallerServiceId;
                        notification.NotificationType   = EnumNotificationType.UNAUTHORIZED_REQUEST;
                        notification.Subject            = string.Format("Access denied for identity {0}.", identity.Name);
                        notification.NotificationSource = EnumNotificationSource.VIS;

                        _notificationService.Notify(notification);
                        _context.SaveChanges();

                        // Log error
                        _logEventService.LogError(EventNumber.VIS_getVoyagePlan_request, EventType.Error_authorization,
                                                  paramList, InstanceContext.CallerServiceId);
                        _context.SaveChanges();
                    }
                    else
                    {
                        accessToAnyUVID = true;
                        //Add it to response object
                        var rtzString = Serialization.ByteArrayToString(publishedVoyagePlan.Message);
                        var vp        = new Models.VoyagePlan(rtzString);
                        result.VoyagePlans.Add(vp);
                    }
                }
            }
            else
            {
                //We didn't find any voyageplans i.e. return not found
                throw CreateHttpResponseException(HttpStatusCode.NotFound, "Voyageplans not found");
            }

            //Final check to verify that we did return at least one VP
            if (!accessToAnyUVID)
            {
                throw CreateHttpResponseException(HttpStatusCode.Forbidden, "Authorization failed: ACL");
            }
            return(result);
        }
        public virtual Models.ResponseObj SubscribeToVoyagePlan([FromUri] string callbackEndpoint, [FromUri] string uvid = null)
        {
            log.Info("Incoming request to " + GetCurrentMethod());
            bool accessToAnyUVID = false;

            var responseObj = new Models.ResponseObj("Success storing subscription request.");

            var paramList = new List <KeyValuePair <string, string> >();
            var param     = new KeyValuePair <string, string>("uvid", uvid);

            paramList.Add(param);
            param = new KeyValuePair <string, string>("callbackEndpoint", callbackEndpoint);
            paramList.Add(param);

            try
            {
                if (string.IsNullOrEmpty(callbackEndpoint))
                {
                    log.Debug("Callback endpoint address is empty");

                    throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required parameter CallbackEndpoint is missing.");
                }
                if (string.IsNullOrEmpty(InstanceContext.CallerOrgId))
                {
                    log.Debug("Calling organization identity missing in header.");

                    throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required header incomingOrganizationId is missing.");
                }

                _logEventService.LogInfo(EventNumber.VIS_subscribeToVoyagePlan_request, EventDataType.None, paramList, null);
                // Get identity ether from internal id talbe or from id registry
                var identity = _identityService.GetCallerIdentity();

                //Set data for notification
                var notification = new Common.Services.Internal.Interfaces.Notification();
                notification.FromOrgName        = identity.Name;
                notification.FromOrgId          = identity.UID;
                notification.FromServiceId      = InstanceContext.CallerServiceId;
                notification.NotificationType   = EnumNotificationType.UNAUTHORIZED_REQUEST;
                notification.Subject            = "New subscription request.";
                notification.NotificationSource = EnumNotificationSource.VIS;

                #region No UVID
                if (string.IsNullOrEmpty(uvid))
                {
                    var voyagePlans = _publishedMessageService.Get(x => (int)x.MessageStatus != 8).
                                      OrderByDescending(x => x.PublishTime).ToList();

                    if (voyagePlans != null && voyagePlans.Count() > 0)
                    {
                        foreach (var voyagePlan in voyagePlans)
                        {
                            var aclObj = _aclObjectService.Get(x => x.Subscriber.ID == identity.ID && x.MessageID == voyagePlan.MessageID);
                            if (aclObj == null || aclObj.Count() == 0)
                            {
                                _notificationService.Notify(notification);
                                _context.SaveChanges();
                            }
                            else
                            {
                                accessToAnyUVID = true;

                                //check if sub already exists
                                var sub = _subscriptionService.Get(x => x.CallbackEndpoint == callbackEndpoint && x.MessageID == voyagePlan.MessageID && x.SubscriberIdentity.ID == identity.ID).FirstOrDefault();
                                if (sub == null)
                                {
                                    SetSubscription(callbackEndpoint, voyagePlan.MessageID, identity, notification, paramList);
                                }
                            }
                        }
                    }
                    if (!accessToAnyUVID)
                    {
                        throw CreateHttpResponseException(HttpStatusCode.Forbidden, "Authorization failed: ACL");
                    }
                }
                #endregion

                #region UVID
                else
                {
                    var sub = _subscriptionService.Get(x => x.CallbackEndpoint == callbackEndpoint && x.MessageID == uvid && x.SubscriberIdentity.ID == identity.ID).FirstOrDefault();
                    if (sub == null)
                    {
                        //Check if uvid exist
                        var vpCheck = _publishedMessageService.Get(x => x.MessageID == uvid).FirstOrDefault();
                        if (vpCheck == null)
                        {
                            string msg = string.Format("Voyageplan with UVID {0} does not exist.", uvid);
                            log.Debug(msg);

                            _notificationService.Notify(notification);
                            _context.SaveChanges();

                            throw CreateHttpResponseException(HttpStatusCode.NotFound, msg);
                        }
                        // Check if identity has access to UVID
                        var aclId = _aclObjectService.Get(a => a.Subscriber.UID == InstanceContext.CallerOrgId && a.MessageID == uvid).FirstOrDefault();
                        if (aclId == null)
                        {
                            string msg = string.Format("Access to UVID {0} failed for user {1}", uvid, InstanceContext.CallerOrgId);
                            log.Debug(msg);

                            _notificationService.Notify(notification);
                            _context.SaveChanges();

                            throw CreateHttpResponseException(HttpStatusCode.Forbidden, msg);
                        }
                        SetSubscription(callbackEndpoint, uvid, identity, notification, paramList);
                    }
                }

                #endregion

                return(responseObj);
            }
            catch (HttpResponseException ex)
            {
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.VIS_subscribeToVoyagePlan_request, EventType.Error_internal, paramList,
                                          JsonConvert.SerializeObject(ex.Response, Formatting.Indented));

                throw;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.VIS_subscribeToVoyagePlan_request, EventType.Error_internal, paramList,
                                          ex.Message);

                string msg = "VIS internal server error. " + ex.Message;
                throw CreateHttpResponseException(HttpStatusCode.InternalServerError, msg);;
            }
        }
        public virtual ResponseObj UploadPCMMessage([FromBody] string pcmMessageObject, [FromUri] string deliveryAckEndPoint = null)
        {
            log.Info("Incoming request to " + GetCurrentMethod());

            var    messageType = _messageTypeService.Get(x => x.Name.ToLower() == "pcm").First();
            var    parser      = new PcmParser(pcmMessageObject);
            string dataId      = parser.PcmMessageId;

            var errorMsgResponse = string.Empty;
            var request          = Request;
            var headers          = request.Headers;

            if (string.IsNullOrEmpty(pcmMessageObject))
            {
                log.Debug("PCM Message is empty");
                errorMsgResponse += "Required parameter pcmMessageObject is missing." + Environment.NewLine;

                throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required parameter pcmMessageObject is missing.");
            }

            var param     = new KeyValuePair <string, string>("deliveryAckEndPoint", deliveryAckEndPoint);
            var paramList = new List <KeyValuePair <string, string> >();

            paramList.Add(param);

            try
            {
                if (string.IsNullOrEmpty(InstanceContext.CallerOrgId))
                {
                    log.Debug("Calling organization identity missing in header.");
                    errorMsgResponse += "Calling organization identity missing in header." + Environment.NewLine;

                    throw CreateHttpResponseException(HttpStatusCode.BadRequest, "Required header incomingOrganizationId is missing.");
                }

                //Write to log table
                _logEventService.LogInfo(EventNumber.SPIS_uploadPCM_request, EventDataType.PCM, paramList, pcmMessageObject);

                // Get identity ether from internal id talbe or from id registry
                var identity = _identityService.GetCallerIdentity();

                var result = new UploadedMessage();
                result.AckDelivered        = false;
                result.DeliveryAckEndpoint = deliveryAckEndPoint;
                result.DeliveryAckReqested = string.IsNullOrEmpty(deliveryAckEndPoint) ? false : true;
                result.FetchedByShip       = false;
                result.FetchTime           = null;
                result.FromOrg             = identity;
                result.FromServiceId       = InstanceContext.CallerServiceId;
                result.Message             = Serialization.StrToByteArray(pcmMessageObject);
                result.MessageType         = messageType;
                result.Notified            = false;
                result.ReceiveTime         = DateTime.UtcNow;
                result.MessageID           = dataId;

                //Notify STM module
                var notification = new Common.Services.Internal.Interfaces.Notification();
                notification.FromOrgName        = identity.Name;
                notification.FromOrgId          = identity.UID;
                notification.FromServiceId      = InstanceContext.CallerServiceId;
                notification.NotificationType   = EnumNotificationType.MESSAGE_WAITING;
                notification.Subject            = "PCM message uploaded.";
                notification.NotificationSource = EnumNotificationSource.SPIS;

                result.Notified = _notificationService.Notify(notification);

                _uploadedMessageService.InsertPCM(result);
                var responsObj = new ResponseObj("Success store message");

                //Save to DB
                _context.SaveChanges();

                _logEventService.LogSuccess(EventNumber.SPIS_uploadPCM_response, EventDataType.None,
                                            paramList, JsonConvert.SerializeObject(responsObj, Formatting.Indented));

                return(responsObj);
            }

            catch (HttpResponseException ex)
            {
                var responseString = JsonConvert.SerializeObject(ex.Response, Formatting.Indented);
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.SPIS_uploadPCM_request, EventType.Error_internal,
                                          paramList, responseString);

                throw;
            }
            catch (DbEntityValidationException dbEx)
            {
                var           response = request.CreateResponse(HttpStatusCode.InternalServerError);
                StringBuilder sb       = new StringBuilder();
                foreach (var item in dbEx.EntityValidationErrors)
                {
                    sb.Append(item + " errors: ");
                    foreach (var i in item.ValidationErrors)
                    {
                        sb.Append(i.PropertyName + " : " + i.ErrorMessage);
                    }
                    sb.Append(Environment.NewLine);
                }
                string msg = "SPIS internal server error. " + dbEx.Message;

                _logEventService.LogError(EventNumber.SPIS_uploadPCM_request, EventType.Error_internal,
                                          paramList, dbEx.Message);
                log.ErrorFormat("Validation errors: {0}", sb.ToString());

                throw CreateHttpResponseException(HttpStatusCode.InternalServerError, sb.ToString());
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                _logEventService.LogError(EventNumber.SPIS_uploadPCM_request, EventType.Error_internal,
                                          paramList, ex.Message);

                string msg = "SPIS internal server error. " + ex.Message;
                throw CreateHttpResponseException(HttpStatusCode.InternalServerError, msg);
            }
        }