using System; using System.Data; using System.Text; using System.Web.UI; using CMS.CMSHelper; using CMS.Controls; using CMS.GlobalHelper; using CMS.LicenseProvider; using CMS.SettingsProvider; using CMS.SiteProvider; using CMS.DocumentEngine; using CMS.UIControls; using CMS.WebAnalytics; using CMS.WorkflowEngine; using CMS.ExtendedControls; using TimeZoneInfo = CMS.SiteProvider.TimeZoneInfo; public partial class CMSModules_Content_Controls_UserContributions_ContributionList : CMSUserControl { #region "Variables" /// /// On after delete event. /// public event EventHandler OnAfterDelete = null; private bool mAllowInsert = true; private bool mAllowDelete = true; private bool mAllowEdit = true; private string mNewItemPageTemplate = String.Empty; private string mAllowedChildClasses = String.Empty; private string mAlternativeFormName = null; private string mValidationErrorMessage = null; private bool mCheckPermissions = false; private bool mCheckGroupPermissions = false; private bool mCheckDocPermissionsForInsert = true; private bool mLogActivity = false; private UserContributionAllowUserEnum mAllowUsers = UserContributionAllowUserEnum.DocumentOwner; private TreeNode mParentNode = null; /// /// Data properties variable. /// protected CMSDataProperties mDataProperties = new CMSDataProperties(); #endregion #region "Document properties" /// /// Component name /// public override string ComponentName { get { return base.ComponentName; } set { base.ComponentName = value; DocumentManager.ComponentName = value; editDoc.ComponentName = value; } } /// /// Document manager /// public override ICMSDocumentManager DocumentManager { get { return editDoc.DocumentManager; } } /// /// Class names. /// public string ClassNames { get { return mDataProperties.ClassNames; } set { mDataProperties.ClassNames = value; } } /// /// Combine with default culture. /// public bool CombineWithDefaultCulture { get { return mDataProperties.CombineWithDefaultCulture; } set { mDataProperties.CombineWithDefaultCulture = value; } } /// /// Culture code. /// public string CultureCode { get { return mDataProperties.CultureCode; } set { mDataProperties.CultureCode = value; } } /// /// Maximal relative level. /// public int MaxRelativeLevel { get { return mDataProperties.MaxRelativeLevel; } set { mDataProperties.MaxRelativeLevel = value; } } /// /// Order by clause. /// public string OrderBy { get { return mDataProperties.OrderBy; } set { mDataProperties.OrderBy = value; } } /// /// Nodes path. /// public string Path { get { return mDataProperties.Path; } set { mDataProperties.Path = value; } } /// /// Select only published nodes. /// public bool SelectOnlyPublished { get { return mDataProperties.SelectOnlyPublished; } set { mDataProperties.SelectOnlyPublished = value; } } /// /// Site name. /// public string SiteName { get { return mDataProperties.SiteName; } set { mDataProperties.SiteName = value; } } /// /// Where condition. /// public string WhereCondition { get { return mDataProperties.WhereCondition; } set { mDataProperties.WhereCondition = value; } } /// /// Gets or sets the columns to retrieve from DB. /// public string Columns { get { return ValidationHelper.GetString(GetValue("Columns"), null); } set { SetValue("Columns", value); } } #endregion #region "Public properties" /// /// Gets Edit form control. /// public CMSModules_Content_Controls_UserContributions_EditForm EditForm { get { return editDoc; } } /// /// Indicates whether the list of documents should be displayed. /// public bool DisplayList { get { return ValidationHelper.GetBoolean(ViewState["DisplayList"], true); } set { ViewState["DisplayList"] = value; } } /// /// Path for new created documents. /// public string NewDocumentPath { get { string newDocPath = ValidationHelper.GetString(ViewState["NewDocumentPath"], ""); // If new document path is not set, use source path if (newDocPath.Trim() == String.Empty) { newDocPath = Path; } // Ensure correct format of the path if (newDocPath.EndsWithCSafe("/%")) { newDocPath = newDocPath.Remove(newDocPath.Length - 2); } if (String.IsNullOrEmpty(newDocPath)) { newDocPath = "/"; } return newDocPath; } set { ViewState["NewDocumentPath"] = value; } } /// /// Indicates whether inserting new document is allowed. /// public bool AllowInsert { get { return mAllowInsert; } set { mAllowInsert = value; } } /// /// Indicates whether editing document is allowed. /// public bool AllowEdit { get { return mAllowEdit; } set { mAllowEdit = value; } } /// /// Indicates whether deleting document is allowed. /// public bool AllowDelete { get { return mAllowDelete; } set { mAllowDelete = (value && CheckGroupPermission("deletepages")); editDoc.AllowDelete = mAllowDelete; } } /// /// Page template the new items are assigned to. /// public string NewItemPageTemplate { get { return mNewItemPageTemplate; } set { mNewItemPageTemplate = value; } } /// /// Type of the child documents that are allowed to be created. /// public string AllowedChildClasses { get { return mAllowedChildClasses; } set { mAllowedChildClasses = value; } } /// /// Alternative form name. /// public string AlternativeFormName { get { return mAlternativeFormName; } set { mAlternativeFormName = value; } } /// /// Form validation error message. /// public string ValidationErrorMessage { get { return mValidationErrorMessage; } set { mValidationErrorMessage = value; } } /// /// Indicates whether permissions should be checked. /// public bool CheckPermissions { get { return mCheckPermissions; } set { mCheckPermissions = value; } } /// /// Indicates whether group permissions should be checked. /// public bool CheckGroupPermissions { get { return mCheckGroupPermissions; } set { mCheckGroupPermissions = value; } } /// /// Indicates if document type permissions are required to create new document. /// public bool CheckDocPermissionsForInsert { get { return mCheckDocPermissionsForInsert; } set { mCheckDocPermissionsForInsert = value; } } /// /// Which group of users can work with the documents. /// public UserContributionAllowUserEnum AllowUsers { get { return mAllowUsers; } set { mAllowUsers = value; } } /// /// Gets or sets New item button label. /// public string NewItemButtonText { get { return DataHelper.GetNotEmpty(GetValue("NewItemButtonText"), "ContributionList.lnkNewDoc"); } set { SetValue("NewItemButtonText", value); btnNewDoc.ResourceString = value; } } /// /// Gets or sets List button label. /// public string ListButtonText { get { return DataHelper.GetNotEmpty(GetValue("ListButtonText"), "ContributionList.lnkDocs"); } set { SetValue("ListButtonText", value); btnList.ResourceString = value; } } /// /// Indicates whether activity logging is enabled. /// public bool LogActivity { get { return mLogActivity; } set { mLogActivity = value; editDoc.LogActivity = value; } } #endregion #region "Private properties" /// /// Parent node. /// private TreeNode ParentNode { get { return mParentNode ?? (mParentNode = GetParentNode()); } } /// /// Parent node id. /// private int ParentNodeID { get { return (ParentNode == null ? 0 : ParentNode.NodeID); } } #endregion #region "Methods" protected void Page_Load(object sender, EventArgs e) { // Check license LicenseHelper.CheckFeatureAndRedirect(URLHelper.GetCurrentDomain(), FeatureEnum.UserContributions); mDataProperties.ParentControl = this; // Reload data ReloadData(); // Control initialization gridDocs.OnExternalDataBound += gridDocs_OnExternalDataBound; gridDocs.OnAction += gridDocs_OnAction; gridDocs.GridView.CssClass = "ContributionsGrid"; gridDocs.IsLiveSite = IsLiveSite; btnNewDoc.ResourceString = NewItemButtonText; btnList.ResourceString = ListButtonText; // Hide/Show edit document form bool editVisible = (editDoc.NodeID > 0); pnlEdit.Visible = editVisible; editDoc.SiteName = SiteName; editDoc.CultureCode = CultureCode; editDoc.LogActivity = LogActivity; } protected override void OnPreRender(EventArgs e) { // Register the scripts ScriptHelper.RegisterClientScriptBlock(this, typeof(string), "ContributionList_" + ClientID, ltlScript.Text); ltlScript.Text = String.Empty; base.OnPreRender(e); } /// /// Checks if columns list contains required columns. /// private string EnsureColumns() { string currentColumns = Columns; string requiredColumns = "DocumentName,Published,DocumentModifiedWhen,DocumentWorkflowStepID"; if (CheckPermissions) { requiredColumns += ",SiteName,ClassName,NodeACLID,NodeSiteID,NodeOwner"; } if (!String.IsNullOrEmpty(currentColumns)) { currentColumns = "," + currentColumns.Replace(" ", String.Empty) + ","; if (currentColumns.Length > 2) { StringBuilder required = new StringBuilder(); foreach (string col in requiredColumns.Split(',')) { if (currentColumns.IndexOfCSafe("," + col + ",", 0, true) == -1) { required.Append(col); required.Append(","); } } currentColumns += required.ToString(); currentColumns = currentColumns.Trim(','); } else { currentColumns = null; } } return currentColumns; } private void ReloadData() { if (StopProcessing) { // Do nothing gridDocs.StopProcessing = true; editDoc.StopProcessing = true; } else { if (((AllowUsers == UserContributionAllowUserEnum.Authenticated) || (AllowUsers == UserContributionAllowUserEnum.DocumentOwner)) && !CMSContext.CurrentUser.IsAuthenticated()) { // Not authenticated, do not display anything pnlList.Visible = false; pnlEdit.Visible = false; StopProcessing = true; } else { SetContext(); // Hide document list gridDocs.Visible = false; // If the list of documents should be displayed ... if (DisplayList) { // Get all documents of the current user TreeProvider tree = new TreeProvider(CMSContext.CurrentUser); // Generate additional where condition string classWhere = null; if (!String.IsNullOrEmpty(ClassNames)) { // Remove ending semicolon classWhere = ClassNames.TrimEnd(';'); // Replace single apostrophs classWhere = SqlHelperClass.GetSafeQueryString(classWhere, false); // Replace ; with ',' classWhere = classWhere.Replace(";", "','"); if (!String.IsNullOrEmpty(classWhere)) { classWhere = String.Format("ClassName IN ('{0}')", classWhere); } } string where = SqlHelperClass.AddWhereCondition(WhereCondition, classWhere); // Add user condition if (AllowUsers == UserContributionAllowUserEnum.DocumentOwner) { where = SqlHelperClass.AddWhereCondition(where, "NodeOwner = " + CMSContext.CurrentUser.UserID); } // Ensure that required columns are included in "Columns" list string columns = EnsureColumns(); // Get the documents DataSet ds = DocumentHelper.GetDocuments(SiteName, CMSContext.ResolveCurrentPath(Path), CultureCode, CombineWithDefaultCulture, null, where, OrderBy, MaxRelativeLevel, SelectOnlyPublished, 0, columns, tree); if (CheckPermissions) { ds = TreeSecurityProvider.FilterDataSetByPermissions(ds, NodePermissionsEnum.Read, CMSContext.CurrentUser); } if (!DataHelper.DataSourceIsEmpty(ds)) { // Display and initialize grid if datasource is not empty gridDocs.Visible = true; gridDocs.DataSource = ds; gridDocs.OrderBy = OrderBy; editDoc.AlternativeFormName = AlternativeFormName; } } bool isAuthorizedToCreateDoc = false; if (ParentNode != null) { // Check if single class name is set string className = (!string.IsNullOrEmpty(AllowedChildClasses) && !AllowedChildClasses.Contains(";")) ? AllowedChildClasses : null; // Check user's permission to create new document if allowed isAuthorizedToCreateDoc = !CheckPermissions || CMSContext.CurrentUser.IsAuthorizedToCreateNewDocument(ParentNodeID, className); // Check group's permission to create new document if allowed isAuthorizedToCreateDoc &= CheckGroupPermission("createpages"); if (!CheckDocPermissionsForInsert && CheckPermissions) { // If document permissions are not required check create permission on parent document isAuthorizedToCreateDoc = CMSContext.CurrentUser.IsAuthorizedPerDocument(ParentNode, NodePermissionsEnum.Create) == AuthorizationResultEnum.Allowed; } if (AllowUsers == UserContributionAllowUserEnum.DocumentOwner) { // Do not allow documents creation under virtual user if (CMSContext.CurrentUser.IsVirtual) { isAuthorizedToCreateDoc = false; } else { // Check if user is document owner (or global admin) isAuthorizedToCreateDoc = isAuthorizedToCreateDoc && ((ParentNode.NodeOwner == CMSContext.CurrentUser.UserID) || CMSContext.CurrentUser.IsGlobalAdministrator); } } } // Enable/disable inserting new document pnlNewDoc.Visible = (isAuthorizedToCreateDoc && AllowInsert); if (!gridDocs.Visible && !pnlNewDoc.Visible && pnlList.Visible) { // Not authenticated to create new docs and grid is hidden StopProcessing = true; } ReleaseContext(); } } } /// /// Initializes and shows edit form with available documents. /// protected void btnNewDoc_Click(object sender, EventArgs e) { // Initialize EditForm control editDoc.EnableViewState = true; editDoc.AllowedChildClasses = AllowedChildClasses; editDoc.AllowDelete = AllowDelete && CheckGroupPermission("deletepages"); editDoc.NewItemPageTemplate = NewItemPageTemplate; editDoc.CheckPermissions = CheckPermissions; editDoc.CheckDocPermissionsForInsert = CheckDocPermissionsForInsert; editDoc.Action = "new"; // Set parent nodeId editDoc.NodeID = ParentNodeID; editDoc.ClassID = 0; editDoc.AlternativeFormName = AlternativeFormName; editDoc.ValidationErrorMessage = ValidationErrorMessage; editDoc.LogActivity = LogActivity; pnlEdit.Visible = true; pnlList.Visible = false; } /// /// Gets parent node ID. /// private TreeNode GetParentNode() { TreeProvider tree = new TreeProvider(CMSContext.CurrentUser); return tree.SelectSingleNode(SiteName, CMSContext.ResolveCurrentPath(NewDocumentPath), TreeProvider.ALL_CULTURES); } /// /// Displays document list and hides edit form. /// protected void btnList_Click(object sender, EventArgs e) { // EditDoc control registers progress script on PreRender event - but when btnList button is clicked, EditDoc control gets hidden, so // progress script needs to be registered again here to hide progress layout properly. if (editDoc.UseProgressScript) { ScriptHelper.RegisterProgress(Page); } pnlList.Visible = true; pnlEdit.Visible = false; editDoc.Action = ""; editDoc.NodeID = 0; editDoc.EnableViewState = false; } /// /// UniGrid action buttons event handler. /// protected void gridDocs_OnAction(string actionName, object actionArgument) { switch (actionName.ToLowerCSafe()) { // Edit document case "edit": // Check group's permission to edit document if allowed if (CheckGroupPermission("editpages")) { editDoc.NodeID = ValidationHelper.GetInteger(actionArgument, 0); editDoc.Action = "edit"; editDoc.CheckPermissions = CheckPermissions; editDoc.AllowDelete = AllowDelete && CheckGroupPermission("deletepages"); pnlEdit.Visible = true; pnlList.Visible = false; } break; // Delete document case "delete": // Check banned IP if (!BannedIPInfoProvider.IsAllowed(CMSContext.CurrentSiteName, BanControlEnum.AllNonComplete)) { AddAlert(GetString("general.bannedip")); return; } TreeProvider tree = new TreeProvider(CMSContext.CurrentUser); // Delete specified node int documentId = ValidationHelper.GetInteger(actionArgument, 0); TreeNode node = DocumentHelper.GetDocument(documentId, tree); if (node != null) { // Check user's permission to delete document if allowed bool hasUserDeletePermission = !CheckPermissions || IsUserAuthorizedToDeleteDocument(node); // Check group's permission to delete document if allowed hasUserDeletePermission &= CheckGroupPermission("deletepages"); if (hasUserDeletePermission) { DocumentHelper.DeleteDocument(node, tree, false, false, true); if (LogActivity) { Activity activity = new ActivityUserContributionDelete(node, node.GetDocumentName(), CMSContext.ActivityEnvironmentVariables); activity.Log(); } // Fire OnAfterDelete RaiseOnAfterDelete(); ReloadData(); } // Access denied - not authorized to delete the document else { AddAlert(String.Format(GetString("cmsdesk.notauthorizedtodeletedocument"), node.NodeAliasPath)); return; } } break; } } /// /// UniGrid external data bound. /// private object gridDocs_OnExternalDataBound(object sender, string sourceName, object parameter) { sourceName = sourceName.ToLowerCSafe(); switch (sourceName) { // Column 'DocumentWorkflowStepID' case "documentworkflowstepid": int stepId = ValidationHelper.GetInteger(parameter, 0); if (stepId > 0) { // Get workflow step display name WorkflowStepInfo wsi = WorkflowStepInfoProvider.GetWorkflowStepInfo(stepId); if (wsi != null) { return ResHelper.LocalizeString(wsi.StepDisplayName); } } break; // Column 'Published' case "published": bool published = ValidationHelper.GetBoolean(parameter, true); return (published ? GetString("General.Yes") : GetString("General.No")); case "documentmodifiedwhen": case "documentmodifiedwhentooltip": TimeZoneInfo tzi = null; // Get current time for user contribution list on live site string result = CMSContext.GetDateTimeForControl(this, ValidationHelper.GetDateTime(parameter, DateTimeHelper.ZERO_TIME), out tzi).ToString(); // Display time zone shift if needed if ((tzi != null) && TimeZoneHelper.TimeZonesEnabled()) { if (sourceName.EndsWithCSafe("tooltip")) { result = TimeZoneHelper.GetGMTLongStringOffset(tzi); } else { result += TimeZoneHelper.GetGMTStringOffset(" (GMT{0:+00.00;-00.00})", tzi); } } return result; // Action 'edit' case "edit": ((Control)sender).Visible = AllowEdit && CheckGroupPermission("editpages"); break; // Action 'delete' case "delete": ((Control)sender).Visible = AllowDelete && CheckGroupPermission("deletepages"); break; } return parameter; } /// /// Checks whether the user is authorized to delete document. /// /// Document node protected bool IsUserAuthorizedToDeleteDocument(TreeNode node) { // Check delete permission bool isAuthorized = CMSContext.CurrentUser.IsAuthorizedPerDocument(node, new NodePermissionsEnum[] { NodePermissionsEnum.Delete, NodePermissionsEnum.Read }) == AuthorizationResultEnum.Allowed; return isAuthorized; } /// /// Adds the alert message to the output request window. /// /// Message to display private void AddAlert(string message) { ScriptHelper.RegisterStartupScript(this, typeof(string), message.GetHashCode().ToString(), ScriptHelper.GetAlertScript(message)); } /// /// Returns true if group permissions should be checked and specified permission is allowed in current group. /// Also returns true if group permissions should not be checked. /// /// Permission to check (createpages, editpages, deletepages) protected bool CheckGroupPermission(string permissionName) { if (CheckGroupPermissions && !CMSContext.CurrentUser.IsGlobalAdministrator) { // Get current group ID int groupId = ModuleCommands.CommunityGetCurrentGroupID(); if (groupId > 0) { // Returns true if current user is authorized for specified action in current group return ModuleCommands.CommunityCheckGroupPermission(permissionName, groupId) || CMSContext.CurrentUser.IsGroupAdministrator(groupId); } return false; } return true; } /// /// Raises the OnAfterDelete event. /// private void RaiseOnAfterDelete() { if (OnAfterDelete != null) { OnAfterDelete(this, null); } } #endregion }