/// <summary> /// Render the treeview with the first two levels of albums that are viewable to the logged on user. /// </summary> private TreeView Generate() { _tv = new TreeView(); foreach (IAlbum rootAlbum in GetRootAlbums()) { // Add root node. TreeNode rootNode = new TreeNode(); string albumTitle = GetRootAlbumTitle(rootAlbum); rootNode.Text = albumTitle; rootNode.ToolTip = albumTitle; rootNode.Id = String.Concat("tv_", rootAlbum.Id.ToString(CultureInfo.InvariantCulture)); rootNode.DataId = rootAlbum.Id.ToString(CultureInfo.InvariantCulture); rootNode.Expanded = true; if (!String.IsNullOrEmpty(_tvOptions.NavigateUrl)) { rootNode.NavigateUrl = Utils.AddQueryStringParameter(_tvOptions.NavigateUrl, String.Concat("aid=", rootAlbum.Id.ToString(CultureInfo.InvariantCulture))); } bool isAlbumSelectable = !rootAlbum.IsVirtualAlbum; rootNode.ShowCheckBox = isAlbumSelectable && _tvOptions.ShowCheckbox; //rootNode.Selectable = isAlbumSelectable; //if (!isAlbumSelectable) rootNode.HoverCssClass = String.Empty; // Select and check this node if needed. if (isAlbumSelectable && (_tvOptions.SelectedAlbumIds.Contains(rootAlbum.Id))) { //_tv.NodesToCheckIdArray.Add(rootNode.Id); //tv.SelectedNode = rootNode; //rootNode.Checked = true; } _tv.Nodes.Add(rootNode); // Add the first level of albums below the root album. BindAlbumToTreeview(rootAlbum.GetChildGalleryObjects(GalleryObjectType.Album, !Utils.IsAuthenticated).ToSortedList(), rootNode, false); // Only display the root node if it is selectable or we added any children to it; otherwise, remove it. if (!rootNode.Selectable && rootNode.Nodes.Count == 0) { _tv.Nodes.Remove(rootNode); } } // Make sure all specified albums are visible and checked. foreach (int albumId in _tvOptions.SelectedAlbumIds) { IAlbum album = AlbumController.LoadAlbumInstance(albumId, false); if (Utils.IsUserAuthorized(_tvOptions.RequiredSecurityPermissions, RoleController.GetGalleryServerRolesForUser(), album.Id, album.GalleryId, album.IsPrivate, SecurityActionsOption.RequireOne, album.IsVirtualAlbum)) { BindSpecificAlbumToTreeview(album); } } return(_tv); }
/// <summary> /// Creates an album, assigns the user name as the owner, saves it, and returns the newly created album. /// A profile entry is created containing the album ID. Returns null if the ID specified in the gallery settings /// for the parent album does not represent an existing album. That is, returns null if <see cref="IGallerySettings.UserAlbumParentAlbumId" /> /// does not match an existing album. /// </summary> /// <param name="userName">The user name representing the user who is the owner of the album.</param> /// <param name="galleryId">The gallery ID for the gallery in which the album is to be created.</param> /// <returns> /// Returns the newly created user album. It has already been persisted to the database. /// Returns null if the ID specified in the gallery settings for the parent album does not represent an existing album. /// That is, returns null if <see cref="IGallerySettings.UserAlbumParentAlbumId" /> /// does not match an existing album. /// </returns> public static IAlbum CreateUserAlbum(string userName, int galleryId) { IGallerySettings gallerySetting = Factory.LoadGallerySetting(galleryId); string albumNameTemplate = gallerySetting.UserAlbumNameTemplate; IAlbum parentAlbum; try { parentAlbum = AlbumController.LoadAlbumInstance(gallerySetting.UserAlbumParentAlbumId, false); } catch (InvalidAlbumException ex) { // The parent album does not exist. Record the error and return null. string galleryDescription = Utils.HtmlEncode(Factory.LoadGallery(gallerySetting.GalleryId).Description); string msg = String.Format(CultureInfo.CurrentCulture, Resources.GalleryServerPro.Error_User_Album_Parent_Invalid_Ex_Msg, galleryDescription, gallerySetting.UserAlbumParentAlbumId); AppErrorController.LogError(new WebException(msg, ex), galleryId); return(null); } IAlbum album = null; try { album = Factory.CreateEmptyAlbumInstance(parentAlbum.GalleryId); album.Title = albumNameTemplate.Replace("{UserName}", userName); album.Summary = gallerySetting.UserAlbumSummaryTemplate; album.OwnerUserName = userName; //newAlbum.ThumbnailMediaObjectId = 0; // not needed album.Parent = parentAlbum; album.IsPrivate = parentAlbum.IsPrivate; GalleryObjectController.SaveGalleryObject(album, userName); SaveAlbumIdToProfile(album.Id, userName, album.GalleryId); HelperFunctions.PurgeCache(); } catch { if (album != null) { album.Dispose(); } throw; } return(album); }
/// <summary> /// Bind the heirarchical list of albums to the specified treeview node. /// </summary> /// <param name="existingParentNode">The treeview node to add the first album in the stack to.</param> /// <param name="albumParents">A list of albums where the first album should be a child of the specified treeview /// node, and each subsequent album is a child of the previous album.</param> private void BindSpecificAlbumToTreeview(TreeNode existingParentNode, Stack <IAlbum> albumParents) { // Assumption: The first album in the stack is a child of the existingParentNode node. existingParentNode.Expanded = true; // For each album in the heirarchy of albums to the current album, add the album and all its siblings to the // treeview. foreach (IAlbum album in albumParents) { if (existingParentNode.Nodes.Count == 0) { // Add all the album's siblings to the treeview. var childAlbums = AlbumController.LoadAlbumInstance(Convert.ToInt32(existingParentNode.DataId, CultureInfo.InvariantCulture), true).GetChildGalleryObjects(GalleryObjectType.Album, !Utils.IsAuthenticated).ToSortedList(); BindAlbumToTreeview(childAlbums, existingParentNode, false); } // Now find the album in the siblings we just added that matches the current album in the stack. // Set that album as the new parent and expand it. TreeNode nodeInAlbumHeirarchy = null; foreach (TreeNode node in existingParentNode.Nodes) { if (node.DataId.Equals(album.Id.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal)) { nodeInAlbumHeirarchy = node; nodeInAlbumHeirarchy.Expanded = true; break; } } if (nodeInAlbumHeirarchy == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "Album ID {0} is not a child of the treeview node representing album ID {1}.", album.Id, Convert.ToInt32(existingParentNode.DataId, CultureInfo.InvariantCulture))); } existingParentNode = nodeInAlbumHeirarchy; } existingParentNode.Expanded = false; }
/// <summary> /// Gets a list of top-level albums to display in the treeview. There will be a maximum of one for each gallery. /// If the <see cref="TreeViewOptions.RootAlbumId" /> property is assigned, that album is returned and the <see cref="Galleries" /> property is /// ignored. /// </summary> /// <returns>Returns a list of top-level albums to display in the treeview.</returns> private IEnumerable <IAlbum> GetRootAlbums() { List <IAlbum> rootAlbums = new List <IAlbum>(1); if (_tvOptions.RootAlbumId > 0) { rootAlbums.Add(AlbumController.LoadAlbumInstance(_tvOptions.RootAlbumId, true)); } else { foreach (IGallery gallery in _tvOptions.Galleries) { var rootAlbum = Factory.LoadRootAlbum(gallery.GalleryId, RoleController.GetGalleryServerRolesForUser(), Utils.IsAuthenticated); if (rootAlbum != null) { rootAlbums.Add(rootAlbum); } } } return(rootAlbums); }
private static List <ActionResult> CreateMediaObjectFromFile(AddMediaObjectSettings options) { string sourceFilePath = Path.Combine(AppSetting.Instance.PhysicalApplicationPath, GlobalConstants.TempUploadDirectory, options.FileNameOnServer); try { IAlbum album = AlbumController.LoadAlbumInstance(options.AlbumId, true); if ((Path.GetExtension(options.FileName).Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (options.ExtractZipFile)) { // Extract the files from the zipped file. using (ZipUtility zip = new ZipUtility(Utils.UserName, RoleController.GetGalleryServerRolesForUser())) { using (FileStream fs = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read)) { return(zip.ExtractZipFile(fs, album, options.DiscardOriginalFile)); } } } else { string albumPhysicalPath = album.FullPhysicalPathOnDisk; string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, options.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); MoveFile(filepath, sourceFilePath); ActionResult result = CreateMediaObject(filepath, album, options); return(new List <ActionResult>() { result }); } } catch (Exception ex) { AppErrorController.LogError(ex); return(new List <ActionResult>() { new ActionResult() { Title = options.FileName, Status = ActionResultStatus.Error, Message = "The event log may have additional details." } }); } finally { try { // If the file still exists in the temp directory, delete it. Typically this happens when we've // extracted the contents of a zip file (since other files will have already been moved to the dest album.) if (File.Exists(sourceFilePath)) { File.Delete(sourceFilePath); } } catch (IOException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory catch (UnauthorizedAccessException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory } }
/// <summary> /// Update the album with the specified properties in the albumEntity parameter. The title is validated before /// saving, and may be altered to conform to business rules, such as removing HTML tags. After the object is persisted /// to the data store, the albumEntity parameter is updated with the latest properties from the album object and returned. /// If the user is not authorized to edit the album, no action is taken. /// </summary> /// <param name="albumEntity">An AlbumWebEntity instance containing data to be persisted to the data store.</param> /// <returns>Returns an AlbumWebEntity instance containing the data as persisted to the data store. Some properties, /// such as the Title property, may be slightly altered to conform to validation rules.</returns> /// <exception cref="ArgumentNullException">Thrown when <paramref name="albumEntity" /> is null.</exception> public static AlbumWebEntity UpdateAlbumInfo(AlbumWebEntity albumEntity) { if (albumEntity == null) { throw new ArgumentNullException("albumEntity"); } if (albumEntity.Owner == Resources.GalleryServerPro.UC_Album_Header_Edit_Album_No_Owner_Text) { albumEntity.Owner = String.Empty; } IAlbum album = AlbumController.LoadAlbumInstance(albumEntity.Id, false, true); // Update remaining properties if user has edit album permission. if (Utils.IsUserAuthorized(SecurityActions.EditAlbum, album.Id, album.GalleryId, album.IsPrivate)) { if (album.Title != albumEntity.Title) { IGallerySettings gallerySetting = Factory.LoadGallerySetting(album.GalleryId); album.Title = Utils.CleanHtmlTags(albumEntity.Title, album.GalleryId); if ((!album.IsRootAlbum) && (gallerySetting.SynchAlbumTitleAndDirectoryName)) { // Root albums do not have a directory name that reflects the album's title, so only update this property for non-root albums. album.DirectoryName = HelperFunctions.ValidateDirectoryName(album.Parent.FullPhysicalPath, album.Title, gallerySetting.DefaultAlbumDirectoryNameLength); } } album.Summary = Utils.CleanHtmlTags(albumEntity.Summary, album.GalleryId); album.DateStart = albumEntity.DateStart.Date; album.DateEnd = albumEntity.DateEnd.Date; if (albumEntity.IsPrivate != album.IsPrivate) { if (!albumEntity.IsPrivate && album.Parent.IsPrivate) { throw new NotSupportedException("Cannot make album public: It is invalid to make an album public when it's parent album is private."); } album.IsPrivate = albumEntity.IsPrivate; SynchIsPrivatePropertyOnChildGalleryObjects(album); } // If the owner has changed, update it, but only if the user is administrator. if (albumEntity.Owner != album.OwnerUserName) { if (Utils.IsUserAuthorized(SecurityActions.AdministerSite | SecurityActions.AdministerGallery, RoleController.GetGalleryServerRolesForUser(), album.Id, album.GalleryId, album.IsPrivate)) { if (!String.IsNullOrEmpty(album.OwnerUserName)) { // Another user was previously assigned as owner. Delete role since this person will no longer be the owner. RoleController.DeleteGalleryServerProRole(album.OwnerRoleName); } if (UserController.GetUsersCurrentUserCanView(album.GalleryId).Contains(albumEntity.Owner) || String.IsNullOrEmpty(albumEntity.Owner)) { // GalleryObjectController.SaveGalleryObject will make sure there is a role created for this user. album.OwnerUserName = albumEntity.Owner; } } } GalleryObjectController.SaveGalleryObject(album); HelperFunctions.PurgeCache(); // Refresh the entity object with the data from the album object, in case something changed. For example, // some javascript or HTML may have been removed from the Title or Summary fields. albumEntity.Title = album.Title; albumEntity.Summary = album.Summary; albumEntity.DateStart = album.DateStart; albumEntity.DateEnd = album.DateEnd; albumEntity.IsPrivate = album.IsPrivate; albumEntity.Owner = album.OwnerUserName; } return(albumEntity); }
/// <summary> /// Get a reference to the highest level album in the specified <paramref name="galleryId" /> the current user has permission to /// add albums and/or media objects to. Returns null if no album meets this criteria. /// </summary> /// <param name="verifyAddAlbumPermissionExists">Specifies whether the current user must have permission to add child albums /// to the album.</param> /// <param name="verifyAddMediaObjectPermissionExists">Specifies whether the current user must have permission to add media objects /// to the album.</param> /// <param name="galleryId">The ID of the gallery.</param> /// <returns> /// Returns a reference to the highest level album the user has permission to add albums and/or media objects to. /// </returns> public static IAlbum GetHighestLevelAlbumWithAddPermission(bool verifyAddAlbumPermissionExists, bool verifyAddMediaObjectPermissionExists, int galleryId) { // Step 1: Loop through the roles and compile a list of album IDs where the role has the required permission. // If the verifyAddAlbumPermissionExists parameter is true, then the user must have permission to add child albums. // If the verifyAddMediaObjectPermissionExists parameter is true, then the user must have permission to add media objects. // If either parameter is false, then the absense of that permission does not disqualify an album. IGallery gallery = Factory.LoadGallery(galleryId); List <int> rootAlbumIdsWithPermission = new List <int>(); foreach (IGalleryServerRole role in RoleController.GetGalleryServerRolesForUser()) { if (role.Galleries.Contains(gallery)) { bool albumPermGranted = (verifyAddAlbumPermissionExists ? role.AllowAddChildAlbum : true); bool mediaObjectPermGranted = (verifyAddMediaObjectPermissionExists ? role.AllowAddMediaObject : true); if (albumPermGranted && mediaObjectPermGranted) { // This role satisfies the requirements, so add each album to the list. foreach (int albumId in role.RootAlbumIds) { if (!rootAlbumIdsWithPermission.Contains(albumId)) { rootAlbumIdsWithPermission.Add(albumId); } } } } } // Step 2: Loop through our list of album IDs. If any album belongs to another gallery, remove it. If any album has an ancestor // that is also in the list, then remove it. We only want a list of top level albums. List <int> albumIdsToRemove = new List <int>(); foreach (int albumIdWithPermission in rootAlbumIdsWithPermission) { IGalleryObject album = AlbumController.LoadAlbumInstance(albumIdWithPermission, false); if (album.GalleryId != galleryId) { // Album belongs to another gallery. Mark it for deletion. albumIdsToRemove.Add(albumIdWithPermission); } else { while (true) { album = album.Parent as IAlbum; if (album == null) { break; } if (rootAlbumIdsWithPermission.Contains(album.Id)) { // Album has an ancestor that is also in the list. Mark it for deletion. albumIdsToRemove.Add(albumIdWithPermission); break; } } } } foreach (int albumId in albumIdsToRemove) { rootAlbumIdsWithPermission.Remove(albumId); } // Step 3: Starting with the root album, start iterating through the child albums. When we get to // one in our list, we can conclude that is the highest level album for which the user has create album permission. return(FindFirstMatchingAlbumRecursive(Factory.LoadRootAlbumInstance(galleryId), rootAlbumIdsWithPermission)); }
/// <summary> /// Get a reference to the highest level album in the specified <paramref name="galleryId" /> the current user has permission /// to add albums to. Returns null if no album meets this criteria. /// </summary> /// <param name="galleryId">The ID of the gallery.</param> /// <returns>Returns a reference to the highest level album the user has permission to add albums to.</returns> public static IAlbum GetHighestLevelAlbumWithCreatePermission(int galleryId) { // Step 1: Loop through the roles and compile a list of album IDs where the role has create album permission. IGallery gallery = Factory.LoadGallery(galleryId); List <int> rootAlbumIdsWithCreatePermission = new List <int>(); foreach (IGalleryServerRole role in RoleController.GetGalleryServerRolesForUser()) { if (role.Galleries.Contains(gallery)) { if (role.AllowAddChildAlbum) { foreach (int albumId in role.RootAlbumIds) { if (!rootAlbumIdsWithCreatePermission.Contains(albumId)) { rootAlbumIdsWithCreatePermission.Add(albumId); } } } } } // Step 2: Loop through our list of album IDs. If any album belongs to another gallery, remove it. If any album has an ancestor // that is also in the list, then remove it. We only want a list of top level albums. List <int> albumIdsToRemove = new List <int>(); foreach (int albumIdWithCreatePermission in rootAlbumIdsWithCreatePermission) { IGalleryObject album = AlbumController.LoadAlbumInstance(albumIdWithCreatePermission, false); if (album.GalleryId != galleryId) { // Album belongs to another gallery. Mark it for deletion. albumIdsToRemove.Add(albumIdWithCreatePermission); } else { while (true) { album = album.Parent as IAlbum; if (album == null) { break; } if (rootAlbumIdsWithCreatePermission.Contains(album.Id)) { // Album has an ancestor that is also in the list. Mark it for deletion. albumIdsToRemove.Add(albumIdWithCreatePermission); break; } } } } foreach (int albumId in albumIdsToRemove) { rootAlbumIdsWithCreatePermission.Remove(albumId); } // Step 3: Starting with the root album, start iterating through the child albums. When we get to // one in our list, we can conclude that is the highest level album for which the user has create album permission. return(FindFirstMatchingAlbumRecursive(Factory.LoadRootAlbumInstance(galleryId), rootAlbumIdsWithCreatePermission)); }
/// <summary> /// Creates the media object from the file specified in <paramref name="options" />. /// </summary> /// <param name="options">The options.</param> /// <returns>List{ActionResult}.</returns> /// <exception cref="Events.CustomExceptions.GallerySecurityException">Thrown when user is not authorized to add a media object to the album.</exception> /// <remarks>This function can be invoked from a thread that does not have access to the current HTTP context (for example, when /// uploading ZIP files). Therefore, be sure nothing in this body (or the functions it calls) uses HttpContext.Current, or at /// least check it for null first.</remarks> private static List <ActionResult> CreateMediaObjectFromFile(AddMediaObjectSettings options) { string sourceFilePath = Path.Combine(AppSetting.Instance.PhysicalApplicationPath, GlobalConstants.TempUploadDirectory, options.FileNameOnServer); try { IAlbum album = AlbumController.LoadAlbumInstance(options.AlbumId, true, true); if (HttpContext.Current != null) { SecurityManager.ThrowIfUserNotAuthorized(SecurityActions.AddMediaObject, RoleController.GetGalleryServerRolesForUser(), album.Id, album.GalleryId, Utils.IsAuthenticated, album.IsPrivate, album.IsVirtualAlbum); } else { // We are extracting files from a zip archive (we know this because this is the only scenario that happens on a background // thread where HttpContext.Current is null). Tweak the security check slightly to ensure the HTTP context isn't used. // The changes are still secure because options.CurrentUserName is assigned in the server's API method. SecurityManager.ThrowIfUserNotAuthorized(SecurityActions.AddMediaObject, RoleController.GetGalleryServerRolesForUser(options.CurrentUserName), album.Id, album.GalleryId, !String.IsNullOrWhiteSpace(options.CurrentUserName), album.IsPrivate, album.IsVirtualAlbum); } var extension = Path.GetExtension(options.FileName); if (extension != null && ((extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (options.ExtractZipFile))) { List <ActionResult> result; // Extract the files from the zipped file. using (var zip = new ZipUtility(options.CurrentUserName, RoleController.GetGalleryServerRolesForUser(options.CurrentUserName))) { using (var fs = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read)) { result = zip.ExtractZipFile(fs, album, options.DiscardOriginalFile); } } album.SortAsync(true, options.CurrentUserName, true); return(result); } else { string albumPhysicalPath = album.FullPhysicalPathOnDisk; string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, options.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); MoveFile(filepath, sourceFilePath); ActionResult result = CreateMediaObject(filepath, album, options); album.Sort(true, options.CurrentUserName); return(new List <ActionResult> { result }); } } catch (Exception ex) { AppEventController.LogError(ex); return(new List <ActionResult> { new ActionResult { Title = options.FileName, Status = ActionResultStatus.Error.ToString(), Message = "The event log may have additional details." } }); } finally { try { // If the file still exists in the temp directory, delete it. Typically this happens when we've // extracted the contents of a zip file (since other files will have already been moved to the dest album.) if (File.Exists(sourceFilePath)) { File.Delete(sourceFilePath); } } catch (IOException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory catch (UnauthorizedAccessException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory } }