Skip to content

Commit 9a3e794

Browse files
authored
Merge pull request #111 from UpendoVentures/dev
Syncing branches
2 parents 67854b8 + b8047df commit 9a3e794

15 files changed

+413
-45
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<root>
3+
<!--
4+
Microsoft ResX Schema
5+
6+
Version 2.0
7+
8+
The primary goals of this format is to allow a simple XML format
9+
that is mostly human readable. The generation and parsing of the
10+
various data types are done through the TypeConverter classes
11+
associated with the data types.
12+
13+
Example:
14+
15+
... ado.net/XML headers & schema ...
16+
<resheader name="resmimetype">text/microsoft-resx</resheader>
17+
<resheader name="version">2.0</resheader>
18+
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19+
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20+
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21+
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22+
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23+
<value>[base64 mime encoded serialized .NET Framework object]</value>
24+
</data>
25+
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26+
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27+
<comment>This is a comment</comment>
28+
</data>
29+
30+
There are any number of "resheader" rows that contain simple
31+
name/value pairs.
32+
33+
Each data row contains a name, and value. The row also contains a
34+
type or mimetype. Type corresponds to a .NET class that support
35+
text/value conversion through the TypeConverter architecture.
36+
Classes that don't support this are serialized and stored with the
37+
mimetype set.
38+
39+
The mimetype is used for serialized objects, and tells the
40+
ResXResourceReader how to depersist the object. This is currently not
41+
extensible. For a given mimetype the value must be set accordingly:
42+
43+
Note - application/x-microsoft.net.object.binary.base64 is the format
44+
that the ResXResourceWriter will generate, however the reader can
45+
read any of the formats listed below.
46+
47+
mimetype: application/x-microsoft.net.object.binary.base64
48+
value : The object must be serialized with
49+
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50+
: and then encoded with base64 encoding.
51+
52+
mimetype: application/x-microsoft.net.object.soap.base64
53+
value : The object must be serialized with
54+
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55+
: and then encoded with base64 encoding.
56+
57+
mimetype: application/x-microsoft.net.object.bytearray.base64
58+
value : The object must be serialized into a byte array
59+
: using a System.ComponentModel.TypeConverter
60+
: and then encoded with base64 encoding.
61+
-->
62+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63+
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64+
<xsd:element name="root" msdata:IsDataSet="true">
65+
<xsd:complexType>
66+
<xsd:choice maxOccurs="unbounded">
67+
<xsd:element name="metadata">
68+
<xsd:complexType>
69+
<xsd:sequence>
70+
<xsd:element name="value" type="xsd:string" minOccurs="0" />
71+
</xsd:sequence>
72+
<xsd:attribute name="name" use="required" type="xsd:string" />
73+
<xsd:attribute name="type" type="xsd:string" />
74+
<xsd:attribute name="mimetype" type="xsd:string" />
75+
<xsd:attribute ref="xml:space" />
76+
</xsd:complexType>
77+
</xsd:element>
78+
<xsd:element name="assembly">
79+
<xsd:complexType>
80+
<xsd:attribute name="alias" type="xsd:string" />
81+
<xsd:attribute name="name" type="xsd:string" />
82+
</xsd:complexType>
83+
</xsd:element>
84+
<xsd:element name="data">
85+
<xsd:complexType>
86+
<xsd:sequence>
87+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88+
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89+
</xsd:sequence>
90+
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91+
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92+
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93+
<xsd:attribute ref="xml:space" />
94+
</xsd:complexType>
95+
</xsd:element>
96+
<xsd:element name="resheader">
97+
<xsd:complexType>
98+
<xsd:sequence>
99+
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100+
</xsd:sequence>
101+
<xsd:attribute name="name" type="xsd:string" use="required" />
102+
</xsd:complexType>
103+
</xsd:element>
104+
</xsd:choice>
105+
</xsd:complexType>
106+
</xsd:element>
107+
</xsd:schema>
108+
<resheader name="resmimetype">
109+
<value>text/microsoft-resx</value>
110+
</resheader>
111+
<resheader name="version">
112+
<value>2.0</value>
113+
</resheader>
114+
<resheader name="reader">
115+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116+
</resheader>
117+
<resheader name="writer">
118+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119+
</resheader>
120+
<data name="AreYouSure.Text" xml:space="preserve">
121+
<value>Are you sure you want to impersonate this user account?</value>
122+
</data>
123+
<data name="DeleteUser.Text" xml:space="preserve">
124+
<value>Delete User Account</value>
125+
</data>
126+
<data name="Impersonate.Text" xml:space="preserve">
127+
<value>Impersonate</value>
128+
</data>
129+
<data name="ImpersonateAnotherUserAccountConfirmation.Text" xml:space="preserve">
130+
<value>You are about to impersonate another user account. &lt;b&gt;If you confirm&lt;/b&gt;, the website will attempt to log you in as if the user themselves logged in. You will need to logout and log back in to restore your superuser access. &lt;b&gt;If you cancel&lt;/b&gt;, nothing will happen.</value>
131+
</data>
132+
<data name="ImpersonateAnotherUserAccountConfirmationAlert.Text" xml:space="preserve">
133+
<value>&lt;b&gt;Technical Limitation:&lt;/b&gt; If you are using another authentication provider other than the built-in DNN provider, this feature may or may not work, depending on the type of authentication you have installed/enabled.</value>
134+
</data>
135+
<data name="ImpersonateUser.Text" xml:space="preserve">
136+
<value>Impersonate User Account</value>
137+
</data>
138+
</root>

