Sitecore Transfer User Passwords

Original artikel: https://kb.sitecore.net/articles/242631

This article describes the inconveniences of password loss in Sitecore when moving users from one Sitecore instance to another and points out that it is particular inconvenient when transferring many users.

It gives you a tool for transfering passwords easily by copying the SQL value in the database field from one core database to another.

However this tool is not very user friendly when it comes to selecting the users. This must be done by selecting one user at the time and clicking ">>" to move the user to the transfer password list (you cannot select many or all in one selection). When you need to transfer passwords of your 2500+ user you just have moved by serialization, this is not a viable solution, if you wish to avoid seriously damages to your hand and fingers :)

If you need to transfer all or all but a few, the solution is simple.

Edit the aspx from the article and in the btnTransfer_Click function let it retrieve the users from your initial list. Then you can remove the few users you wish to not transfer password for to the other list, or simply transfer all of the original users passwords.

So instead of calling:

protected void btnTransfer_Click(object sender, EventArgs e)
    {
        if (lbTransferPasswords.Items != null && lbTransferPasswords.Items.Count > 0)
        {
            int count = UpdatePasswords(tbSQL2.Text, SelectPasswords(tbSQL1.Text, lbTransferPasswords.Items));
            SetErrorMessage(Color.Green, String.Format("{0} user passwords were transferred successfully!", count));
            btnRefresh_Click(sender, e);
        }
        else
        {
            SetErrorMessage(Color.Red, "The list of users whose passwords will be transferred cannot be empty!");
        }
    }

Change it to:

protected void btnTransfer_Click(object sender, EventArgs e)
    {
        if (lbUsersIntersect.Items != null && lbUsersIntersect.Items.Count > 0)
        {
            int count = UpdatePasswords(tbSQL2.Text, SelectPasswords(tbSQL1.Text, lbUsersIntersect.Items));
            SetErrorMessage(Color.Green, String.Format("{0} user passwords were transferred successfully!", count));
            btnRefresh_Click(sender, e);
        }
        else
        {
            SetErrorMessage(Color.Red, "The list of users whose passwords will be transferred cannot be empty!");
        }
    }

Sitecore WFFM not sending emails

Some weeks ago, I had an issue with the Sitecore Web Forms For Marketers (WFFM) module related to the Save Actions and sending out Email messages. All the data collection was handled in MongoDB correctly, but in some of the forms no emails was send.

When the WFFM did not send out email messages, I found the following exception message in the log file:

"Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Source: Sitecore.Forms.Core
at Sitecore.Form.UI.Adapters.ListControlAdapter.AdaptToFriendlyListValues(FieldItem field, String value, Boolean returnTexts)
at Sitecore.Form.UI.Adapters.ListControlAdapter.AdaptToFriendlyValue(FieldItem field, String value)
at Sitecore.Form.Core.Utility.FieldReflectionUtil.GetAdaptedValue(FieldItem field, String value)
at Sitecore.Form.Core.Pipelines.ProcessMessage.ProcessMessage.ExpandTokens(ProcessMessageArgs args)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Form.Core.Submit.SubmitActionManager.ExecuteSaving(ID formID, ControlResult[] list, ActionDefinition[] actions, Boolean simpleAdapt, ID sessionID)"


Taking a look at the exception it shows some problems with the AdaptToFiendlyListValues method. So I knew it had something to do with List fields types. 

Looking at one of the WFFM List field item at a WFFM form the list data was stored in the “Localized Parameters” field. It seemed all good and fine:

  • %3cquery+t%3d%22default%22+sov%3d%22true%22%3e%3cvalue%3eyes%3c%2fvalue%3e%3c%2fquery%3e%3cquery+t%3d%22default%22+sov%3d%22true%22%3e%3cvalue%3eno%3c%2fvalue%3e%3c%2fquery%3e


Reflecting the “Sitecore.Form.UI.Adapters.ListControlAdapter.AdaptToFriendlyListValues” in Sitecore.Forms.Core.dll:




The Regex.Match in line 21 expect a decoded value – but the value stored in the “Localized Parameters” field was encoded.

Decoding and saving the value stored in the “Localized Parameters” field of the List field item, the value would be:

  • "<items><query sov="true" t="default"><value>yes</value></query><query sov="true" t="default"><value>no</value></query></items>"

The form could now send out emails regarding the field types.

I created a Sitecore Support Ticket and Sitecore responded quickly and provided me with a Support dll. 

To track the future status of this bug report go to:



Related to WFFM 8.0 rev. 151127

Logging User Changing Password

How to extend Sitecore to log information, when user change password.

In Sitecore, you can subscribe to a significant number of default events and define if and how Sitecore should log information about the events (none, low, medium and high). From Sitecore v 8.1 the events are listed in the Sitecore config file located at “/App_Config/Sitecore.config” (previous versions of Sitecore the events are listed in the web.config file).

Sitecore logs different information about the user, when the user is created, deleted, when user information is updated, whenever a user logging in and out of Sitecore. There is no event about changing a user password, though.

If Sitecore should log information about change password for a specific user, one way to do this, is to override the System.Web.Security.SqlMembershipProvider.ChangePassword, add Sitecore log information to the ChangePassword method and change the SQL membership provider.

 The include file changing the membership provider:

    <membership defaultProvider="sitecore" hashAlgorithmType="SHA1">
      <providers>
        <add name="sql" type="MyExtensions.Providers.MyExtendedSqlMembershipProvider" connectionStringName="core" applicationName="sitecore" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="256"  xdt:Locator="Match(name)" xdt:Transform="Replace" />
      </providers>
    </membership>


The override of the System.Web.Security.SqlMembershipProvider.ChangePassword:

namespace MyExtensions.Providers
{
    public class MyExtendedSqlMembershipProvider: System.Web.Security.SqlMembershipProvider
    {
        // Added logging for change password.
        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            var flag = base.ChangePassword(username, oldPassword, newPassword);
            var msg = "";

            if (flag)
            {
                msg = string.Format("AUDIT Password changed for '{0}' by '{1}'", username, Sitecore.Context.User.Name);
            }
            else
            {
                msg = string.Format("AUDIT Change password failed for '{0}' by '{1}'", username, Sitecore.Context.User.Name);
            }

            Sitecore.Diagnostics.Log.Info(msg, this);

            return flag;
        }
    }
}

Adding Custom Dialog to Rich Text Editor

Taking the scenario, you want to let the content editors insert some content into the Rich Text Editor, and you want the Rich Text Editor to wrap some html around the content. It could be adding an anchor tag around a phone number, with “href” attribute equals to the phone number or as in the following example a div tag with different class attribute around a YouTube iFrame, depending on whether the YouTube video is a format of 4/3 or 16/9, respectively.

It only takes the following five steps:

  1. Create a new HTML Editor Button in Rich Text Editor
  2. Create a new dialog and name it YoutubeManager.xml 
  3. Add a .js file used in the dialog and name it YoutubeManager.js
  4. Enhance the existing “RichText Command.js” file
  5. Create your codebeside to the dialog //YoutubeManager.xml file


Step 1) HTML Editor Button
Create a new HTML Editor Button place at the “HTML Editor Profile”, from where you want to use the new command. The “HTML Editor Profiles” are placed in the Core database and located at “/Sitecore/system/Settings/Html Editor Profiles/”. In this case, it is the “Rich Text Full” profile, I want to add the command into. 

Sitecore uses the “Click” field to define, which radEditorCommandList from the “RichText Command.js” to use, when using the command or “HTML Editor Button” in the Rich Text Editor (RadEditorCommandList["YoutubeManager"] = function (commandName, editor, args)) se step 4.




Assign an icon and a name to the “HTML Editor Button”. In this case the name is “Insert Youtube iFrame”. Save the new “HTML Editor Button”. Navigate to the Master database, select an Item using the “HTML Editor Profile” and verify the Rich Text Editor contains the new HTML Editor Button:


Step 2) Create a new dialog and name it YoutubeManager.XML
At “\sitecore\shell\Controls\Rich Text Editor\” create a folder with a name equal to the value of the “Click” field. In this case, I name it “YoutubeManager”. In this folder, you place your YoutubeManager.xml and YoutubeManager.js file. 

The YoutubeManager.xml dialog will opens, when selecting the Insert Youtube iFrame command created in step 1.

YoutubeManager.xml:
<?xml version="1.0" encoding="utf-8" ?>
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense">
  <RichText.YoutubeManager>
    <FormDialog Icon="People/32x32/movie_run.png" Header="Insert Youtbube" Text="Insert the IFrame code frome Youtube.com." OKButton="Insert">
      <script Type="text/javascript" Language="javascript" Src="/sitecore/shell/controls/rich text editor/youtubemanager/YoutubeManager.js">.</script>
      <CodeBeside Type="MySitecoreExtensions.Modules.RichTextEditor.Youtube, MySitecoreExtensions"/>
      <GridPanel Width="100%" Height="100%" Style="table-layout:fixed">
          <GridPanel Columns="2">
        <Checkbox ID="cbxYouTubeFormat" Class="checkbox" ToolTip="16:9 format if checked (default is 4:3 format)" /><Label For="lblYouTubeFormat">16:9 format if checked (default is 4:3 format)</Label>
          </GridPanel>
        <Memo ID="memYoutubeIframe" Style="height:75px;width:100%;border-top:1px solid #919b9c" ></Memo>
      </GridPanel>
    </FormDialog>
  </RichText.YoutubeManager>
</control>

Step 3) Add the YoutubeManager.js
This js file contains standard js functionality for handling the dialog, when using dialogs in the Rich Text editor. Create it, name it YoutubeManager.js and place it in the folder described in step 2.

