Skip to content

Commit

Permalink
Version 1.1.7:
Browse files Browse the repository at this point in the history
Fixed issue with special chars "Zero width space" and "Zero width no-break space" in the names of the columns.
Improved import process when missed some required columns: DisplayName, IsSuperUser, Username, AffiliateId.
  • Loading branch information
fordnn committed Nov 23, 2018
1 parent 385800a commit b9bf03a
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 195 deletions.
3 changes: 3 additions & 0 deletions App_LocalResources/MainControl.ascx.resx
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,7 @@
<data name="MaxAllowedFileSize.Text" xml:space="preserve">
<value>Max allowed file size for upload is {0}</value>
</data>
<data name="ExportInProgress.Text" xml:space="preserve">
<value>Export in progress...</value>
</data>
</root>
34 changes: 31 additions & 3 deletions Components/CommonController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,39 @@ public static void ResponseFile(string ContentType, byte[] lstBytes, string File
objResponse.End();
}

public static string SaveFile(int PortalId, string ToWrite, string FileName)
{
PortalSettings objPortalSettings = new PortalSettings(PortalId);
string Path = objPortalSettings.HomeDirectoryMapPath + "UsersExportImport\\";
if (!System.IO.Directory.Exists(Path))
{
System.IO.Directory.CreateDirectory(Path);
}
//delete all files in directory for security reason
foreach (string tempName in System.IO.Directory.GetFiles(Path))
{
System.IO.File.Delete(tempName);
}

System.IO.StreamWriter sw = new System.IO.StreamWriter(Path + FileName, false, Encoding.UTF8);
sw.Write(ToWrite);
sw.Close();

return objPortalSettings.HomeDirectory + "UsersExportImport/" + FileName;
}

public static string GetMaxAllowedFileSize()
{
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
HttpRuntimeSection section = config.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
return string.Format("{0} kB", section.MaxRequestLength);
try
{
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
HttpRuntimeSection section = config.GetSection("system.web/httpRuntime") as HttpRuntimeSection;
return string.Format("{0} kB", section.MaxRequestLength);
}
catch
{
return "undefined";
}
}
}
}
187 changes: 187 additions & 0 deletions Components/ExportController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
using System;
using System.Data;
using System.Collections;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using DotNetNuke.Entities.Users;
using DotNetNuke.Entities.Portals;

