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 })); }
// // 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")); }
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")); }
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 })); }
// 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)); }
/// <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 }); } }