function scClose(text) {
    var returnValue = {
        Text: text
    };
 
    getRadWindow().close(returnValue);
}
 
function GetDialogArguments() {
    return getRadWindow().ClientParameters;
}
 
function getRadWindow() {
    if (window.radWindow) {
        return window.radWindow;
    }
 
    if (window.frameElement && window.frameElement.radWindow) {
        return window.frameElement.radWindow;
    }
 
    return null;
}
 
var isRadWindow = true;
 
var radWindow = getRadWindow();
 
if (radWindow) {
    if (window.dialogArguments) {
        radWindow.Window = window;
    }
}
 
function scCancel() {
 
    getRadWindow().close();
}
 
function scCloseWebEdit(embedTag) {
    window.returnValue = embedTag;
    window.close();
}
 
if (window.focus && Prototype.Browser.Gecko) {
    window.focus();
}

Step 4) Enhance the existing RichtText Commands.js file
Add the following into the existing “RichText Command.js” located at “\sitecore\shell\Controls\Rich Text Editor”. What it does is, whenever you select the “YoutubeManager” command (from the Rich Text Editor), it opens the xml control named YoutubeManager (the one created in step 1).

RadEditorCommandList["YoutubeManager"] = function (commandName, editor, args) {
 
    var html = editor.getSelectionHtml();
 
    scEditor = editor;
 
    editor.showExternalDialog(
  "/sitecore/shell/default.aspx?xmlcontrol=RichText.YoutubeManager&la=" + scLanguage + "&selectedText=" + escape(html),
  null, //argument
  500, //width
  300, //height
  scYoutubeManager, //callback
  null, // callback args
  "Insert Youtube IFrame",
  true, //modal
  Telerik.Web.UI.WindowBehaviors.Close, // behaviors
  false, //showStatusBar
  false //showTitleBar
 );
};
 
function scYoutubeManager(sender, returnValue) {
    if (!returnValue) {
        return;
    }
 
    scEditor.pasteHtml(unescape(returnValue.Text), "DocumentManager");
}


Step 5) Create your codebeside to the YoutubeManager.xml 
This is the codebeside to the YoutubeManager.xml. It simply just add
tag around the Youtube iFrame.





using System;
using Sitecore.Web.UI.Pages;
using Sitecore.Diagnostics;
using Sitecore;
using Sitecore.Web;
using Sitecore.Web.UI.Sheer;
 
namespace MySitecoreExtensions.Modules.RichTextEditor
{
 public class Youtube : DialogForm
 {
  // Fields
  protected Sitecore.Web.UI.HtmlControls.Memo memYoutubeIframe;
     protected Sitecore.Web.UI.HtmlControls.Checkbox cbxYouTubeFormat;

 // Properties
  protected string Mode 
{
   get {
    string str = StringUtil.GetString(base.ServerProperties["Mode"]);
    if (!string.IsNullOrEmpty(str)) {
     return str;
    }
    return "shell";
   }
   set {
    Assert.ArgumentNotNull(value, "value");
    base.ServerProperties["Mode"] = value;
   }
  }

  //setup page
  protected override void OnLoad(EventArgs e) {
   Assert.ArgumentNotNull(e, "e");
   base.OnLoad(e);
   if (!Context.ClientPage.IsEvent) {
    this.Mode = WebUtil.GetQueryString("mo");
    string text = WebUtil.GetQueryString("selectedText");
 
    //set textbox text to selected text
    memYoutubeIframe.Value = text;
   }
  }
 
  //When pressed ok
  protected override void OnOK(object sender, EventArgs args) 
{
   Assert.ArgumentNotNull(sender, "sender");
   Assert.ArgumentNotNull(args, "args");
 
      string divClassYoutubeFormat = "embed-responsive-4by3";
      if (cbxYouTubeFormat.Checked)
      {
                divClassYoutubeFormat = "embed-responsive-16by9";
      }
    //Add div tag around the youtube iFrame
      string code = string.Format("
{1}
", divClassYoutubeFormat, memYoutubeIframe.Value); //encode it and send it back to the rich text editor if (this.Mode == "webedit") { SheerResponse.SetDialogValue(StringUtil.EscapeJavascriptString(code)); base.OnOK(sender, args); } else { SheerResponse.Eval("scClose(" + StringUtil.EscapeJavascriptString(code) + ")"); } } //When pressed cancelled protected override void OnCancel(object sender, EventArgs args) { Assert.ArgumentNotNull(sender, "sender"); Assert.ArgumentNotNull(args, "args"); if (this.Mode == "webedit") { base.OnCancel(sender, args); } else { SheerResponse.Eval("scCancel()"); } } } }

Finally, try to use the command. Select a YouTube video from youtube.com and copy the embedded code. Open the HTML Editor Button in the Rich Text Editor and paste the embedded code into the dialog.




Verify the YouTube video in “Design” mode:



Verify the YouTube video in “Html” mode: