public async Task ActionComment(int userId, int commentId)
        {
            var comment = DataModel.UserComments.FirstOrDefault(c => c.Id == commentId);

            comment.IsActionedByEditor = true;
            DataModel.SaveChanges();

            var user = new UserManager().GetUser(userId);

            AuditLogManager.Log(user, AuditEventType.UpdatedItem, "{EntityType:\"Comment\",EntityID:" + commentId + ",ChargePointID:" + comment.ChargePointId + "}", "User marked comment as actioned");

            //refresh cached POI data
            await CacheManager.RefreshCachedPOI(comment.ChargePointId);
        }
        public void DeleteComment(int userId, int commentId)
        {
            var comment = DataModel.UserComments.FirstOrDefault(c => c.ID == commentId);

            if (comment != null)
            {
                var cpID = comment.ChargePointID;
                DataModel.UserComments.Remove(comment);
                DataModel.ChargePoints.Find(cpID).DateLastStatusUpdate = DateTime.UtcNow;
                DataModel.SaveChanges();

                var user = new UserManager().GetUser(userId);
                AuditLogManager.Log(user, AuditEventType.DeletedItem, "{EntityType:\"Comment\",EntityID:" + commentId + ",ChargePointID:" + cpID + "}", "User deleted comment");

                CacheManager.RefreshCachedPOIList();
            }
        }
        public void DeleteMediaItem(int userId, int mediaItemId)
        {
            var dataModel = new OCMEntities();

            var item = dataModel.MediaItems.FirstOrDefault(c => c.ID == mediaItemId);

            if (item != null)
            {
                var cpID = item.ChargePointID;
                dataModel.MediaItems.Remove(item);
                dataModel.ChargePoints.Find(cpID).DateLastStatusUpdate = DateTime.UtcNow;
                dataModel.SaveChanges();

                //TODO: delete from underlying storage
                var user = new UserManager().GetUser(userId);
                AuditLogManager.Log(user, AuditEventType.DeletedItem, "{EntityType:\"Comment\", EntityID:" + mediaItemId + ",ChargePointID:" + cpID + "}", "User deleted media item");
            }
        }
        public string[] UploadPOIImageToStorage(string tempFolder, string sourceImageFile, Model.ChargePoint poi)
        {
            string extension = sourceImageFile.Substring(sourceImageFile.LastIndexOf('.'), sourceImageFile.Length - sourceImageFile.LastIndexOf('.')).ToLower();

            if (extension != ".jpg" && extension != ".jpeg" && extension != ".png" && extension != ".gif")
            {
                return(null);
            }
            var storage = new StorageManager();

            try
            {
                //TODO: allocate sequences properly
                string destFolderPrefix = poi.AddressInfo.Country.ISOCode + "/" + "OCM" + poi.ID + "/";
                string dateStamp        = String.Format("{0:yyyyMMddHHmmssff}", DateTime.UtcNow);
                string largeFileName    = "OCM-" + poi.ID + ".orig." + dateStamp + extension;
                string thumbFileName    = "OCM-" + poi.ID + ".thmb." + dateStamp + extension;
                string mediumFileName   = "OCM-" + poi.ID + ".medi." + dateStamp + extension;

                var metadataTags = new List <KeyValuePair <string, string> >();
                metadataTags.Add(new KeyValuePair <string, string>("OCM", poi.ID.ToString()));
                //metadataTags.Add(new KeyValuePair<string, string>("Title", poi.AddressInfo.Title));
                metadataTags.Add(new KeyValuePair <string, string>("Latitude", poi.AddressInfo.Latitude.ToString()));
                metadataTags.Add(new KeyValuePair <string, string>("Longitude", poi.AddressInfo.Longitude.ToString()));

                //TODO: generate thumbnail
                var urls = new string[3];

                //attempt thumbnails
                try
                {
                    //generate thumbnail max 100 wide
                    GenerateImageThumbnails(sourceImageFile, tempFolder + thumbFileName, 100);
                    //generate medium max 400 wide
                    GenerateImageThumbnails(sourceImageFile, tempFolder + mediumFileName, 400);
                    //resize original max 2048
                    GenerateImageThumbnails(sourceImageFile, tempFolder + largeFileName, 2048);
                }
                catch (Exception)
                {
                    AuditLogManager.Log(null, AuditEventType.SystemErrorAPI, "Failed to generate image upload thumbnails : OCM-" + poi.ID, "");
                    return(null);
                }

                //attempt upload
                bool success      = false;
                int  attemptCount = 0;
                while (success == false && attemptCount < 5)
                {
                    attemptCount++;
                    try
                    {
                        if (urls[0] == null)
                        {
                            urls[0] = storage.UploadImage(sourceImageFile, destFolderPrefix + largeFileName, metadataTags);
                        }

                        if (urls[1] == null)
                        {
                            urls[1] = storage.UploadImage(tempFolder + thumbFileName, destFolderPrefix + thumbFileName, metadataTags);
                        }

                        if (urls[2] == null)
                        {
                            urls[2] = storage.UploadImage(tempFolder + mediumFileName, destFolderPrefix + mediumFileName, metadataTags);
                        }
                        if (urls[0] != null && urls[1] != null && urls[2] != null)
                        {
                            success = true;
                        }
                    }
                    catch (Exception exp)
                    {
                        //failed to store blobs
                        AuditLogManager.Log(null, AuditEventType.SystemErrorAPI, "Failed to upload images to azure (attempt " + attemptCount + "): OCM-" + poi.ID, exp.ToString());
                        //return null;
                    }
                    attemptCount++;
                    Thread.Sleep(5000); //wait a bit then try again
                }

                Thread.Sleep(5000);
                //attempt to delete temp files
                try
                {
                    System.IO.File.Delete(sourceImageFile);
                    System.IO.File.Delete(tempFolder + thumbFileName);
                    System.IO.File.Delete(tempFolder + mediumFileName);
                    System.IO.File.Delete(tempFolder + largeFileName);
                }
                catch (Exception)
                {
                    ;
                }

                return(urls);
            }
            catch (Exception)
            {
                //failed to upload
                AuditLogManager.Log(null, AuditEventType.SystemErrorAPI, "Final attempt to upload images to azure failed: OCM-" + poi.ID, "");

                return(null);
            }
        }
