using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Security.Principal;
using System.Text;
using CMS.CMSHelper;
using CMS.DocumentEngine;
using CMS.EmailEngine;
using CMS.EventLog;
using CMS.FormEngine;
using CMS.GlobalHelper;
using CMS.LicenseProvider;
using CMS.ResourceManager;
using CMS.SettingsProvider;
using CMS.SiteProvider;
using CMS.UIControls;
public partial class CMSModules_System_System_Macros : SiteManagerPage
{
private const string EVENTLOG_SOURCE_REFRESHSECURITYPARAMS = "Macros - Refresh security parameters";
private NameValueCollection processedObjects = new NameValueCollection();
///
/// Gets the log context for the async control.
///
public LogContext AsyncLogContext
{
get
{
return EnsureAsyncLogContext();
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
InitRefreshSecurityParamsForm();
InitAsyncDialog();
}
#region "Async log"
///
/// Ensures and returns the log context for the async control.
///
private LogContext EnsureAsyncLogContext()
{
var log = LogContext.EnsureLog(ucAsync.ProcessGUID);
log.Reversed = true;
log.LineSeparator = "
";
return log;
}
///
/// Inits the async dialog.
///
private void InitAsyncDialog()
{
btnCancel.Text = GetString("general.cancel");
btnCancel.OnClientClick = ucAsync.GetCancelScript(true) + " return false;";
ucAsync.OnRequestLog += (sender, args) =>
{
ucAsync.Log = AsyncLogContext.Log;
};
ucAsync.OnCancel += (sender, args) =>
{
EventLogProvider.LogInformation((string)ucAsync.Parameter, "CANCELLED");
plcAsyncLog.Visible = false;
AsyncLogContext.Close();
ShowConfirmation(GetString("general.actioncanceled"));
};
ucAsync.OnFinished += (sender, args) =>
{
EventLogProvider.LogInformation((string)ucAsync.Parameter, "FINISHED");
plcAsyncLog.Visible = false;
AsyncLogContext.Close();
ShowConfirmation(GetString("general.actionfinished"));
};
}
///
/// Runs the specified action asynchronously.
///
/// Action name
/// Action
private void RunAsync(string actionName, AsyncAction action)
{
// Set action name as process parameter
ucAsync.Parameter = actionName;
EnsureAsyncLogContext();
// Log async action start
EventLogProvider.LogInformation(actionName, "STARTED");
// Run async action
ucAsync.RunAsync(action, WindowsIdentity.GetCurrent());
}
#endregion
#region "Refresh security params"
///
/// Inits the "Refresh security parameters" form.
///
private void InitRefreshSecurityParamsForm()
{
pnlRefreshSecurityParams.GroupingText = GetString("macros.refreshsecurityparams");
// Init old salt text box
if (chkRefreshAll.Checked)
{
txtOldSalt.Enabled = false;
txtOldSalt.Text = GetString("macros.refreshsecurityparams.refreshalldescription");
}
else
{
txtOldSalt.Enabled = true;
}
chkRefreshAll.CheckedChanged += (sender, args) =>
{
// Clear the textbox after enabling it
if (!chkRefreshAll.Checked)
{
txtOldSalt.Text = null;
}
};
// Init new salt text box
if (chkUseCurrentSalt.Checked)
{
txtNewSalt.Enabled = false;
var customSalt = SettingsHelper.AppSettings["CMSHashStringSalt"];
if (string.IsNullOrEmpty(customSalt))
{
txtNewSalt.Text = GetString("macros.refreshsecurityparams.currentsaltisconnectionstring");
}
else
{
txtNewSalt.Text = GetString("macros.refreshsecurityparams.currentsaltiscustomvalue");
}
}
else
{
txtNewSalt.Enabled = true;
}
chkUseCurrentSalt.CheckedChanged += (sender, args) =>
{
// Clear the textbox after enabling it
if (!chkUseCurrentSalt.Checked)
{
txtNewSalt.Text = null;
}
};
// Init submit button
btnRefreshSecurityParams.Text = pnlRefreshSecurityParams.GroupingText;
btnRefreshSecurityParams.Click += (sender, args) =>
{
var oldSaltInput = txtOldSalt.Text.Trim();
var newSaltInput = txtNewSalt.Text.Trim();
if (!chkRefreshAll.Checked && string.IsNullOrEmpty(oldSaltInput))
{
ShowError(GetString("macros.refreshsecurityparams.oldsaltempty"));
return;
}
if (!chkUseCurrentSalt.Checked && string.IsNullOrEmpty(newSaltInput))
{
ShowError(GetString("macros.refreshsecurityparams.newsaltempty"));
return;
}
plcAsyncLog.Visible = true;
var objectTypes = GetObjectTypesWithMacros(null, null);
RunAsync(EVENTLOG_SOURCE_REFRESHSECURITYPARAMS, p => RefreshSecurityParams(objectTypes, oldSaltInput, newSaltInput));
};
}
///
/// Refreshes the security parameters in macros for all the objects of the specified object types.
/// Signs all the macros with the current user if the old salt is not specified.
///
/// Object types
/// Old salt
/// New salt
private void RefreshSecurityParams(IEnumerable objectTypes, string oldSalt, string newSalt)
{
var oldSaltSpecified = !string.IsNullOrEmpty(oldSalt) && !chkRefreshAll.Checked;
var newSaltSpecified = !string.IsNullOrEmpty(newSalt) && !chkUseCurrentSalt.Checked;
processedObjects.Clear();
using (CMSActionContext context = new CMSActionContext())
{
context.LogEvents = false;
context.LogSynchronization = false;
foreach (var objectType in objectTypes)
{
var objectTypeResourceKey = TypeHelper.GetObjectTypeResourceKey(objectType);
var niceObjectType = GetString(objectTypeResourceKey);
if (niceObjectType == objectTypeResourceKey)
{
if (objectType.StartsWithCSafe("bizformitem.bizform.", true))
{
DataClassInfo dci = DataClassInfoProvider.GetDataClass(objectType.Substring("bizformitem.".Length));
if (dci != null)
{
niceObjectType = "on-line form " + dci.ClassDisplayName;
}
}
else
{
niceObjectType = objectType;
}
}
LogContext.AppendLine(string.Format(GetString("macros.refreshsecurityparams.processing"), niceObjectType));
try
{
var infos = InfoObjectCollection.New(objectType);
foreach (var info in infos)
{
bool refreshed = false;
if (oldSaltSpecified)
{
refreshed = MacroResolver.RefreshSecurityParameters(info, oldSalt, newSaltSpecified ? newSalt : ValidationHelper.HashStringSalt, true);
}
else
{
if (chkRefreshAll.Checked && newSaltSpecified)
{
// Do not check integrity, but use new salt
refreshed = MacroResolver.RefreshSecurityParameters(info, CMSContext.CurrentUser.UserName, true, newSalt);
}
else
{
// Do not check integrity, sign everything with current user, current salt
refreshed = MacroResolver.RefreshSecurityParameters(info, CMSContext.CurrentUser.UserName, true);
}
}
if (refreshed)
{
var objectName = HTMLHelper.HTMLEncode(ResHelper.LocalizeString(info.Generalized.ObjectDisplayName));
processedObjects.Add(niceObjectType, objectName);
}
}
}
catch (Exception e)
{
LogContext.AppendLine(e.Message);
EventLogProvider.LogException(EVENTLOG_SOURCE_REFRESHSECURITYPARAMS, "ERROR", e);
}
}
}
EventLogProvider.LogInformation(EVENTLOG_SOURCE_REFRESHSECURITYPARAMS, "PROCESSEDOBJECTS", GetProcessedObjectsForEventLog());
}
///
/// Builds and returns the list of object types that can contain macros.
///
/// Object types to include in the list
/// Object types to exclude from the list
///
/// Excludes the object types that cannot contain macros.
///
private IEnumerable GetObjectTypesWithMacros(IEnumerable include, IEnumerable exclude)
{
// Get the system object types
var objectTypes = ObjectTypeLists.AllObjectTypes.AsEnumerable();
// Include custom table object types
objectTypes = objectTypes.Union(DataClassInfoProvider.GetCustomTableClasses(null, null, 0, "ClassName").Tables[0].Select().Select(r => r["ClassName"].ToString()));
// Include biz form object types
objectTypes = objectTypes.Union(BizFormInfoProvider.GetAllBizForms().Tables[0].Select().Select(r => "bizformitem.bizform." + r["FormName"].ToString()));
// Include object types
if (include != null)
{
objectTypes = objectTypes.Union(include);
}
// Exclude object types
if (exclude != null)
{
objectTypes = objectTypes.Except(exclude);
}
// Exclude object types that do not contain macros
objectTypes = objectTypes.Except(new[] {
PredefinedObjectType.STATISTICS,
EmailObjectType.EMAIL,
LicenseObjectType.LICENSEKEY,
PredefinedObjectType.ACTIVITY,
"om.pagevisit",
"om.search",
PredefinedObjectType.CHATONLINEUSER,
PredefinedObjectType.EVENT,
ResourceObjectType.RESOURCESTRING,
ResourceObjectType.RESOURCETRANSLATION,
ResourceObjectType.RESOURCETRANSLATED,
"cms.objectsettings",
SiteObjectType.USERROLELIST,
SiteObjectType.MEMBERSHIPLIST,
DocumentObjectType.USERDOCUMENTSLIST,
"temp.file"
});
objectTypes = objectTypes.Where(t =>
{
try
{
var typeInfo = TranslationHelper.GetReadOnlyObject(t).TypeInfo;
return (!typeInfo.Inherited && !typeInfo.IsBinding);
}
catch (Exception)
{
return false;
}
});
return objectTypes;
}
///
/// Gets the list of processed objects formatted for use in the event log.
///
///
private string GetProcessedObjectsForEventLog()
{
StringBuilder sb = new StringBuilder();
foreach (var item in processedObjects.AllKeys)
{
sb.Append("
", string.Format("{0} '{1}'", item, processedObjects[item]));
}
string result = sb.ToString();
if (!string.IsNullOrEmpty(result))
{
result = result.Substring(6);
}
return result;
}
#endregion
}