Modules/UserManager/App_LocalResources/Index.resx

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
<value>Create User</value>
128128
</data>
129129
<data name="BulkDeleteUser.Text" xml:space="preserve">
130-
<value>Bulk Delete User</value>
130+
<value>Bulk Delete Users</value>
131131
</data>
132132
<data name="CreateRole.Text" xml:space="preserve">
133133
<value>Create Role</value>
@@ -187,7 +187,7 @@
187187
<value>Username</value>
188188
</data>
189189
<data name="UserRoles.Text" xml:space="preserve">
190-
<value>User Roles</value>
190+
<value>User's Roles</value>
191191
</data>
192192
<data name="Users.Text" xml:space="preserve">
193193
<value>USERS</value>

Modules/UserManager/App_LocalResources/Shared.resx

+3
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,7 @@
180180
<data name="OnlySuperUserIsAllowedBulkDeleteUserAccounts.Text" xml:space="preserve">
181181
<value>Only a superuser is allowed to bulk delete user accounts</value>
182182
</data>
183+
<data name="Cancel.Text" xml:space="preserve">
184+
<value>Cancel</value>
185+
</data>
183186
</root>

Modules/UserManager/Controllers/UserManageController.cs

+22
Original file line numberDiff line numberDiff line change
@@ -534,5 +534,27 @@ public ActionResult PasswordResetLink(int itemId)
534534
TempData["Message"] = UserRepository.SendPasswordResetLink(portalId, itemId, portalSettings);
535535
return RedirectToAction("Index");
536536
}
537+
538+
/// <summary>
539+
/// Impersonate a user
540+
/// </summary>
541+
/// <param name="itemId"></param>
542+
/// <returns></returns>
543+
public ActionResult ImpersonateUserById(int itemId)
544+
{
545+
if (_currentUser.IsSuperUser)
546+
{
547+
var user = UserController.GetUserById(PortalSettings.PortalId, itemId);
548+
if (user != null)
549+
{
550+
// Perform impersonation
551+
UserController.UserLogin(PortalSettings.PortalId, user, PortalSettings.PortalName, Request.UserHostAddress, false);
552+
}
553+
return Redirect(Url.Content("~/"));
554+
}
555+
string errorMessage = Localization.GetString("NotPermissions.Text", ResourceFile);
556+
ViewBag.ErrorMessage = errorMessage;
557+
return View("Error");
558+
}
537559
}
538560
}

Modules/UserManager/Module.css

+10
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
.checkbox {
207207
font-size: 16px;
208208
}
209+
209210
.admin-manager .checkbox {
210211
margin-top: 20px;
211212
}
@@ -320,6 +321,11 @@
320321
margin-bottom: 25px;
321322
}
322323

324+
.mtb-2 {
325+
margin-top: 0.5em;
326+
margin-bottom: 0.5em;
327+
}
328+
323329
.pb10 {
324330
padding-bottom: 10px !important;
325331
}
@@ -726,4 +732,8 @@
726732
line-height: 26px;
727733
border-top-left-radius: 0;
728734
border-bottom-left-radius: 0;
735+
}
736+
737+
.AM-white, .AM-white a, .AM-white a:visited {
738+
color: white;
729739
}

