decouple user repo from the membershi providers, lets see what happens with unit tests on the server

This commit is contained in:
Shannon
2017-07-31 18:15:30 +10:00
parent d103151159
commit b8971f0dd1
2 changed files with 89 additions and 69 deletions

View File

@@ -26,12 +26,23 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class UserRepository : PetaPocoRepositoryBase<int, IUser>, IUserRepository
{
//private readonly CacheHelper _cacheHelper;
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax)
private readonly IDictionary<string, string> _passwordConfiguration;
/// <summary>
/// Constructor
/// </summary>
/// <param name="work"></param>
/// <param name="cacheHelper"></param>
/// <param name="logger"></param>
/// <param name="sqlSyntax"></param>
/// <param name="passwordConfiguration">
/// A dictionary specifying the configuration for user passwords. If this is null then no password configuration will be persisted or read.
/// </param>
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax,
IDictionary<string, string> passwordConfiguration = null)
: base(work, cacheHelper, logger, sqlSyntax)
{
//_cacheHelper = cacheHelper;
_passwordConfiguration = passwordConfiguration;
}
#region Overrides of RepositoryBase<int,IUser>
@@ -46,8 +57,8 @@ namespace Umbraco.Core.Persistence.Repositories
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
var dto = Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, sql)
.FirstOrDefault();
.FirstOrDefault();
if (dto == null)
return null;
@@ -127,7 +138,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var sql = GetBaseQuery("umbracoUser.*");
sql.Where(GetBaseWhereClause(), new { Id = id });
dto = Database.FirstOrDefault<UserDto>(sql);
dto = Database.FirstOrDefault<UserDto>(sql);
}
if (dto == null)
@@ -139,14 +150,14 @@ namespace Umbraco.Core.Persistence.Repositories
public IProfile GetProfile(string username)
{
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.UserName == username, SqlSyntax);
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.UserName == username, SqlSyntax);
var dto = Database.Fetch<UserDto>(sql)
.FirstOrDefault();
if (dto == null)
return null;
return null;
return new UserProfile(dto.Id, dto.UserName);
}
@@ -176,8 +187,8 @@ UNION
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
ORDER BY colName";
var result = Database.Fetch<dynamic>(sql);
var result = Database.Fetch<dynamic>(sql);
return new Dictionary<UserState, int>
{
{UserState.All, result[0].num},
@@ -193,7 +204,7 @@ ORDER BY colName";
var sql = GetQueryWithGroups();
if (ids.Any())
{
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
sql.Where("umbracoUser.id in (@ids)", new { ids = ids });
}
sql //must be included for relator to work
.OrderBy<UserDto>(d => d.Id, SqlSyntax)
@@ -201,11 +212,11 @@ ORDER BY colName";
.OrderBy<UserStartNodeDto>(d => d.Id, SqlSyntax);
var users = ConvertFromDtos(Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, sql))
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return users;
}
}
protected override IEnumerable<IUser> PerformGetByQuery(IQuery<IUser> query)
{
var sqlClause = GetQueryWithGroups();
@@ -220,15 +231,15 @@ ORDER BY colName";
.DistinctBy(x => x.Id);
var users = ConvertFromDtos(dtos)
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return users;
}
}
#endregion
#region Overrides of PetaPocoRepositoryBase<int,IUser>
protected override Sql GetBaseQuery(bool isCount)
{
var sql = new Sql();
@@ -298,26 +309,25 @@ ORDER BY colName";
protected override Guid NodeObjectTypeId
{
get { throw new NotImplementedException(); }
}
}
protected override void PersistNewItem(IUser entity)
{
((User)entity).AddingEntity();
//ensure security stamp if non
//ensure security stamp if non
if (entity.SecurityStamp.IsNullOrWhiteSpace())
{
entity.SecurityStamp = Guid.NewGuid().ToString();
}
}
var userDto = UserFactory.BuildDto(entity);
//Check if we have a known config, we only want to store config for hashing
//TODO: This logic will need to be updated when we do http://issues.umbraco.org/issue/U4-10089
var membershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
if (membershipProvider.PasswordFormat == MembershipPasswordFormat.Hashed)
//TODO: This logic will need to be updated when we do http://issues.umbraco.org/issue/U4-10089
if (_passwordConfiguration != null && _passwordConfiguration.Count > 0)
{
var json = JsonConvert.SerializeObject(new { hashAlgorithm = Membership.HashAlgorithmType });
var json = JsonConvert.SerializeObject(_passwordConfiguration);
userDto.PasswordConfig = json;
}
@@ -341,8 +351,8 @@ ORDER BY colName";
//lookup all assigned
var assigned = entity.Groups == null || entity.Groups.Any() == false
? new List<UserGroupDto>()
: Database.Fetch<UserGroupDto>("SELECT * FROM umbracoUserGroup WHERE userGroupAlias IN (@aliases)", new { aliases = entity.Groups.Select(x => x.Alias) });
: Database.Fetch<UserGroupDto>("SELECT * FROM umbracoUserGroup WHERE userGroupAlias IN (@aliases)", new { aliases = entity.Groups.Select(x => x.Alias) });
foreach (var groupDto in assigned)
{
var dto = new User2UserGroupDto
@@ -360,18 +370,18 @@ ORDER BY colName";
protected override void PersistUpdatedItem(IUser entity)
{
//Updates Modified date
((User)entity).UpdatingEntity();
//ensure security stamp if non
((User)entity).UpdatingEntity();
//ensure security stamp if non
if (entity.SecurityStamp.IsNullOrWhiteSpace())
{
entity.SecurityStamp = Guid.NewGuid().ToString();
}
var userDto = UserFactory.BuildDto(entity);
//build list of columns to check for saving - we don't want to save the password if it hasn't changed!
//List the columns to save, NOTE: would be nice to not have hard coded strings here but no real good way around that
var userDto = UserFactory.BuildDto(entity);
//build list of columns to check for saving - we don't want to save the password if it hasn't changed!
//List the columns to save, NOTE: would be nice to not have hard coded strings here but no real good way around that
var colsToSave = new Dictionary<string, string>()
{
{"userDisabled", "IsApproved"},
@@ -379,8 +389,8 @@ ORDER BY colName";
{"startStructureID", "StartContentId"},
{"startMediaID", "StartMediaId"},
{"userName", "Name"},
{"userLogin", "Username"},
{"userEmail", "Email"},
{"userLogin", "Username"},
{"userEmail", "Email"},
{"userLanguage", "Language"},
{"securityStampToken", "SecurityStamp"},
{"lastLockoutDate", "LastLockoutDate"},
@@ -416,11 +426,12 @@ ORDER BY colName";
//Check if we have a known config, we only want to store config for hashing
//TODO: This logic will need to be updated when we do http://issues.umbraco.org/issue/U4-10089
var membershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
if (membershipProvider.PasswordFormat == MembershipPasswordFormat.Hashed)
if (_passwordConfiguration != null && _passwordConfiguration.Count > 0)
{
var json = JsonConvert.SerializeObject(new { hashAlgorithm = Membership.HashAlgorithmType });
var json = JsonConvert.SerializeObject(_passwordConfiguration);
userDto.PasswordConfig = json;
changedCols.Add("passwordConfig");
}
}
@@ -475,7 +486,7 @@ ORDER BY colName";
//remove the ones not assigned to the entity
var toDelete = assignedIds.Except(entityStartIds).ToArray();
if (toDelete.Length > 0)
Database.Delete<UserStartNodeDto>("WHERE UserId = @UserId AND startNode IN (@startNodes)", new {UserId = entity.Id, startNodes = toDelete});
Database.Delete<UserStartNodeDto>("WHERE UserId = @UserId AND startNode IN (@startNodes)", new { UserId = entity.Id, startNodes = toDelete });
//add the ones not currently in the db
var toAdd = entityStartIds.Except(assignedIds).ToArray();
foreach (var i in toAdd)
@@ -515,8 +526,8 @@ ORDER BY colName";
.Where<UserDto>(x => x.UserName == username);
return Database.ExecuteScalar<int>(sql) > 0;
}
}
/// <summary>
/// Gets a list of <see cref="IUser"/> objects associated with a given group
/// </summary>
@@ -566,8 +577,8 @@ ORDER BY colName";
var mappedField = mapper.Map(expressionMember.Name);
if (mappedField.IsNullOrWhiteSpace())
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
long tr;
var results = GetPagedResultsByQuery(query, Convert.ToInt64(pageIndex), pageSize, out tr, mappedField, Direction.Ascending);
totalRecords = Convert.ToInt32(tr);
@@ -603,13 +614,13 @@ ORDER BY colName";
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, mappedField, orderDirection, userGroups, userState, filter);
}
private IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection,
string[] userGroups = null,
UserState[] userState = null,
}
private IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection,
string[] userGroups = null,
UserState[] userState = null,
IQuery<IUser> filter = null)
{
if (string.IsNullOrWhiteSpace(orderBy)) throw new ArgumentException("Value cannot be null or whitespace.", "orderBy");
@@ -633,7 +644,7 @@ ORDER BY colName";
INNER JOIN umbracoUser2UserGroup ON umbracoUser2UserGroup.userId = umbracoUser.id
INNER JOIN umbracoUserGroup ON umbracoUserGroup.id = umbracoUser2UserGroup.userGroupId
WHERE umbracoUserGroup.userGroupAlias IN (@userGroups)))";
filterSql.Append(subQuery, new {userGroups= userGroups});
filterSql.Append(subQuery, new { userGroups = userGroups });
}
if (userState != null && userState.Length > 0)
{
@@ -671,12 +682,12 @@ ORDER BY colName";
}
// Get base query for returning IDs
var sqlBaseIds = GetBaseQuery("id");
var sqlBaseIds = GetBaseQuery("id");
if (query == null) query = new Query<IUser>();
var translatorIds = new SqlTranslator<IUser>(sqlBaseIds, query);
var sqlQueryIds = translatorIds.Translate();
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql),
@@ -696,11 +707,11 @@ ORDER BY colName";
string sqlStringCount, sqlStringPage;
Database.BuildPageQueries<UserDto>(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage);
var sqlQueryFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var sqlQueryFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var fullQueryWithPagedInnerJoin = sqlQueryFull
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
.Append(sqlStringPage, args)
.Append(") temp ")
.Append("ON umbracoUser.id = temp.id");

View File

@@ -1,6 +1,7 @@
using Umbraco.Core.Configuration;
using System;
using System.ComponentModel;
using System.Web.Security;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -9,6 +10,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Security;
namespace Umbraco.Core.Persistence
{
@@ -314,11 +316,18 @@ namespace Umbraco.Core.Persistence
public virtual IUserRepository CreateUserRepository(IScopeUnitOfWork uow)
{
var userMembershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
var passwordConfig = userMembershipProvider == null || userMembershipProvider.PasswordFormat != MembershipPasswordFormat.Hashed
? null
: new System.Collections.Generic.Dictionary<string, string> {{"hashAlgorithm", Membership.HashAlgorithmType}};
return new UserRepository(
uow,
//Need to cache users - we look up user information more than anything in the back office!
_cacheHelper,
_logger, _sqlSyntax);
_logger,
_sqlSyntax,
passwordConfig);
}
internal virtual IMacroRepository CreateMacroRepository(IScopeUnitOfWork uow)