Beispiel #5
0
        public bool GrantPermission(User user, StandardPermissionAttributes permissionAttribute, string attributeValue, bool removeOnly, User administrator)
        {
            //to apply permissions we add or remove from the permissions list attached to the user details, we also maintain a string in the legacy semicolon seperated format for apps/code which still requires the older format.
            var userDetails = dataModel.Users.FirstOrDefault(u => u.Id == user.ID);

            if (userDetails != null)
            {
                UserPermissionsContainer userPermissions = new UserPermissionsContainer();
                if (!String.IsNullOrEmpty(user.Permissions))
                {
                    userPermissions = JsonConvert.DeserializeObject <UserPermissionsContainer>(user.Permissions);
                }

                //apply permission to legacypermission tag of user details
                string attributeTag = "[" + permissionAttribute.ToString() + "=" + attributeValue + "];";

                if (userPermissions.LegacyPermissions == null)
                {
                    userPermissions.LegacyPermissions = "";
                }
                if (userPermissions.Permissions == null)
                {
                    userPermissions.Permissions = new List <UserPermission>();
                }

                if (!removeOnly)
                {
                    //add permission

                    //append permission attribute for user

                    //legacy format is [AttributeName1=Value];[AttributeName2=Value]; -legacy  format is maintained as LegacyPermissions  field in JSON format, for older apps (mainly older versions of OCM app)
                    if (!userPermissions.LegacyPermissions.Contains(attributeTag))
                    {
                        if (!userPermissions.LegacyPermissions.EndsWith(";") && userPermissions.LegacyPermissions != "")
                        {
                            userPermissions.LegacyPermissions += ";";
                        }
                        userPermissions.LegacyPermissions += attributeTag;

                        //add permission to main permission list
                        if (permissionAttribute == StandardPermissionAttributes.CountryLevel_Editor)
                        {
                            var permission = new UserPermission();
                            if (attributeValue != "All")
                            {
                                permission.CountryID = int.Parse(attributeValue);
                            }
                            permission.Level = PermissionLevel.Editor;
                            userPermissions.Permissions.Add(permission);
                        }

                        //TODO: administrator permissions
                        AuditLogManager.Log(administrator, AuditEventType.PermissionGranted, "User: "******"; Permission:" + permissionAttribute.ToString(), null);
                    }
                }
                else
                {
                    //remove permission
                    userPermissions.LegacyPermissions = userPermissions.LegacyPermissions.Replace(attributeTag, "");

                    if (permissionAttribute == StandardPermissionAttributes.CountryLevel_Editor)
                    {
                        if (attributeValue != "All")
                        {
                            int countryID = int.Parse(attributeValue);
                            userPermissions.Permissions.RemoveAll(p => p.Level == PermissionLevel.Editor && p.CountryID == countryID);
                        }
                        else
                        {
                            userPermissions.Permissions.RemoveAll(p => p.Level == PermissionLevel.Editor);
                        }
                    }
                    AuditLogManager.Log(administrator, AuditEventType.PermissionRemoved, "User: "******"; Permission:" + permissionAttribute.ToString(), null);
                }

                //remove requested permission attribute if it exists
                if (userDetails.PermissionsRequested != null)
                {
                    userDetails.PermissionsRequested = userDetails.PermissionsRequested.Replace(attributeTag, "");
                }

                userDetails.Permissions = JsonConvert.SerializeObject(userPermissions, Formatting.None, new JsonSerializerSettings {
                    NullValueHandling = NullValueHandling.Ignore
                });
                dataModel.SaveChanges();
                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #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
                });
            }
        }