Modules/UserManager/Properties/AssemblyInfo.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@
2929
// Build Number
3030
// Revision
3131
//
32-
[assembly: AssemblyVersion("01.04.01")]
33-
[assembly: AssemblyFileVersion("01.04.01")]
32+
[assembly: AssemblyVersion("01.05.00")]
33+
[assembly: AssemblyFileVersion("01.05.00")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/************************************************************/
2+
/***** SqlDataProvider *****/
3+
/************************************************************/
4+
5+
IF OBJECT_ID('{databaseOwner}{objectQualifier}UUM_GetUsers', 'P') IS NOT NULL
6+
BEGIN
7+
EXEC('DROP PROCEDURE ' + '{databaseOwner}{objectQualifier}UUM_GetUsers');
8+
END
9+
GO
10+
11+
CREATE PROCEDURE {databaseOwner}{objectQualifier}UUM_GetUsers
12+
@PageIndex INT,
13+
@PageSize INT,
14+
@SearchTerm NVARCHAR(100) = NULL,
15+
@SortColumn NVARCHAR(50) = 'UserID',
16+
@SortOrder NVARCHAR(4) = 'ASC',
17+
@IsSuperUser BIT = NULL,
18+
@Authorised BIT = NULL,
19+
@PortalId INT = NULL,
20+
@Deleted BIT = NULL,
21+
@AllUsers BIT = NULL,
22+
@TotalRecords INT OUTPUT
23+
AS
24+
BEGIN
25+
SET NOCOUNT ON;
26+
27+
DECLARE @Offset INT;
28+
SET @Offset = (@PageIndex - 1) * @PageSize;
29+
30+
DECLARE @SortExpression NVARCHAR(100);
31+
SET @SortExpression = QUOTENAME(@SortColumn) + ' ' + @SortOrder;
32+
33+
DECLARE @Results TABLE
34+
(
35+
UserID INT,
36+
FirstName NVARCHAR(100),
37+
Username NVARCHAR(100),
38+
Email NVARCHAR(100),
39+
DisplayName NVARCHAR(100),
40+
IsSuperUser BIT,
41+
RowNumber INT
42+
);
43+
44+
-- Perform total count
45+
IF @AllUsers = 0
46+
BEGIN
47+
SELECT @TotalRecords = COUNT(*)
48+
FROM [dbo].[Users] u
49+
LEFT JOIN [dbo].[UserPortals] up ON u.UserID = up.UserID
50+
WHERE (LOWER(u.[UserName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
51+
LOWER(u.[FirstName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
52+
LOWER(u.[Email]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
53+
LOWER(u.[DisplayName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%')
54+
AND u.IsDeleted = 0
55+
AND (@IsSuperUser IS NULL OR u.IsSuperUser = @IsSuperUser)
56+
AND (@Deleted IS NULL OR up.IsDeleted = @Deleted)
57+
AND (@Authorised IS NULL OR (up.Authorised = @Authorised AND up.IsDeleted = 0))
58+
AND (@PortalId IS NULL OR up.PortalId = @PortalId);
59+
END
60+
ELSE
61+
BEGIN
62+
SELECT @TotalRecords = COUNT(*)
63+
FROM [dbo].[Users] u
64+
LEFT JOIN [dbo].[UserPortals] up ON u.UserID = up.UserID
65+
WHERE (LOWER(u.[UserName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
66+
LOWER(u.[FirstName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
67+
LOWER(u.[Email]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
68+
LOWER(u.[DisplayName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%')
69+
AND (@PortalId IS NULL OR up.PortalId = @PortalId);
70+
END;
71+
72+
-- Get paginated results
73+
INSERT INTO @Results (UserID, FirstName, Username, Email, DisplayName, IsSuperUser, RowNumber)
74+
SELECT u.UserID, u.FirstName, u.Username, u.Email, u.DisplayName, u.IsSuperUser,
75+
ROW_NUMBER() OVER (
76+
ORDER BY
77+
CASE WHEN @SortOrder = 'ASC' AND @SortColumn = 'FirstName' THEN u.FirstName END ASC,
78+
CASE WHEN @SortOrder = 'DESC' AND @SortColumn = 'FirstName' THEN u.FirstName END DESC,
79+
CASE WHEN @SortOrder = 'ASC' AND @SortColumn = 'Username' THEN u.UserName END ASC,
80+
CASE WHEN @SortOrder = 'DESC' AND @SortColumn = 'Username' THEN u.UserName END DESC,
81+
CASE WHEN @SortOrder = 'ASC' AND @SortColumn = 'Email' THEN u.Email END ASC,
82+
CASE WHEN @SortOrder = 'DESC' AND @SortColumn = 'Email' THEN u.Email END DESC,
83+
CASE WHEN @SortOrder = 'ASC' AND @SortColumn = 'DisplayName' THEN u.DisplayName END ASC,
84+
CASE WHEN @SortOrder = 'DESC' AND @SortColumn = 'DisplayName' THEN u.DisplayName END DESC
85+
) AS RowNumber
86+
FROM [dbo].[Users] u
87+
LEFT JOIN [dbo].[UserPortals] up ON u.UserID = up.UserID
88+
WHERE
89+
(LOWER(u.[UserName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
90+
LOWER(u.[FirstName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
91+
LOWER(u.[Email]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%' OR
92+
LOWER(u.[DisplayName]) COLLATE Latin1_General_CI_AI LIKE '%' + LOWER(@SearchTerm) COLLATE Latin1_General_CI_AI + '%')
93+
AND u.IsDeleted = 0
94+
AND (@IsSuperUser IS NULL OR u.IsSuperUser = @IsSuperUser)
95+
AND (@Deleted IS NULL OR up.IsDeleted = @Deleted)
96+
AND (@Authorised IS NULL OR (up.Authorised = @Authorised AND up.IsDeleted = 0))
97+
AND (@PortalId IS NULL OR up.PortalId = @PortalId)
98+
ORDER BY RowNumber;
99+
100+
-- Return paginated results
101+
SELECT UserID, FirstName, Username, Email, DisplayName, IsSuperUser
102+
FROM @Results
103+
WHERE RowNumber BETWEEN (@Offset + 1) AND (@Offset + @PageSize);
104+
END;

Modules/UserManager/Upendo.Modules.UserManager.csproj

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
44
<PropertyGroup>
@@ -13,7 +13,7 @@
1313
<AppDesignerFolder>Properties</AppDesignerFolder>
1414
<RootNamespace>Upendo.Modules.UserManager</RootNamespace>
1515
<AssemblyName>Upendo.Modules.UserManager</AssemblyName>
16-
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
16+
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
1717
<UseIISExpress>false</UseIISExpress>
1818
<IISExpressSSLPort />
1919
<IISExpressAnonymousAuthentication />
@@ -75,10 +75,6 @@
7575
<Reference Include="System.ComponentModel.DataAnnotations" />
7676
<Reference Include="System" />
7777
<Reference Include="System.Data" />
78-
<Reference Include="System.Core" />
79-
<Reference Include="System.Data.DataSetExtensions" />
80-
<Reference Include="System.Web.Extensions" />
81-
<Reference Include="System.Xml.Linq" />
8278
<Reference Include="System.Drawing" />
8379
<Reference Include="System.Web" />
8480
<Reference Include="System.Web.Http">
@@ -176,6 +172,7 @@
176172
<Content Include="Providers\DataProviders\SqlDataProvider\01.01.01.SqlDataProvider" />
177173
<Content Include="Providers\DataProviders\SqlDataProvider\Uninstall.SqlDataProvider" />
178174
<Content Include="Views\UserManage\BulkDelete.cshtml" />
175+
<Content Include="Providers\DataProviders\SqlDataProvider\01.05.00.SqlDataProvider" />
179176
</ItemGroup>
180177
<ItemGroup>
181178
<Content Include="App_LocalResources\RolesManageController.resx" />
@@ -186,6 +183,9 @@
186183
<ItemGroup>
187184
<Content Include="App_LocalResources\BulkDelete.resx" />
188185
</ItemGroup>
186+
<ItemGroup>
187+
<Content Include="App_LocalResources\Impersonate.resx" />
188+
</ItemGroup>
189189
<PropertyGroup>
190190
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
191191
<VSToolsPath Condition="'$(VSToolsPath)' == ''">

0 commit comments

Comments
 (0)