/// <summary> /// Deletes the project. /// </summary> /// <param name="projectId">The project id.</param> /// <returns></returns> public static bool Delete(int projectId) { if (projectId <= Globals.NEW_ID) { throw (new ArgumentOutOfRangeException("projectId")); } var uploadpath = GetById(projectId).UploadPath; if (DataProviderManager.Provider.DeleteProject(projectId)) { DeleteProjectCustomView(projectId); try { uploadpath = string.Concat(HostSettingManager.Get(HostSettingNames.AttachmentUploadPath), uploadpath); if (uploadpath.StartsWith("~")) { uploadpath = HttpContext.Current.Server.MapPath(uploadpath); } Directory.Delete(uploadpath, true); } catch (Exception ex) { Log.Error(string.Format(LoggingManager.GetErrorMessageResource("DeleteProjectUploadFolderError"), uploadpath, projectId), ex); } return(true); } return(false); }
/// <summary> /// Updates the project. /// </summary> /// <returns></returns> private static bool Update(Project entity) { var p = GetById(entity.Id); if (entity.AttachmentStorageType == IssueAttachmentStorageTypes.FileSystem && p.UploadPath != entity.UploadPath) { // BGN-1909 // Better santization of Upload Paths var currentPath = string.Concat("~", Globals.UPLOAD_FOLDER, p.UploadPath.Trim()); var currentFullPath = HttpContext.Current.Server.MapPath(currentPath); var newPath = string.Concat("~", Globals.UPLOAD_FOLDER, entity.UploadPath.Trim()); var newFullPath = HttpContext.Current.Server.MapPath(newPath); // WARNING: When editing an invalid path, and trying to make it valid, // you will still get an error. This is because the Directory.Move() call // can traverse directories! Maybe we should allow the database to change, // but not change the file system? var isPathNorty = !Utilities.CheckUploadPath(currentPath); if (!Utilities.CheckUploadPath(newPath)) { isPathNorty = true; } if (isPathNorty) { // something bad is going on. DONT even File.Exist()!! if (Log.IsErrorEnabled) { Log.Error(string.Format(LoggingManager.GetErrorMessageResource("CouldNotCreateUploadDirectory"), newFullPath)); } return(false); } try { // BGN-1878 Upload path not recreated when user fiddles with a project setting if (File.Exists(currentFullPath)) { Directory.Move(currentFullPath, newFullPath); } else { Directory.CreateDirectory(newFullPath); } } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error(string.Format(LoggingManager.GetErrorMessageResource("CouldNotCreateUploadDirectory"), newFullPath), ex); } return(false); } } return(DataProviderManager.Provider.UpdateProject(entity)); }
/// <summary> /// Returns an Issue object, pre-populated with defaults settings. /// </summary> /// <param name="projectId">The project id.</param> /// <param name="title"></param> /// <param name="description"></param> /// <param name="assignedName"></param> /// <param name="ownerName"></param> /// <returns></returns> public static Issue GetDefaultIssueByProjectId(int projectId, string title, string description, string assignedName, string ownerName) { if (projectId <= Globals.NEW_ID) { throw new ArgumentException(string.Format(LoggingManager.GetErrorMessageResource("InvalidProjectId"), projectId)); } var curProject = ProjectManager.GetById(projectId); if (curProject == null) { throw new ArgumentException(string.Format(LoggingManager.GetErrorMessageResource("ProjectNotFoundError"), projectId)); } var cats = CategoryManager.GetByProjectId(projectId); var statuses = StatusManager.GetByProjectId(projectId); var priorities = PriorityManager.GetByProjectId(projectId); var issueTypes = IssueTypeManager.GetByProjectId(projectId); var resolutions = ResolutionManager.GetByProjectId(projectId); var affectedMilestones = MilestoneManager.GetByProjectId(projectId); var milestones = MilestoneManager.GetByProjectId(projectId); // Select the first one in the list, not really the default intended. var defCat = cats[0]; var defStatus = statuses[0]; var defPriority = priorities[0]; var defIssueType = issueTypes[0]; var defResolution = resolutions[0]; var defAffectedMilestone = affectedMilestones[0]; var defMilestone = milestones[0]; // Now create an issue var issue = new Issue { ProjectId = projectId, Id = Globals.NEW_ID, Title = title, CreatorUserName = ownerName, DateCreated = DateTime.Now, Description = description, DueDate = DateTime.MinValue, IssueTypeId = defIssueType.Id, AffectedMilestoneId = defAffectedMilestone.Id, AssignedUserName = assignedName, CategoryId = defCat.Id, MilestoneId = defMilestone.Id, OwnerUserName = ownerName, PriorityId = defPriority.Id, ResolutionId = defResolution.Id, StatusId = defStatus.Id, Estimation = 0, Visibility = 1 }; return(issue); }
/// <summary> /// Clones the project. /// </summary> /// <param name="projectId">The project id.</param> /// <param name="projectName">Name of the project.</param> /// <returns></returns> public static int CloneProject(int projectId, string projectName) { if (projectId <= Globals.NEW_ID) { throw (new ArgumentOutOfRangeException("projectId")); } if (string.IsNullOrEmpty(projectName)) { throw new ArgumentNullException("projectName"); } var newProjectId = DataProviderManager.Provider.CloneProject(projectId, projectName, Security.GetUserName()); if (newProjectId != 0) { var newProject = GetById(newProjectId); CustomFieldManager.UpdateCustomFieldView(newProjectId); try { if (newProject.AllowAttachments && HostSettingManager.Get(HostSettingNames.AttachmentStorageType, 0) == (int)IssueAttachmentStorageTypes.FileSystem) { // set upload path to new Guid newProject.UploadPath = Guid.NewGuid().ToString(); DataProviderManager.Provider.UpdateProject(newProject); var fullPath = string.Concat(HostSettingManager.Get(HostSettingNames.AttachmentUploadPath), newProject.UploadPath); if (fullPath.StartsWith("~")) { fullPath = HttpContext.Current.Server.MapPath(fullPath); } Directory.CreateDirectory(fullPath); } } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error(string.Format(LoggingManager.GetErrorMessageResource("CreateProjectUploadFolderError"), newProject.UploadPath, projectId), ex); } } HttpContext.Current.Cache.Remove("RolePermission"); return(newProjectId); } return(0); }
///// <summary> ///// Stewart Moss ///// Apr 14 2010 ///// ///// Performs a query containing any number of query clauses on a certain IssueID ///// </summary> ///// <param name="issueId"></param> ///// <param name="queryClauses"></param> ///// <returns></returns> //public static List<IssueAttachment> PerformQuery(int issueId, List<QueryClause> queryClauses) //{ // if (issueId < 0) // throw new ArgumentOutOfRangeException("issueId", "must be bigger than 0"); // queryClauses.Add(new QueryClause("AND", "IssueId", "=", issueId.ToString(), SqlDbType.Int, false)); // return PerformQuery(queryClauses); //} ///// <summary> ///// Stewart Moss ///// Apr 14 2010 8:30 pm ///// ///// Performs any query containing any number of query clauses ///// WARNING! Will expose the entire IssueAttachment table, regardless of ///// project level privileges. (that's why its private for now) ///// </summary> ///// <param name="queryClauses"></param> ///// <returns></returns> //private static List<IssueAttachment> PerformQuery(List<QueryClause> queryClauses) //{ // if (queryClauses == null) // throw new ArgumentNullException("queryClauses"); // var lst = new List<IssueAttachment>(); // DataProviderManager.Provider.PerformGenericQuery(ref lst, queryClauses, @"SELECT a.*, b.UserName as CreatorUserName, a.Userid as CreatorUserID, b.Username as CreatorDisplayName from BugNet_IssueAttachment as a, aspnet_Users as b WHERE a.UserId=b.UserID ", @" ORDER BY IssueAttachmentId DESC"); // return lst; //} /// <summary> /// Validate the file if we can attach it or not /// </summary> /// <param name="fileName">The file name to validate</param> /// <param name="inValidReason">The reason the validation failed</param> /// <returns>True if the file is valid, otherwise false</returns> public static bool IsValidFile(string fileName, out string inValidReason) { inValidReason = String.Empty; fileName = fileName.Trim(); fileName = Path.GetFileName(fileName); // empty file name if (String.IsNullOrEmpty(fileName)) { inValidReason = LoggingManager.GetErrorMessageResource("InvalidFileName"); return(false); } var allowedFileTypes = HostSettingManager.Get(HostSettingNames.AllowedFileExtensions, String.Empty).Split(';'); var fileExt = Path.GetExtension(fileName); var fileOk = false; if (allowedFileTypes.Length > 0 && String.CompareOrdinal(allowedFileTypes[0], "*.*") == 0) { fileOk = true; } else { if (allowedFileTypes.Select(fileType => fileType.Substring(fileType.LastIndexOf("."))).Any(newfileType => newfileType.CompareTo(fileExt) == 0)) { fileOk = true; } } // valid file type if (!fileOk) { inValidReason = String.Format(LoggingManager.GetErrorMessageResource("InvalidFileType"), fileName); return(false); } // illegal filename characters if (Path.GetInvalidFileNameChars().Any(invalidFileNameChar => fileName.Contains(invalidFileNameChar))) { inValidReason = String.Format(LoggingManager.GetErrorMessageResource("InvalidFileName"), fileName); return(false); } return(true); }
/// <summary> /// Saves the custom field values. /// </summary> /// <param name="issueId">The issue id.</param> /// <param name="fields">The fields.</param> /// <returns></returns> public static bool SaveCustomFieldValues(Guid userId, List <UserCustomField> fields) { if (fields == null) { throw (new ArgumentOutOfRangeException("fields")); } try { DataProviderManager.Provider.SaveUserCustomFieldValues(userId, fields); return(true); } catch (Exception ex) { Log.Error(LoggingManager.GetErrorMessageResource("SaveCustomFieldValuesError"), ex); return(false); } }
/// <summary> /// Saves the issue /// </summary> /// <param name="entity">The issue to save.</param> /// <returns></returns> public static bool SaveOrUpdate(Issue entity) { if (entity == null) { throw new ArgumentNullException("entity"); } if (entity.ProjectId <= Globals.NEW_ID) { throw (new ArgumentException("The issue project id is invalid")); } if (string.IsNullOrEmpty(entity.Title)) { throw (new ArgumentException("The issue title cannot be empty or null")); } try { if (entity.Id <= Globals.NEW_ID) { var tempId = DataProviderManager.Provider.CreateNewIssue(entity); if (tempId > 0) { entity.Id = tempId; return(true); } return(false); } // this is here due to issue with updating the issue from the Mailbox reader // to fix the inline images. we don't have an http context so we are limited to what we can // do from here. in any case the mailbox reader is creating and updating concurrently so // we are not missing anything. if (HttpContext.Current != null) { //existing issue entity.LastUpdate = DateTime.Now; entity.LastUpdateUserName = Security.GetUserName(); var issueChanges = GetIssueChanges(GetById(entity.Id), entity); DataProviderManager.Provider.UpdateIssue(entity); UpdateHistory(issueChanges); IssueNotificationManager.SendIssueNotifications(entity.Id, issueChanges); if (entity.SendNewAssigneeNotification) { //add this user to notifications and send them a notification var notification = new IssueNotification { IssueId = entity.Id, NotificationUsername = entity.AssignedUserName, NotificationCulture = string.Empty }; var profile = new WebProfile().GetProfile(entity.AssignedUserName); if (profile != null && !string.IsNullOrWhiteSpace(profile.PreferredLocale)) { notification.NotificationCulture = profile.PreferredLocale; } IssueNotificationManager.SaveOrUpdate(notification); IssueNotificationManager.SendNewAssigneeNotification(notification); } } else { DataProviderManager.Provider.UpdateIssue(entity); } return(true); } catch (Exception ex) { Log.Error(LoggingManager.GetErrorMessageResource("SaveIssueError"), ex); return(false); } }
/// <summary> /// Saves this instance. /// </summary> /// <returns></returns> public static bool SaveOrUpdate(Project entity) { if (entity == null) { throw new ArgumentNullException("entity"); } if (string.IsNullOrEmpty(entity.Name)) { throw (new ArgumentException("The project name cannot be empty or null")); } if (entity.Id > 0) { return(Update(entity)); } var tempId = DataProviderManager.Provider.CreateNewProject(entity); if (tempId <= Globals.NEW_ID) { return(false); } entity.Id = tempId; CustomFieldManager.UpdateCustomFieldView(entity.Id); try { //create default roles for new project. RoleManager.CreateDefaultProjectRoles(entity.Id); } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error( string.Format( LoggingManager.GetErrorMessageResource("CouldNotCreateDefaultProjectRoles"), string.Format("ProjectID= {0}", entity.Id)), ex); } return(false); } //create attachment directory if (entity.AttachmentStorageType == IssueAttachmentStorageTypes.FileSystem) { var uploadPath = string.Concat("~", Globals.UPLOAD_FOLDER, entity.UploadPath); var fullUploadPath = HttpContext.Current.Server.MapPath(uploadPath); try { // BGN-1909 // Better santization of Upload Paths if (!Utilities.CheckUploadPath(uploadPath)) { throw new InvalidDataException(LoggingManager.GetErrorMessageResource("UploadPathInvalid")); } Directory.CreateDirectory(fullUploadPath); } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error( string.Format( LoggingManager.GetErrorMessageResource("CouldNotCreateUploadDirectory"), fullUploadPath), ex); } return(false); } } return(true); }
/// <summary> /// Saves this instance. /// </summary> /// <param name="entity">The issue attachment to save.</param> /// <returns></returns> public static bool SaveOrUpdate(IssueAttachment entity) { if (entity == null) { throw new ArgumentNullException("entity"); } if (entity.IssueId <= Globals.NEW_ID) { throw (new ArgumentException("Cannot save issue attachment, the issue id is invalid")); } if (String.IsNullOrEmpty(entity.FileName)) { throw (new ArgumentException("The attachment file name cannot be empty or null")); } var invalidReason = String.Empty; if (!IsValidFile(entity.FileName, out invalidReason)) { throw new ApplicationException(invalidReason); } //Start new save attachment code if (entity.Attachment.Length > 0) { // save the file to the upload directory var projectId = IssueManager.GetById(entity.IssueId).ProjectId; var project = ProjectManager.GetById(projectId); if (project.AllowAttachments) { entity.ContentType = entity.ContentType.Replace("/x-png", "/png"); if (entity.ContentType == "image/bmp") { using (var ms = new MemoryStream(entity.Attachment, 0, entity.Attachment.Length)) { ms.Write(entity.Attachment, 0, entity.Attachment.Length); var img = Image.FromStream(ms); img.Save(ms, ImageFormat.Png); ms.Seek(0, SeekOrigin.Begin); entity.Attachment = ms.ToArray(); } entity.ContentType = "image/png"; entity.FileName = Path.ChangeExtension(entity.FileName, "png"); } entity.Size = entity.Attachment.Length; if (HostSettingManager.Get(HostSettingNames.AttachmentStorageType, 0) == (int)IssueAttachmentStorageTypes.Database) { //save the attachment record to the database. var tempId = DataProviderManager.Provider.CreateNewIssueAttachment(entity); if (tempId > 0) { entity.Id = tempId; return(true); } return(false); } var projectPath = project.UploadPath; try { if (projectPath.Length == 0) { projectPath = project.Id.ToString(); } //throw new ApplicationException(String.Format(LoggingManager.GetErrorMessageResource("UploadPathNotDefined"), project.Name)); var attachmentGuid = Guid.NewGuid(); var attachmentBytes = entity.Attachment; entity.Attachment = null; //set attachment to null entity.FileName = String.Format("{0}.{1}{2}", Path.GetFileNameWithoutExtension(entity.FileName), attachmentGuid, Path.GetExtension(entity.FileName)); var uploadedFilePath = string.Empty; // added by WRH 2012-08-18 // this to fix the issue where attachments from the mailbox reader cannot be saved due to the lack of a http context. // we need to supply the actual folder path on the entity if (HttpContext.Current != null) { uploadedFilePath = string.Format(@"{0}\{1}", string.Format("{0}{1}", HostSettingManager.Get(HostSettingNames.AttachmentUploadPath), projectPath), entity.FileName); if (uploadedFilePath.StartsWith("~")) { uploadedFilePath = HttpContext.Current.Server.MapPath(uploadedFilePath); } } else { if (entity.ProjectFolderPath.Trim().Length > 0) { uploadedFilePath = string.Format("{0}\\{1}", entity.ProjectFolderPath, entity.FileName); } } //save the attachment record to the database. var tempId = DataProviderManager.Provider.CreateNewIssueAttachment(entity); if (tempId > 0) { entity.Id = tempId; //save file to file system var fi = new FileInfo(uploadedFilePath); if (!Directory.Exists(fi.DirectoryName)) { Directory.CreateDirectory(fi.DirectoryName); } File.WriteAllBytes(uploadedFilePath, attachmentBytes); return(true); } return(false); } catch (DirectoryNotFoundException ex) { if (Log.IsErrorEnabled) { Log.Error(String.Format(LoggingManager.GetErrorMessageResource("UploadPathNotFound"), projectPath), ex); } throw; } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error(ex.Message, ex); } throw; } } } return(false); }
/// <summary> /// Deletes the IssueAttachment. /// </summary> /// <param name="issueAttachmentId">The issue attachment id.</param> /// <returns></returns> public static bool Delete(int issueAttachmentId) { var att = GetById(issueAttachmentId); var issue = IssueManager.GetById(att.IssueId); var project = ProjectManager.GetById(issue.ProjectId); if (DataProviderManager.Provider.DeleteIssueAttachment(issueAttachmentId)) { try { var history = new IssueHistory { IssueId = att.IssueId, CreatedUserName = Security.GetUserName(), DateChanged = DateTime.Now, FieldChanged = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Attachment", "Attachment"), OldValue = att.FileName, NewValue = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Deleted", "Deleted"), TriggerLastUpdateChange = true }; IssueHistoryManager.SaveOrUpdate(history); var changes = new List <IssueHistory> { history }; IssueNotificationManager.SendIssueNotifications(att.IssueId, changes); } catch (Exception ex) { if (Log.IsErrorEnabled) { Log.Error(ex); } } if (HostSettingManager.Get(HostSettingNames.AttachmentStorageType, 0) == (int)IssueAttachmentStorageTypes.FileSystem) { //delete IssueAttachment from file system. try { if (string.IsNullOrEmpty(project.UploadPath)) { project.UploadPath = project.Id.ToString();//use project id as pathroot } var filePath = String.Format(@"{2}{0}\{1}", project.UploadPath, att.FileName, HostSettingManager.Get(HostSettingNames.AttachmentUploadPath)); if (filePath.StartsWith("~")) { filePath = HttpContext.Current.Server.MapPath(filePath); } if (File.Exists(filePath)) { File.Delete(filePath); } else { Log.Info(String.Format("Failed to locate file {0} to delete, it may have been moved or manually deleted", filePath)); } } catch (Exception ex) { //set user to log4net context, so we can use %X{user} in the appenders if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated) { MDC.Set("user", HttpContext.Current.User.Identity.Name); } if (Log.IsErrorEnabled) { Log.Error(String.Format("Error Deleting IssueAttachment - {0}", String.Format("{0}\\{1}", project.UploadPath, att.FileName)), ex); } throw new ApplicationException(LoggingManager.GetErrorMessageResource("AttachmentDeleteError"), ex); } } } return(true); }