Beispiel #7
0
        /// <summary>
        /// Submit a new comment against a given charge equipment id
        /// </summary>
        /// <param name="comment"></param>
        /// <returns>ID of new comment, -1 for invalid cp, -2 for general error saving comment</returns>
        public async Task <int> PerformSubmission(Common.Model.UserComment comment, Model.User user)
        {
            //TODO: move all to UserCommentManager
            //populate data model comment from simple comment object

            var dataModel       = new Core.Data.OCMEntities();
            int cpID            = comment.ChargePointID;
            var dataComment     = new Core.Data.UserComment();
            var dataChargePoint = dataModel.ChargePoints.FirstOrDefault(c => c.Id == cpID);

            if (dataChargePoint == null)
            {
                return(-1);                         //invalid charge point specified
            }
            dataComment.ChargePointId = dataChargePoint.Id;

            dataComment.Comment = comment.Comment;
            int commentTypeID = comment.CommentTypeID ?? 10; //default to General Comment

            // some clients may post a CommentType object instead of just an ID
            if (comment.CommentType != null)
            {
                commentTypeID = comment.CommentType.ID;
            }

            dataComment.UserCommentTypeId = commentTypeID;

            int?checkinStatusType = comment.CheckinStatusTypeID;

            dataComment.CheckinStatusTypeId = (byte?)comment.CheckinStatusTypeID;

            // some clients may post a CheckinStatusType object instead of just an ID
            if (dataComment.CheckinStatusTypeId == null && comment.CheckinStatusType != null)
            {
                dataComment.CheckinStatusTypeId = (byte?)comment.CheckinStatusType.ID;
            }

            dataComment.UserName    = comment.UserName;
            dataComment.Rating      = comment.Rating;
            dataComment.RelatedUrl  = comment.RelatedURL;
            dataComment.DateCreated = DateTime.UtcNow;

            if (user != null && user.ID > 0)
            {
                var ocmUser = dataModel.Users.FirstOrDefault(u => u.Id == user.ID);

                if (ocmUser != null)
                {
                    dataComment.UserId   = ocmUser.Id;
                    dataComment.UserName = ocmUser.Username;
                }
            }

            try
            {
                dataChargePoint.DateLastStatusUpdate = DateTime.UtcNow;
                dataModel.UserComments.Add(dataComment);

                dataModel.SaveChanges();

                if (user != null)
                {
                    AuditLogManager.Log(user, AuditEventType.CreatedItem, "Added Comment " + dataComment.Id + " to OCM-" + cpID, null);
                    //add reputation points
                    new UserManager().AddReputationPoints(user, 1);
                }

                //SendPOICommentSubmissionNotifications(comment, user, dataComment);

                //TODO: only refresh cache for specific POI
                await CacheManager.RefreshCachedPOI(dataComment.ChargePoint.Id);

                return(dataComment.Id);
            }
            catch (Exception exp)
            {
                return(-2); //error saving
            }
        }
Beispiel #8
0
        public static void ReportWebException(HttpServerUtility Server, AuditEventType eventType)
        {
            bool   ignoreException = false;
            string body            = "An error has occurred while a user was browsing OCM:<br><br>";

            object exceptionObject = null;

            if (Server.GetLastError() != null)
            {
                Exception exp = Server.GetLastError();
                exceptionObject = exp;

                if (exp.InnerException != null)
                {
                    exceptionObject = exp.InnerException;
                }

                body += ((Exception)exceptionObject).ToString();

                HttpContext con = HttpContext.Current;
                if (con.Request.Url != null)
                {
                    body += "<br><br>Request Url:" + con.Request.Url.ToString();

                    //special case to avoid reporting /trackback url exceptions
                    if (con.Request.Url.ToString().EndsWith("/trackback/"))
                    {
                        ignoreException = true;
                    }
                }
                if (con.Request.UserAgent != null)
                {
                    body += "<br>User Agent: " + con.Request.UserAgent;
                }
                body += "<br><br>" + DateTime.UtcNow.ToString();
            }

            if (exceptionObject is System.Web.HttpRequestValidationException || exceptionObject is System.Web.UI.ViewStateException)
            {
                ignoreException = true;
            }

            if (!ignoreException)
            {
                if (ConfigurationManager.AppSettings["EnableErrorNotifications"] == "true")
                {
                    NotificationManager notification = new NotificationManager();

                    var msgParams = new Hashtable()
                    {
                        { "Description", "System Error" },
                        { "Name", "OCM Website" },
                        { "Email", "*****@*****.**" },
                        { "Comment", body }
                    };

                    notification.PrepareNotification(NotificationType.ContactUsMessage, msgParams);
                    notification.SendNotification(NotificationType.ContactUsMessage);
                }

                AuditLogManager.Log(null, eventType, body, null);
            }
        }
