Пример #1
0
        //convert a simple POI to data and back again to fully populate all related properties, as submission may only have simple IDs for ref data etc
        private Model.ChargePoint PopulateFullPOI(Model.ChargePoint poi)
        {
            OCMEntities tempDataModel = new OCMEntities();
            var         poiData       = new Core.Data.ChargePoint();

            if (poi.ID > 0)
            {
                poiData = tempDataModel.ChargePoints.First(c => c.ID == poi.ID);
            }

            //convert simple poi to fully populated db version
            new POIManager().PopulateChargePoint_SimpleToData(poi, poiData, tempDataModel);

            //convert back to simple POI
            var modelPOI = Model.Extensions.ChargePoint.FromDataModel(poiData, false, false, true, true);

            //clear temp changes from the poi
            //dataModel.Entry(poiData).Reload();
            tempDataModel.Dispose();
            return(modelPOI);
        }
Пример #2
0
 public static Model.ChargePoint FromDataModel(Core.Data.ChargePoint source)
 {
     return(FromDataModel(source, false, false, false, true));
 }
Пример #3
0
        public static Model.ChargePoint FromDataModel(Core.Data.ChargePoint source, bool loadUserComments, bool loadMediaItems, bool loadMetadataValues, bool isVerboseMode)
        {
            if (source == null)
            {
                return(null);
            }

            var poi = new Model.ChargePoint();

            poi.ID   = source.ID;
            poi.UUID = source.UUID;

            //populate data provider info (full object or id only)
            if (isVerboseMode && source.DataProvider != null)
            {
                poi.DataProvider   = DataProvider.FromDataModel(source.DataProvider);
                poi.DataProviderID = source.DataProvider.ID;
            }
            else
            {
                poi.DataProviderID = source.DataProviderID;
            }

            poi.DataProvidersReference = source.DataProvidersReference;

            //populate Operator (full object or id only)
            if (isVerboseMode && source.Operator != null)
            {
                poi.OperatorInfo = OperatorInfo.FromDataModel(source.Operator);
                poi.OperatorID   = source.Operator.ID;
            }
            else
            {
                poi.OperatorID = source.OperatorID;
            }

            poi.OperatorsReference = source.OperatorsReference;

            //populate usage type (full object or id only)
            if (isVerboseMode && source.UsageType != null)
            {
                poi.UsageType   = UsageType.FromDataModel(source.UsageType);
                poi.UsageTypeID = source.UsageType.ID;
            }
            else
            {
                poi.UsageTypeID = source.UsageTypeID;
            }

            poi.UsageCost = source.UsageCost;

            //populate address info
            if (source.AddressInfo != null)
            {
                poi.AddressInfo = AddressInfo.FromDataModel(source.AddressInfo, isVerboseMode);
            }

            poi.NumberOfPoints  = source.NumberOfPoints;
            poi.GeneralComments = source.GeneralComments;

            poi.DatePlanned       = source.DatePlanned;
            poi.DateLastConfirmed = source.DateLastConfirmed;

            //populate status type (full object or id only)
            if (isVerboseMode && source.StatusType != null)
            {
                poi.StatusType   = StatusType.FromDataModel(source.StatusType);
                poi.StatusTypeID = source.StatusType.ID;
            }
            else
            {
                poi.StatusTypeID = source.StatusTypeID;
            }

            poi.DateLastStatusUpdate = source.DateLastStatusUpdate;
            poi.DataQualityLevel     = source.DataQualityLevel;
            poi.DateCreated          = source.DateCreated;

            //populate submission status type (full object or id only)
            if (isVerboseMode && source.SubmissionStatusType != null)
            {
                poi.SubmissionStatus       = SubmissionStatusType.FromDataModel(source.SubmissionStatusType);
                poi.SubmissionStatusTypeID = source.SubmissionStatusType.ID;
            }
            else
            {
                poi.SubmissionStatusTypeID = source.SubmissionStatusTypeID;
            }

            poi.Connections = new List <Model.ConnectionInfo>();
            foreach (var conn in source.Connections)
            {
                poi.Connections.Add(ConnectionInfo.FromDataModel(conn, isVerboseMode));
            }

            //loadUserComments = true;
            //loadMetadataValues = true;
            //loadMediaItems = true;

            //optionally load user comments
            if (loadUserComments)
            {
                foreach (var comment in source.UserComments.OrderByDescending(cm => cm.DateCreated))
                {
                    if (poi.UserComments == null)
                    {
                        poi.UserComments = new List <Model.UserComment>();
                    }
                    Model.UserComment com = UserComment.FromDataModel(comment, isVerboseMode);
                    poi.UserComments.Add(com);
                }
            }

            if (loadMediaItems)
            {
                foreach (var mediaItem in source.MediaItems)
                {
                    if (poi.MediaItems == null)
                    {
                        poi.MediaItems = new List <Model.MediaItem>();
                    }
                    poi.MediaItems.Add(MediaItem.FromDataModel(mediaItem));
                }
            }

            if (loadMetadataValues)
            {
                foreach (var metadataValue in source.MetadataValues)
                {
                    if (poi.MetadataValues == null)
                    {
                        poi.MetadataValues = new List <Model.MetadataValue>();
                    }
                    poi.MetadataValues.Add(MetadataValue.FromDataModel(metadataValue));
                }
            }
            return(poi);
        }
