예제 #1
0
        public async Task <ActionResult> CommentActioned(int poiId, int commentId)
        {
            CheckForReadOnly();

            // if poi is awaiting review, publish now
            var poiManager = new POIManager();

            var poi = await poiManager.Get(poiId, true);

            var comment = poi.UserComments.Find(c => c.ID == commentId);

            using (var userManager = new UserManager())
            {
                var user = userManager.GetUser((int)UserID);

                if (POIManager.CanUserEditPOI(poi, user))
                {
                    using (var commentManager = new UserCommentManager())
                    {
                        await commentManager.ActionComment(user.ID, commentId);
                    }
                }
            }

            // return to approval queue
            return(RedirectToAction("details", "POI", new { id = poiId }));
        }
예제 #2
0
        //
        // GET: /POI/Edit/5
        public ActionResult Edit(int?id)
        {
            if (id > 0)
            {
                var poi = new POIManager().Get((int)id);
                if (poi != null)
                {
                    InitEditReferenceData(poi);

                    var refData = new POIBrowseModel();
                    ViewBag.ReferenceData    = refData;
                    ViewBag.HideAdvancedInfo = true;

                    try
                    {
                        var user = new UserManager().GetUser((int)Session["UserID"]);
                        if (POIManager.CanUserEditPOI(poi, user))
                        {
                            ViewBag.HideAdvancedInfo = false;
                        }
                    }
                    catch (Exception)
                    {
                        ;;  //user not signed in
                    }

                    //enable advanced edit options for full editors/admin
                    return(View(poi));
                }
            }

            //no applicable poi, jump back to browse
            return(RedirectToAction("Index", "POI"));
        }
예제 #3
0
        public async Task <ActionResult> Edit(int?id, bool createCopy = false)
        {
            ViewBag.IsReadOnlyMode = this.IsReadOnlyMode;

            if (id > 0)
            {
                ChargePoint poi = null;

                if (createCopy)
                {
                    //get version of POI with location details removed, copying equipment etc
                    poi = await new POIManager().GetCopy((int)id, true);
                }
                else
                {
                    poi = await new POIManager().Get((int)id);
                }

                if (poi != null)
                {
                    InitEditReferenceData(poi);

                    var refData = new POIBrowseModel(GetCoreReferenceData());
                    ViewBag.ReferenceData    = refData;
                    ViewBag.HideAdvancedInfo = true;

                    if (!createCopy)
                    {
                        try
                        {
                            var user = new UserManager().GetUser((int)UserID);
                            if (POIManager.CanUserEditPOI(poi, user))
                            {
                                ViewBag.HideAdvancedInfo = false;
                            }
                        }
                        catch (Exception)
                        {
                            ;;  //user not signed in
                        }
                    }

                    //enable advanced edit options for full editors/admin
                    return(View(poi));
                }
            }

            //no applicable poi, jump back to browse
            return(RedirectToAction("Index", "POI"));
        }
예제 #4
0
        public async Task <ActionResult> Approve(int id)
        {
            CheckForReadOnly();

            // if poi is awaiting review, publish now
            var poiManager = new POIManager();

            var poi = await poiManager.Get(id, true);

            if (poi.SubmissionStatusTypeID == (int)StandardSubmissionStatusTypes.Submitted_UnderReview || poi.SubmissionStatusTypeID == (int)StandardSubmissionStatusTypes.Imported_UnderReview)
            {
                var user = new UserManager().GetUser((int)UserID);
                if (POIManager.CanUserEditPOI(poi, user))
                {
                    poi.SubmissionStatusTypeID = (int)StandardSubmissionStatusTypes.Submitted_Published;
                    await new SubmissionManager().PerformPOISubmission(poi, user);
                }
            }

            // return to approval queue
            return(RedirectToAction("Index", "POI", new { submissionStatusTypeId = 1 }));
        }
예제 #5
0
        // GET: /POI/Details/5

        //[OutputCache(Duration=240, VaryByParam="id")]
        public async Task <ActionResult> Details(int id = 0, string layout = null, string status = null)
        {
            if (id <= 0)
            {
                return(RedirectToAction("Index"));
            }

            if (status != null)
            {
                ViewBag.Status = status;
            }

            OCM.API.Common.POIManager cpManager = new API.Common.POIManager();
            POIViewModel viewModel = new POIViewModel();

            var poi = await cpManager.Get(id, true, allowDiskCache : false, allowMirrorDB : true);

            if (poi != null)
            {
                ViewBag.FullTitle = "Location Details: OCM-" + poi.ID + " " + poi.AddressInfo.Title;

                List <LocationImage> imageList = null; // new OCM.MVC.App_Code.GeocodingHelper().GetGeneralLocationImages((double)poi.AddressInfo.Latitude, (double)poi.AddressInfo.Longitude);

                if (imageList != null)
                {
                    imageList         = imageList.Where(i => i.Width >= 500).ToList();
                    ViewBag.ImageList = imageList.ToList();
                }

                viewModel.POI = poi;

                if (!IsRequestByRobot)
                {
                    viewModel.NewComment = new UserComment()
                    {
                        ChargePointID = poi.ID, CommentType = new UserCommentType {
                            ID = 10
                        }, CheckinStatusType = new CheckinStatusType {
                            ID = 0
                        }
                    };

                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();
                    viewModel.POIListNearby = (await cpManager.GetPOIListAsync(new APIRequestParams {
                        MaxResults = 10, Latitude = poi.AddressInfo.Latitude, Longitude = poi.AddressInfo.Longitude, Distance = 15, DistanceUnit = DistanceUnit.Miles, AllowMirrorDB = true
                    })).ToList();
                    viewModel.POIListNearby.RemoveAll(p => p.ID == poi.ID); //don't include the current item in nearby POI list
                    sw.Stop();
                    System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds);

                    ViewBag.ReferenceData = new POIBrowseModel(await GetCoreReferenceDataAsync());

                    //get data quality report

                    //if (IsUserAdmin)
                    //{
                    viewModel.DataQualityReport = new DataAnalysisManager().GetDataQualityReport(poi);
                    //}

                    ViewBag.UserCanEditPOI = false;
                    if (IsUserSignedIn)
                    {
                        var user = new UserManager().GetUser((int)UserID);
                        if (POIManager.CanUserEditPOI(poi, user))
                        {
                            ViewBag.UserCanEditPOI = true;
                        }
                    }
                }
                else
                {
                    viewModel.POIListNearby = new List <ChargePoint>();
                }
            }

            return(View(viewModel));
        }