namespace forDNN.Modules.UsersExportImport.Controller
{
public class ExportController
{
#region Export

public static string DoExport(int PortalId, Models.ExportInfo objExportInfo)
{
string ResultURL = "";
try
{
IDataReader idr = null;

//check if IsDeleted column exists
bool IsDeletedExists = true;
try
{
idr = DotNetNuke.Data.DataProvider.Instance().ExecuteSQL("SELECT TOP 1 IsDeleted FROM {databaseOwner}{objectQualifier}vw_Users");
}
catch
{
IsDeletedExists = false;
}

//build dynamic query to retireve data
Hashtable htFieldNames = new Hashtable();
htFieldNames["UserID"] = 1;
htFieldNames["UserName"] = 1;
htFieldNames["FirstName"] = 1;
htFieldNames["LastName"] = 1;
htFieldNames["DisplayName"] = 1;
htFieldNames["IsSuperUser"] = 1;
htFieldNames["Email"] = 1;
htFieldNames["AffiliateId"] = 1;
htFieldNames["Authorised"] = 1;

StringBuilder sbSelect = new StringBuilder(
@"SELECT u.UserID,
u.UserName,
u.FirstName,
u.LastName,
u.DisplayName,
u.IsSuperUser,
u.Email,
u.AffiliateId,
u.Authorised");

StringBuilder sbFrom = new StringBuilder(@"
FROM {databaseOwner}{objectQualifier}vw_Users u ");
StringBuilder sbWhere = new StringBuilder(@"
WHERE (1=1)
AND ((u.PortalId={0}) OR (u.IsSuperUser=1)) ".Replace("{0}", PortalId.ToString()));

//check SuperUsers
if (!objExportInfo.IncludeSuperUsers)
{
sbWhere.Append(" AND (u.IsSuperUser=0) ");
}

//check deleted accounts
if (IsDeletedExists)
{
sbSelect.Append(", u.IsDeleted");
if (!objExportInfo.IncludeDeleted)
{
sbWhere.Append(" AND (u.IsDeleted=0) ");
}
htFieldNames["IsDeleted"] = 1;
}

//check authorised accounts
if (!objExportInfo.IncludeNonAuthorised)
{
sbWhere.Append(" AND (u.Authorised=1) ");
}

//check if requires to export roles
if (objExportInfo.ExportRoles)
{
sbSelect.Append(@", (SELECT CAST(ur.RoleID AS nvarchar(10)) + ','
FROM {databaseOwner}{objectQualifier}UserRoles ur
WHERE (ur.UserID=u.UserID) AND (ur.RoleID IN (SELECT r.RoleID FROM {databaseOwner}{objectQualifier}Roles r WHERE (r.PortalID={0})))
FOR XML PATH('')) RoleIDs,
(SELECT r.RoleName + ','
FROM {databaseOwner}{objectQualifier}UserRoles ur
LEFT JOIN {databaseOwner}{objectQualifier}Roles r ON (ur.RoleID=r.RoleID)
WHERE (ur.UserID=u.UserID) AND (ur.RoleID IN (SELECT r.RoleID FROM {databaseOwner}{objectQualifier}Roles r WHERE (r.PortalID={0})))
FOR XML PATH('')) Roles
").Replace("{0}", PortalId.ToString());

htFieldNames["RoleIDs"] = 1;
htFieldNames["Roles"] = 1;
}

//define properties
foreach (string li in objExportInfo.PropertiesToExport.Split(new char[] { ',' }))
{
string[] objParam = li.Split(new char[] { '=' });
if (htFieldNames[objParam[0]] != null)
{
continue;
}

htFieldNames[objParam[0]] = 1;

sbSelect.Append(", up{0}.PropertyValue [{1}] "
.Replace("{0}", objParam[1])
.Replace("{1}", objParam[0])
);


sbFrom.Append(" LEFT JOIN {databaseOwner}{objectQualifier}UserProfile up{0} ON ((u.UserID=up{0}.UserID) AND (up{0}.PropertyDefinitionID={0})) "
.Replace("{0}", objParam[1]));
}

idr = DotNetNuke.Data.DataProvider.Instance().ExecuteSQL(sbSelect.ToString() + sbFrom.ToString() + sbWhere.ToString());
DataTable dt = DotNetNuke.Common.Globals.ConvertDataReaderToDataTable(idr);
if (objExportInfo.ExportPasswords)
{
dt = AddPasswordsColumn(PortalId, dt);
}

string strResult = "";

switch (objExportInfo.ExportFileType)
{
case 0://temporary disabled for Excel
break;
case 1://XML - FOR XML RAW
strResult = CommonController.ToXML(dt);
ResultURL = CommonController.SaveFile(PortalId,
strResult,
string.Format("Users_{0:ddMMyyyy_HHmmss}_{1}.xml", DateTime.Now, System.Guid.NewGuid().ToString()));
break;
case 2://CSV
strResult = CommonController.ToCSV(dt, true, ",");
ResultURL = CommonController.SaveFile(PortalId,
strResult,
string.Format("Users_{0:ddMMyyyy_HHmmss}_{1}.csv", DateTime.Now, System.Guid.NewGuid().ToString()));
break;
}
}
catch (System.Exception ex)
{
DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
}

return ResultURL;
}

private static DataTable AddPasswordsColumn(int PortalId, DataTable dt)
{
dt.Columns.Add("Password", "".GetType());

foreach (DataRow dr in dt.Rows)
{
if (DotNetNuke.Security.Membership.MembershipProviderConfig.PasswordRetrievalEnabled)
{
UserInfo objUser = UserController.GetUserById(PortalId, (int)dr["userid"]);
dr["Password"] = UserController.GetPassword(ref objUser, objUser.Membership.PasswordAnswer);
}
else
{
dr["Password"] = "";
}
}

return dt;
}

#endregion

}
}
11 changes: 9 additions & 2 deletions Install/_UsersExportImport.dnn
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<dotnetnuke type="Package" version="5.0">
<packages>
<package name="forDNN.UsersExportImport" type="Module" version="1.1.5">
<package name="forDNN.UsersExportImport" type="Module" version="1.1.7">
<friendlyName>forDNN.UsersExportImport</friendlyName>
<description>This module allows to export/import users, user profiles properties and roles to DNN (former DotNetNuke) from CSV/XML files. This is simple and fast way to create your users accounts in one click.</description>
<owner>
<name>Sergey Velichko</name>
<name>Sergiy Velychko</name>
<organization>forDNN Team</organization>
<url>&lt;a href="http://forDNN.com" target="_blank"&gt;http://forDNN.com&lt;/a&gt;</url>
<email>&lt;a href="mailto:support@forDNN.com" target="_blank"&gt;support@forDNN.com&lt;/a&gt;</email>
Expand All @@ -25,6 +25,13 @@
</license>
<releaseNotes>
<![CDATA[
<b>Version 1.1.7:</b><br />
Fixed issue with special chars "Zero width space" and "Zero width no-break space" in the names of the columns.<br />
Improved import process when missed some required columns: DisplayName, IsSuperUser, Username, AffiliateId.<br />

<b>Version 1.1.6:</b><br />
Added export support for versions 9.x.<br />

<b>Version 1.1.5:</b><br />
Fixed an issue with multi portals DNN installation (there were dublicates of the users).<br />
Added notification on maximum allowed file size for import.<br />
Expand Down
Binary file added Install/forDNN.UsersExportImport_v.01.01.06.zip
Binary file not shown.
Binary file added Install/forDNN.UsersExportImport_v.01.01.07.zip
Binary file not shown.
76 changes: 69 additions & 7 deletions MainControl.ascx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<asp:ListItem Value="2" resourcekey="ExportFileType_2" Selected></asp:ListItem>
</asp:DropDownList>
</div>
<div class="dnnFormItem">
<div class="dnnFormItem" runat="server" id="divIncludeSuperUsers">
<dnn:Label runat="server" id="lblIncludeSuperUsers" resourcekey="IncludeSuperUsers" AssociatedControlID="cbIncludeSuperUsers"></dnn:Label>
<asp:CheckBox runat="server" ID="cbIncludeSuperUsers" CssClass="normalCheckBox" />
</div>
Expand Down Expand Up @@ -64,8 +64,10 @@
<asp:CheckBoxList runat="server" ID="cblPropertiesToExport" RepeatDirection="Vertical" RepeatColumns="3" CssClass="normalCheckBox"></asp:CheckBoxList>
</div>
</fieldset>
<asp:LinkButton ID="btnExportUsers" runat="server" CssClass="dnnPrimaryAction" OnClick="btnExportUsers_Click"
resourcekey="ExportUsers"></asp:LinkButton>
<asp:HyperLink ID="btnExportUsers" runat="server" CssClass="dnnPrimaryAction" resourcekey="ExportUsers"></asp:HyperLink>
<div id="ExportInProgress" style="display:none;">
<asp:Label runat="server" ID="lblExportInProgress" resourcekey="ExportInProgress" CssClass="NormalRed"></asp:Label>
</div>
</div>
<div id="divImportUsers" class="dnnClear dnnForm">
<fieldset>
Expand Down Expand Up @@ -127,8 +129,68 @@
</div>

<script type="text/javascript">
jQuery(function ($)
{
$('#tabs-demo').dnnTabs();
});
$(document).ready(function ()
{
$('#tabs-demo').dnnTabs();
});
function doExport(moduleId)
{
var objValues = new Object();
objValues.ExportFileType = $("#<%=ddlExportFileType.ClientID%>").val();
objValues.IncludeSuperUsers = $("#<%=cbIncludeSuperUsers.ClientID%>").prop("checked");
objValues.IncludeDeleted = $("#<%=cbIncludeDeleted.ClientID%>").prop("checked");
objValues.IncludeNonAuthorised = $("#<%=cbIncludeNonAuthorised.ClientID%>").prop("checked");
objValues.ExportRoles = $("#<%=cbExportRoles.ClientID%>").prop("checked");
objValues.ExportPasswords = $("#<%=cbExportPasswords.ClientID%>").prop("checked");
objValues.PropertiesToExport = "";
$("#<%=cblPropertiesToExport.ClientID%> input[type='checkbox']:checked").each(
function (ind, val)
{
var objVal = $(val);
objValues.PropertiesToExport += ((objValues.PropertiesToExport==="")?"":",") + objVal.parent().find("label").html() + "=" + objVal.val();
}
);
$("#<%=btnExportUsers.ClientID%>").toggle();
$("#ExportInProgress").toggle();
callWebAPI(moduleId, "DoExport", objValues, function (data)
{
$("#<%=btnExportUsers.ClientID%>").toggle();
$("#ExportInProgress").toggle();
if (data === "")
{
alert("Export error, please check logs");
}
else
{
document.location.href = data;
}
});
return false;
}
function callWebAPI(moduleId, methodName, values, callBack)
{
var sf = $.ServicesFramework(moduleId);
var serviceUrl = sf.getServiceRoot('forDNN.UsersExportImport') + "ExportImport/" + methodName;
$.ajax({
url: serviceUrl,
data: JSON.stringify(values),
type: "POST",
contentType: "application/json",
headers: { "RequestVerificationToken": sf.getAntiForgeryValue(), "ModuleId": sf.getModuleId(), "TabId": sf.getTabId() },
success: function (data, status, xhr)
{
callBack(data);
},
error: function (xhr, status, err)
{
console.error(serviceUrl, status, err.toString());
}
});
}
</script>
Loading

0 comments on commit b9bf03a

Please sign in to comment.