Пример #4
0
 public static Model.ChargePoint FromDataModel(Core.Data.ChargePoint source, Model.CoreReferenceData refData)
 {
     return(FromDataModel(source, false, false, false, true, refData));
 }
Пример #5
0
        public static Model.ChargePoint FromDataModel(Core.Data.ChargePoint source, bool loadUserComments, bool loadMediaItems, bool loadMetadataValues, bool isVerboseMode, Model.CoreReferenceData refData)
        {
            if (source == null)
            {
                return(null);
            }

            var poi = new Model.ChargePoint();

            poi.ID   = source.Id;
            poi.UUID = source.Uuid;

            //populate data provider info (full object or id only)
            if (isVerboseMode && source.DataProviderId != null)
            {
                poi.DataProvider   = refData.DataProviders.FirstOrDefault(i => i.ID == source.DataProviderId) ?? DataProvider.FromDataModel(source.DataProvider);
                poi.DataProviderID = source.DataProviderId;
            }
            else
            {
                poi.DataProviderID = source.DataProviderId;
            }

            poi.DataProvidersReference = source.DataProvidersReference;

            //populate Operator (full object or id only)
            if (isVerboseMode && source.OperatorId != null)
            {
                poi.OperatorInfo = refData.Operators.FirstOrDefault(i => i.ID == source.OperatorId) ?? OperatorInfo.FromDataModel(source.Operator);
                poi.OperatorID   = source.OperatorId;
            }
            else
            {
                poi.OperatorID = source.OperatorId;
            }

            poi.OperatorsReference = source.OperatorsReference;

            //populate usage type (full object or id only)
            if (isVerboseMode && source.UsageTypeId != null)
            {
                poi.UsageType   = refData.UsageTypes.FirstOrDefault(i => i.ID == source.UsageTypeId) ?? UsageType.FromDataModel(source.UsageType);
                poi.UsageTypeID = source.UsageTypeId;
            }
            else
            {
                poi.UsageTypeID = source.UsageTypeId;
            }

            poi.UsageCost = source.UsageCost;

            //populate address info
            if (source.AddressInfoId != null || source.AddressInfo != null)
            {
                poi.AddressInfo = AddressInfo.FromDataModel(source.AddressInfo, isVerboseMode);
            }

            poi.NumberOfPoints  = source.NumberOfPoints;
            poi.GeneralComments = source.GeneralComments;

            poi.DatePlanned       = source.DatePlanned;
            poi.DateLastConfirmed = source.DateLastConfirmed;

            //populate status type (full object or id only)
            if (isVerboseMode && source.StatusTypeId != null)
            {
                poi.StatusType   = refData.StatusTypes.FirstOrDefault(i => i.ID == source.StatusTypeId) ?? StatusType.FromDataModel(source.StatusType);
                poi.StatusTypeID = source.StatusTypeId;
            }
            else
            {
                poi.StatusTypeID = source.StatusTypeId;
            }

            poi.DateLastStatusUpdate = source.DateLastStatusUpdate;
            poi.DataQualityLevel     = source.DataQualityLevel;
            poi.DateCreated          = source.DateCreated;

            //populate submission status type (full object or id only)
            if (isVerboseMode && source.SubmissionStatusTypeId != null)
            {
                poi.SubmissionStatus       = refData.SubmissionStatusTypes.FirstOrDefault(i => i.ID == source.SubmissionStatusTypeId) ?? SubmissionStatusType.FromDataModel(source.SubmissionStatusType);
                poi.SubmissionStatusTypeID = source.SubmissionStatusTypeId;
            }
            else
            {
                poi.SubmissionStatusTypeID = source.SubmissionStatusTypeId;
            }

            poi.Connections = new List <Model.ConnectionInfo>();
            foreach (var conn in source.ConnectionInfoes)
            {
                poi.Connections.Add(ConnectionInfo.FromDataModel(conn, isVerboseMode, refData));
            }

            //loadUserComments = true;
            //loadMetadataValues = true;
            //loadMediaItems = true;

            //optionally load user comments
            if (loadUserComments)
            {
                foreach (var comment in source.UserComments.OrderByDescending(cm => cm.DateCreated))
                {
                    if (poi.UserComments == null)
                    {
                        poi.UserComments = new List <Model.UserComment>();
                    }
                    Model.UserComment com = UserComment.FromDataModel(comment, isVerboseMode, refData);
                    poi.UserComments.Add(com);
                }
            }

            if (loadMediaItems)
            {
                foreach (var mediaItem in source.MediaItems.OrderByDescending(cm => cm.DateCreated))
                {
                    if (poi.MediaItems == null)
                    {
                        poi.MediaItems = new List <Model.MediaItem>();
                    }
                    poi.MediaItems.Add(MediaItem.FromDataModel(mediaItem));
                }
            }

            if (loadMetadataValues)
            {
                foreach (var metadataValue in source.MetadataValues)
                {
                    if (poi.MetadataValues == null)
                    {
                        poi.MetadataValues = new List <Model.MetadataValue>();
                    }
                    poi.MetadataValues.Add(MetadataValue.FromDataModel(metadataValue));
                }
            }

            //mapping level of detail (priority level, lower is higher priority)
            poi.LevelOfDetail = source.LevelOfDetail;
            return(poi);
        }