예제 #6
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 async Task <ValidationResult> PerformPOISubmission(Model.ChargePoint updatedPOI, Model.User user, bool performCacheRefresh = true, bool disablePOISuperseding = false)
        {
            try
            {
                var  poiManager             = new POIManager();
                bool enableEditQueueLogging = bool.Parse(ConfigurationManager.AppSettings["EnableEditQueue"]);
                bool isUpdate = false;
                bool userCanEditWithoutApproval = false;
                bool isSystemUser = false;
                int? supersedesID = null;//POI from another data provider which has been superseded by an edit

                //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)
                        {
                            //valid update requested but updates not allowed
                            return(new ValidationResult {
                                IsValid = false, Message = "Updates are disabled"
                            });
                        }
                    }
                    else
                    {
                        //update does not correctly identify an existing poi
                        return(new ValidationResult {
                            IsValid = false, Message = "Update does not correctly match an existing POI"
                        });
                    }
                }

                //validate if minimal required data is present
                if (updatedPOI.AddressInfo.Title == null || (updatedPOI.AddressInfo.Country == null && updatedPOI.AddressInfo.CountryID == null))
                {
                    return(new ValidationResult {
                        IsValid = false, Message = "Update failed basic validation"
                    });
                }

                //convert to DB version of POI and back so that properties are fully populated
                using (var refDataManager = new ReferenceDataManager())
                {
                    var refData = await refDataManager.GetCoreReferenceDataAsync();

                    updatedPOI = PopulateFullPOI(updatedPOI, refData);
                }

                Model.ChargePoint oldPOI = null;

                if (updatedPOI.ID > 0)
                {
                    //get json snapshot of current cp data to store as 'previous'
                    oldPOI = await 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

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

                    string editData = 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(new ValidationResult {
                                IsValid = true, ItemId = updatedPOI.ID, Message = "No POI changes detected"
                            });
                        }
                        else
                        {
                            editQueueItem.PreviousData = PerformSerialisationToString(oldPOI, new JsonSerializerSettings {
                                NullValueHandling = NullValueHandling.Ignore
                            });
                        }
                    }

                    if (user != null)
                    {
                        editQueueItem.User = dataModel.Users.FirstOrDefault(u => u.Id == user.ID);
                    }
                    var processedByUser = editQueueItem.User ?? dataModel.Users.FirstOrDefault(u => u.Id == (int)StandardUsers.System);

                    editQueueItem.IsProcessed = false;
                    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;
                        previousEdit.ProcessedByUser = processedByUser;

                        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(new ValidationResult {
                        IsValid = true, ItemId = updatedPOI.ID, Message = "Update submitted for review"
                    });
                }

                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
                {
                    //if poi being updated exists from an imported source we supersede the old POI with the new version, unless we're doing a fresh import from same data provider
                    if (!disablePOISuperseding)
                    {
                        //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
                //set/update cp properties
                var cpData = poiManager.PopulateChargePoint_SimpleToData(updatedPOI, dataModel);

                //if item has no submission status and user permitted to edit, set to published
                if (userCanEditWithoutApproval && cpData.SubmissionStatusTypeId == null)
                {
                    cpData.SubmissionStatusTypeId = (int)StandardSubmissionStatusTypes.Submitted_Published; //hack due to conflicting state change for SubmissionStatusType
                }
                else
                {
                    //no submission status, set to 'under review'
                    if (cpData.SubmissionStatusTypeId == null)
                    {
                        cpData.SubmissionStatusTypeId = (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.AddressInfos.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 (performCacheRefresh)
                {
                    if (supersedesID != null)
                    {
                        await CacheManager.RefreshCachedPOI((int)supersedesID);
                    }
                    await CacheManager.RefreshCachedPOI(updatedPOI.ID);
                }

                return(new ValidationResult {
                    IsValid = true, ItemId = updatedPOI.ID, Message = "Update submitted."
                });
            }
            catch (Exception exp)
            {
                System.Diagnostics.Debug.WriteLine(exp.ToString());
                AuditLogManager.ReportWebException(true, null, AuditEventType.SystemErrorWeb, "POI Submission Failed", exp);

                //error performing submission
                return(new ValidationResult {
                    IsValid = false, Message = "Submission Failed with an Exception: " + exp.Message
                });
            }
        }