Beispiel #9
0
        public static void ReportWebException(bool enableNotifications, string contextUrl, AuditEventType eventType, string msg = null, Exception exp = null)
        {
            bool   ignoreException = false;
            string body            = "An error has occurred while a user was browsing OCM:<br><br>";

            if (msg != null)
            {
                body = msg;
            }


            if (exp != null)
            {
                object exceptionObject = exp;

                if (exp.InnerException != null)
                {
                    exceptionObject = exp.InnerException;
                }

                body += ((Exception)exceptionObject).ToString();


                if (contextUrl != null)
                {
                    body += "<br><br>Request Url:" + contextUrl.ToString();

                    //special case to avoid reporting /trackback url exceptions
                    if (contextUrl.ToString().EndsWith("/trackback/"))
                    {
                        ignoreException = true;
                    }
                }

                /*if (con.Request.UserAgent != null)
                 * {
                 *  body += "<br>User Agent: " + con.Request.UserAgent;
                 * }*/
            }
            body += "<br><br>" + DateTime.UtcNow.ToString();

            //if (exp is System.Web.HttpRequestValidationException || exceptionObject is System.Web.UI.ViewStateException) ignoreException = true;

            if (!ignoreException)
            {
                if (enableNotifications)
                {
                    NotificationManager notification = new NotificationManager();

                    var msgParams = new Hashtable()
                    {
                        { "Description", "System Error" },
                        { "Name", "OCM Website" },
                        { "Email", "*****@*****.**" },
                        { "Comment", body }
                    };

                    notification.PrepareNotification(NotificationType.ContactUsMessage, msgParams);
                    notification.SendNotification(NotificationType.ContactUsMessage);
                }

                AuditLogManager.Log(null, eventType, body, null);
            }
        }
        /// <summary>
        /// Submit a new comment against a given charge equipment id
        /// </summary>
        /// <param name="comment"></param>
        /// <returns>ID of new comment, -1 for invalid cp, -2 for general error saving comment</returns>
        public int PerformSubmission(Common.Model.UserComment comment, Model.User user)
        {
            //TODO: move all to UserCommentManager
            //populate data model comment from simple comment object

            var dataModel   = new Core.Data.OCMEntities();
            int cpID        = comment.ChargePointID;
            var dataComment = new Core.Data.UserComment();

            dataComment.ChargePoint = dataModel.ChargePoints.FirstOrDefault(c => c.ID == cpID);

            if (dataComment.ChargePoint == null)
            {
                return(-1);                                 //invalid charge point specified
            }
            dataComment.Comment = comment.Comment;
            int commentTypeID = 10; //default to General Comment

            if (comment.CommentType != null)
            {
                commentTypeID = comment.CommentType.ID;
            }
            dataComment.UserCommentType = dataModel.UserCommentTypes.FirstOrDefault(t => t.ID == commentTypeID);
            if (comment.CheckinStatusType != null)
            {
                dataComment.CheckinStatusType = dataModel.CheckinStatusTypes.FirstOrDefault(t => t.ID == comment.CheckinStatusType.ID);
            }
            dataComment.UserName    = comment.UserName;
            dataComment.Rating      = comment.Rating;
            dataComment.RelatedURL  = comment.RelatedURL;
            dataComment.DateCreated = DateTime.UtcNow;

            if (user != null && user.ID > 0)
            {
                var ocmUser = dataModel.Users.FirstOrDefault(u => u.ID == user.ID);

                if (ocmUser != null)
                {
                    dataComment.User     = ocmUser;
                    dataComment.UserName = ocmUser.Username;
                }
            }

            /*if (dataComment.User==null)
             * {
             *  return -3; //rejected, not authenticated
             * }*/

            try
            {
                dataComment.ChargePoint.DateLastStatusUpdate = DateTime.UtcNow;
                dataModel.UserComments.Add(dataComment);

                dataModel.SaveChanges();

                if (user != null)
                {
                    AuditLogManager.Log(user, AuditEventType.CreatedItem, "Added Comment " + dataComment.ID + " to OCM-" + cpID, null);
                    //add reputation points
                    new UserManager().AddReputationPoints(user, 1);
                }

                //SendPOICommentSubmissionNotifications(comment, user, dataComment);

                //TODO: only refresh cache for specific POI
                CacheManager.RefreshCachedPOI(dataComment.ChargePoint.ID);

                return(dataComment.ID);
            }
            catch (Exception)
            {
                return(-2); //error saving
            }
        }