Пример #6
0
        public void ProcessEditQueueItem(int id, bool publishEdit, int userId)
        {
            //check current user is authorized to approve edits

            //prepare poi details

            var queueItem = DataModel.EditQueueItems.FirstOrDefault(e => e.ID == id);

            if (queueItem != null && queueItem.IsProcessed == false)
            {
                if (queueItem.EntityType.ID == (int)StandardEntityTypes.POI)
                {
                    //processing a POI add/edit

                    if (publishEdit)
                    {
                        //get diff between previous and edit

                        POIManager        poiManager = new POIManager();
                        Model.ChargePoint poiA       = DeserializePOIFromJSON(queueItem.PreviousData);
                        Model.ChargePoint poiB       = DeserializePOIFromJSON(queueItem.EditData);

                        bool poiUpdateRequired = false;

                        if (poiA != null)
                        {
                            //this is an edit, load the latest version of the POI as version 'A'
                            poiA = poiManager.Get(poiA.ID);
                            if (poiManager.HasDifferences(poiA, poiB))
                            {
                                poiUpdateRequired = true;
                            }
                        }

                        //save poi update
                        var poiData = new Core.Data.ChargePoint();

                        //if its an edit, load the original details before applying the change
                        if (poiUpdateRequired)
                        {
                            //updates to externally provided POIs require old version to be superseded (archived) first
                            if (poiA != null && poiA.DataProviderID != (int)StandardDataProviders.OpenChargeMapContrib)
                            {
                                poiManager.SupersedePOI(DataModel, poiA, poiB);
                            }
                            poiData = DataModel.ChargePoints.First(c => c.ID == poiB.ID);
                        }

                        //set/update cp properties
                        poiManager.PopulateChargePoint_SimpleToData(poiB, poiData, DataModel);

                        //set status type to published if previously unset
                        if (poiData.SubmissionStatusTypeID == null)
                        {
                            poiData.SubmissionStatusType = DataModel.SubmissionStatusTypes.First(s => s.ID == (int)StandardSubmissionStatusTypes.Submitted_Published);
                        }

                        poiData.DateLastStatusUpdate = DateTime.UtcNow;

                        //publish edit
                        DataModel.SaveChanges();

                        //attribute submitter with reputation points
                        if (queueItem.UserID != null)
                        {
                            new UserManager().AddReputationPoints((int)queueItem.UserID, 1);
                        }
                    }

                    //update edit queue item as processed
                    queueItem.IsProcessed     = true;
                    queueItem.ProcessedByUser = DataModel.Users.FirstOrDefault(u => u.ID == userId);
                    queueItem.DateProcessed   = DateTime.UtcNow;
                    DataModel.SaveChanges();

                    CacheManager.RefreshCachedPOIList();
                }
            }
        }
Пример #7
0
        private static void SendNewPOISubmissionNotification(Model.ChargePoint poi, Model.User user, Core.Data.ChargePoint cpData)
        {
            try
            {
                string approvalStatus = cpData.SubmissionStatusType.Title;

                //send notification
                NotificationManager notification = new NotificationManager();
                Hashtable           msgParams    = new Hashtable();
                msgParams.Add("Description", "OCM-" + cpData.Id + " : " + poi.AddressInfo.Title);
                msgParams.Add("SubmissionStatusType", approvalStatus);
                msgParams.Add("ItemURL", "https://openchargemap.org/site/poi/details/" + cpData.Id);
                msgParams.Add("ChargePointID", cpData.Id);
                msgParams.Add("UserName", user != null ? user.Username : "******");
                msgParams.Add("MessageBody",
                              "New Location " + approvalStatus + " OCM-" + cpData.Id + " Submitted: " +
                              poi.AddressInfo.Title);

                notification.PrepareNotification(NotificationType.LocationSubmitted, msgParams);

                //notify default system recipients
                notification.SendNotification(NotificationType.LocationSubmitted);
            }
            catch (Exception)
            {
                ;
                ; //failed to send notification
            }
        }
Пример #8
0
        /// <summary>
        /// Consumers should prepare a new/updated ChargePoint with as much info populated as possible
        /// </summary>
        /// <param name="submission">ChargePoint info for submission, if ID and UUID set will be treated as an update</param>
        /// <returns>false on error or not enough data supplied</returns>
        public int PerformPOISubmission(Model.ChargePoint updatedPOI, Model.User user)
        {
            try
            {
                var  poiManager             = new POIManager();
                bool enableEditQueueLogging = bool.Parse(ConfigurationManager.AppSettings["EnableEditQueue"]);
                bool isUpdate = false;
                bool userCanEditWithoutApproval = false;
                bool isSystemUser = false;

                //if user signed in, check if they have required permission to perform an edit/approve (if required)
                if (user != null)
                {
                    if (user.ID == (int)StandardUsers.System)
                    {
                        isSystemUser = true;
                    }

                    //if user is system user, edits/updates are not recorded in edit queue
                    if (isSystemUser)
                    {
                        enableEditQueueLogging = false;
                    }

                    userCanEditWithoutApproval = POIManager.CanUserEditPOI(updatedPOI, user);
                }

                var dataModel = new Core.Data.OCMEntities();

                //if poi is an update, validate if update can be performed
                if (updatedPOI.ID > 0 && !String.IsNullOrEmpty(updatedPOI.UUID))
                {
                    if (dataModel.ChargePoints.Any(c => c.ID == updatedPOI.ID && c.UUID == updatedPOI.UUID))
                    {
                        //update is valid poi, check if user has permission to perform an update
                        isUpdate = true;
                        if (userCanEditWithoutApproval)
                        {
                            AllowUpdates = true;
                        }
                        if (!AllowUpdates && !enableEditQueueLogging)
                        {
                            return(-1); //valid update requested but updates not allowed
                        }
                    }
                    else
                    {
                        //update does not correctly identify an existing poi
                        return(-1);
                    }
                }

                //validate if minimal required data is present
                if (updatedPOI.AddressInfo.Title == null || updatedPOI.AddressInfo.Country == null)
                {
                    return(-1);
                }

                //convert to DB version of POI and back so that properties are fully populated
                updatedPOI = PopulateFullPOI(updatedPOI);
                Model.ChargePoint oldPOI = null;

                if (updatedPOI.ID > 0)
                {
                    //get json snapshot of current cp data to store as 'previous'
                    oldPOI = poiManager.Get(updatedPOI.ID);
                }

                //if user cannot edit directly, add to edit queue for approval
                var editQueueItem = new Core.Data.EditQueueItem {
                    DateSubmitted = DateTime.UtcNow
                };
                if (enableEditQueueLogging)
                {
                    editQueueItem.EntityID   = updatedPOI.ID;
                    editQueueItem.EntityType = dataModel.EntityTypes.FirstOrDefault(t => t.ID == 1);
                    //charging point location entity type id

                    //serialize cp as json
                    var jsonOutput = new OutputProviders.JSONOutputProvider();

                    //null extra data we don't want to serialize/compare
                    updatedPOI.UserComments = null;
                    updatedPOI.MediaItems   = null;

                    string editData = jsonOutput.PerformSerialisationToString(updatedPOI, new JsonSerializerSettings {
                        NullValueHandling = NullValueHandling.Ignore
                    });

                    editQueueItem.EditData = editData;

                    if (updatedPOI.ID > 0)
                    {
                        //check if poi will change with this edit, if not we discard it completely
                        if (!poiManager.HasDifferences(oldPOI, updatedPOI))
                        {
                            System.Diagnostics.Debug.WriteLine("POI Update has no changes, discarding change.");
                            return(updatedPOI.ID);
                        }
                        else
                        {
                            editQueueItem.PreviousData = jsonOutput.PerformSerialisationToString(oldPOI, new JsonSerializerSettings {
                                NullValueHandling = NullValueHandling.Ignore
                            });
                        }
                    }

                    if (user != null)
                    {
                        editQueueItem.User = dataModel.Users.FirstOrDefault(u => u.ID == user.ID);
                    }
                    editQueueItem.IsProcessed = false;
                    editQueueItem             = dataModel.EditQueueItems.Add(editQueueItem);
                    //TODO: send notification of new item for approval

                    //save edit queue item
                    dataModel.SaveChanges();

                    //if previous edit queue item exists by same user for same POI, mark as processed
                    var previousEdits = dataModel.EditQueueItems.Where(e => e.UserID == editQueueItem.UserID && e.EntityID == editQueueItem.EntityID && e.EntityTypeID == editQueueItem.EntityTypeID && e.ID != editQueueItem.ID && e.IsProcessed != true);
                    foreach (var previousEdit in previousEdits)
                    {
                        previousEdit.IsProcessed = true;
                        if (editQueueItem.User != null)
                        {
                            previousEdit.ProcessedByUser = editQueueItem.User;
                        }
                        else
                        {
                            editQueueItem.ProcessedByUser = dataModel.Users.FirstOrDefault(u => u.ID == (int)StandardUsers.System);
                        }
                        previousEdit.DateProcessed = DateTime.UtcNow;
                    }
                    //save updated edit queue items
                    dataModel.SaveChanges();
                }

                //prepare and save changes POI changes/addition
                if (isUpdate && !AllowUpdates)
                {
                    //user has submitted an edit but is not an approved editor
                    //SendEditSubmissionNotification(updatedPOI, user);

                    //user is not an editor, item is now pending in edit queue for approval.
                    return(updatedPOI.ID);
                }

                if (isUpdate && updatedPOI.SubmissionStatusTypeID >= 1000)
                {
                    //update is a delisting, skip superseding poi
                    System.Diagnostics.Debug.WriteLine("skipping superseding of imported POI due to delisting");
                }
                else
                {
                    int?supersedesID = null;
                    //if update by non-system user will change an imported/externally provided data, supersede old POI with new one (retain ID against new POI)
                    if (isUpdate && !isSystemUser && oldPOI.DataProviderID != (int)StandardDataProviders.OpenChargeMapContrib)
                    {
                        //move old poi to new id, set status of new item to superseded
                        supersedesID = poiManager.SupersedePOI(dataModel, oldPOI, updatedPOI);
                    }
                }

                //user is an editor, go ahead and store the addition/update
                var cpData = new Core.Data.ChargePoint();
                if (isUpdate)
                {
                    cpData = dataModel.ChargePoints.First(c => c.ID == updatedPOI.ID);
                }

                //set/update cp properties
                poiManager.PopulateChargePoint_SimpleToData(updatedPOI, cpData, dataModel);

                //if item has no submission status and user permitted to edit, set to published
                if (userCanEditWithoutApproval && cpData.SubmissionStatusTypeID == null)
                {
                    cpData.SubmissionStatusType   = dataModel.SubmissionStatusTypes.First(s => s.ID == (int)StandardSubmissionStatusTypes.Submitted_Published);
                    cpData.SubmissionStatusTypeID = cpData.SubmissionStatusType.ID; //hack due to conflicting state change for SubmissionStatusType
                }
                else
                {
                    //no submission status, set to 'under review'
                    if (cpData.SubmissionStatusType == null)
                    {
                        cpData.SubmissionStatusType = dataModel.SubmissionStatusTypes.First(s => s.ID == (int)StandardSubmissionStatusTypes.Submitted_UnderReview);
                    }
                }

                cpData.DateLastStatusUpdate = DateTime.UtcNow;

                if (!isUpdate)
                {
                    //new data objects need added to data model before save
                    if (cpData.AddressInfo != null)
                    {
                        dataModel.AddressInfoList.Add(cpData.AddressInfo);
                    }

                    dataModel.ChargePoints.Add(cpData);
                }

                //finally - save poi update
                dataModel.SaveChanges();

                //get id of update/new poi
                int newPoiID = cpData.ID;

                //this is an authorised update, reflect change in edit queue item
                if (enableEditQueueLogging && user != null && user.ID > 0)
                {
                    var editUser = dataModel.Users.FirstOrDefault(u => u.ID == user.ID);
                    editQueueItem.User = editUser;

                    if (newPoiID > 0)
                    {
                        editQueueItem.EntityID = newPoiID;
                    }

                    //if user is authorised to edit, process item automatically without review
                    if (userCanEditWithoutApproval)
                    {
                        editQueueItem.ProcessedByUser = editUser;
                        editQueueItem.DateProcessed   = DateTime.UtcNow;
                        editQueueItem.IsProcessed     = true;
                    }

                    //save edit queue item changes
                    dataModel.SaveChanges();
                }
                else
                {
                    //anonymous submission, update edit queue item
                    if (enableEditQueueLogging && user == null)
                    {
                        if (newPoiID > 0)
                        {
                            editQueueItem.EntityID = newPoiID;
                        }
                        dataModel.SaveChanges();
                    }
                }

                System.Diagnostics.Debug.WriteLine("Added/Updated CP:" + cpData.ID);

                //if user is not anonymous, log their submission and update their reputation points
                if (user != null)
                {
                    AuditLogManager.Log(user, isUpdate ? AuditEventType.UpdatedItem : AuditEventType.CreatedItem, "Modified OCM-" + cpData.ID, null);
                    //add reputation points
                    new UserManager().AddReputationPoints(user, 1);
                }

                //preserve new POI Id for caller
                updatedPOI.ID = cpData.ID;

                //if new item added, send notification

                /*if (!isUpdate)
                 * {
                 *  SendNewPOISubmissionNotification(updatedPOI, user, cpData);
                 * }*/

                var cacheTask = Task.Run(async() =>
                {
                    return(await CacheManager.RefreshCachedPOIList());
                });
                cacheTask.Wait();

                return(updatedPOI.ID);
            }
            catch (Exception exp)
            {
                System.Diagnostics.Debug.WriteLine(exp.ToString());
                AuditLogManager.ReportWebException(HttpContext.Current.Server, AuditEventType.SystemErrorWeb);
                //throw exp;
                //error performing submission
                return(-1);
            }
        }