Port 7.7 - WIP
This commit is contained in:
@@ -21,6 +21,9 @@ namespace Umbraco.Core.Composing.CompositionRoots
|
||||
// register the service context
|
||||
container.RegisterSingleton<ServiceContext>();
|
||||
|
||||
// register the special idk map
|
||||
container.RegisterSingleton<IdkMap>();
|
||||
|
||||
// register the services
|
||||
container.RegisterSingleton<IMigrationEntryService, MigrationEntryService>();
|
||||
container.RegisterSingleton<IPublicAccessService, PublicAccessService>();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using NPoco;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
|
||||
namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
public int? StartMediaId { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.Many, ReferenceMemberName = "id")]
|
||||
public List<UserGroup2AppDto> UserGroup2AppDtos { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.DisableChangeTracking();
|
||||
|
||||
entity.CreateDate = d.createDate;
|
||||
entity.CreatorId = d.nodeUser;
|
||||
entity.CreatorId = d.nodeUser == null ? 0 : d.nodeUser;
|
||||
entity.Id = d.id;
|
||||
entity.Key = d.uniqueID;
|
||||
entity.Level = d.level;
|
||||
|
||||
@@ -7,47 +7,35 @@ using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class UserFactory
|
||||
internal static class UserFactory
|
||||
{
|
||||
private readonly IUserType _userType;
|
||||
|
||||
public UserFactory(IUserType userType)
|
||||
{
|
||||
_userType = userType;
|
||||
}
|
||||
|
||||
#region Implementation of IEntityFactory<IUser,UserDto>
|
||||
|
||||
public IUser BuildEntity(UserDto dto)
|
||||
public static IUser BuildEntity(UserDto dto)
|
||||
{
|
||||
var guidId = dto.Id.ToGuid();
|
||||
var user = new User(_userType);
|
||||
|
||||
var user = new User(dto.Id, dto.UserName, dto.Email, dto.Login,dto.Password,
|
||||
dto.UserGroupDtos.Select(x => x.ToReadOnlyGroup()).ToArray(),
|
||||
dto.UserStartNodeDtos.Where(x => x.StartNodeType == (int)UserStartNodeDto.StartNodeTypeValue.Content).Select(x => x.StartNode).ToArray(),
|
||||
dto.UserStartNodeDtos.Where(x => x.StartNodeType == (int)UserStartNodeDto.StartNodeTypeValue.Media).Select(x => x.StartNode).ToArray());
|
||||
|
||||
try
|
||||
{
|
||||
user.DisableChangeTracking();
|
||||
|
||||
user.Id = dto.Id;
|
||||
|
||||
user.Key = guidId;
|
||||
user.StartContentId = dto.ContentStartId;
|
||||
user.StartMediaId = dto.MediaStartId.HasValue ? dto.MediaStartId.Value : -1;
|
||||
user.RawPasswordValue = dto.Password;
|
||||
user.Username = dto.Login;
|
||||
user.Name = dto.UserName;
|
||||
user.IsLockedOut = dto.NoConsole;
|
||||
user.IsApproved = dto.Disabled == false;
|
||||
user.Email = dto.Email;
|
||||
user.Language = dto.UserLanguage;
|
||||
user.SecurityStamp = dto.SecurityStampToken;
|
||||
user.FailedPasswordAttempts = dto.FailedLoginAttempts ?? 0;
|
||||
user.LastLockoutDate = dto.LastLockoutDate ?? DateTime.MinValue;
|
||||
user.LastLoginDate = dto.LastLoginDate ?? DateTime.MinValue;
|
||||
user.LastPasswordChangeDate = dto.LastPasswordChangeDate ?? DateTime.MinValue;
|
||||
|
||||
foreach (var app in dto.User2AppDtos.EmptyNull())
|
||||
{
|
||||
user.AddAllowedSection(app.AppAlias);
|
||||
}
|
||||
user.CreateDate = dto.CreateDate;
|
||||
user.UpdateDate = dto.UpdateDate;
|
||||
user.Avatar = dto.Avatar;
|
||||
user.EmailConfirmedDate = dto.EmailConfirmedDate;
|
||||
user.InvitedDate = dto.InvitedDate;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
@@ -61,48 +49,55 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
}
|
||||
}
|
||||
|
||||
public UserDto BuildDto(IUser entity)
|
||||
public static UserDto BuildDto(IUser entity)
|
||||
{
|
||||
var dto = new UserDto
|
||||
{
|
||||
ContentStartId = entity.StartContentId,
|
||||
MediaStartId = entity.StartMediaId,
|
||||
Disabled = entity.IsApproved == false,
|
||||
Email = entity.Email,
|
||||
Login = entity.Username,
|
||||
NoConsole = entity.IsLockedOut,
|
||||
Password = entity.RawPasswordValue,
|
||||
UserLanguage = entity.Language,
|
||||
UserName = entity.Name,
|
||||
Type = short.Parse(entity.UserType.Id.ToString(CultureInfo.InvariantCulture)),
|
||||
User2AppDtos = new List<User2AppDto>(),
|
||||
SecurityStampToken = entity.SecurityStamp,
|
||||
FailedLoginAttempts = entity.FailedPasswordAttempts,
|
||||
LastLockoutDate = entity.LastLockoutDate == DateTime.MinValue ? (DateTime?)null : entity.LastLockoutDate,
|
||||
LastLoginDate = entity.LastLoginDate == DateTime.MinValue ? (DateTime?)null : entity.LastLoginDate,
|
||||
LastPasswordChangeDate = entity.LastPasswordChangeDate == DateTime.MinValue ? (DateTime?)null : entity.LastPasswordChangeDate,
|
||||
};
|
||||
{
|
||||
Disabled = entity.IsApproved == false,
|
||||
Email = entity.Email,
|
||||
Login = entity.Username,
|
||||
NoConsole = entity.IsLockedOut,
|
||||
Password = entity.RawPasswordValue,
|
||||
UserLanguage = entity.Language,
|
||||
UserName = entity.Name,
|
||||
SecurityStampToken = entity.SecurityStamp,
|
||||
FailedLoginAttempts = entity.FailedPasswordAttempts,
|
||||
LastLockoutDate = entity.LastLockoutDate == DateTime.MinValue ? (DateTime?)null : entity.LastLockoutDate,
|
||||
LastLoginDate = entity.LastLoginDate == DateTime.MinValue ? (DateTime?)null : entity.LastLoginDate,
|
||||
LastPasswordChangeDate = entity.LastPasswordChangeDate == DateTime.MinValue ? (DateTime?)null : entity.LastPasswordChangeDate,
|
||||
CreateDate = entity.CreateDate,
|
||||
UpdateDate = entity.UpdateDate,
|
||||
Avatar = entity.Avatar,
|
||||
EmailConfirmedDate = entity.EmailConfirmedDate,
|
||||
InvitedDate = entity.InvitedDate
|
||||
};
|
||||
|
||||
foreach (var app in entity.AllowedSections)
|
||||
foreach (var startNodeId in entity.StartContentIds)
|
||||
{
|
||||
var appDto = new User2AppDto
|
||||
{
|
||||
AppAlias = app
|
||||
};
|
||||
if (entity.HasIdentity)
|
||||
dto.UserStartNodeDtos.Add(new UserStartNodeDto
|
||||
{
|
||||
appDto.UserId = (int) entity.Id;
|
||||
}
|
||||
StartNode = startNodeId,
|
||||
StartNodeType = (int)UserStartNodeDto.StartNodeTypeValue.Content,
|
||||
UserId = entity.Id
|
||||
});
|
||||
}
|
||||
|
||||
dto.User2AppDtos.Add(appDto);
|
||||
foreach (var startNodeId in entity.StartMediaIds)
|
||||
{
|
||||
dto.UserStartNodeDtos.Add(new UserStartNodeDto
|
||||
{
|
||||
StartNode = startNodeId,
|
||||
StartNodeType = (int)UserStartNodeDto.StartNodeTypeValue.Media,
|
||||
UserId = entity.Id
|
||||
});
|
||||
}
|
||||
|
||||
if (entity.HasIdentity)
|
||||
{
|
||||
dto.Id = entity.Id.SafeCast<int>();
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal static class UserGroupFactory
|
||||
{
|
||||
public static IUserGroup BuildEntity(UserGroupDto dto)
|
||||
{
|
||||
var userGroup = new UserGroup(dto.UserCount, dto.Alias, dto.Name,
|
||||
dto.DefaultPermissions.IsNullOrWhiteSpace()
|
||||
? Enumerable.Empty<string>()
|
||||
: dto.DefaultPermissions.ToCharArray().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToList(),
|
||||
dto.Icon);
|
||||
|
||||
try
|
||||
{
|
||||
userGroup.DisableChangeTracking();
|
||||
userGroup.Id = dto.Id;
|
||||
userGroup.CreateDate = dto.CreateDate;
|
||||
userGroup.UpdateDate = dto.UpdateDate;
|
||||
userGroup.StartContentId = dto.StartContentId;
|
||||
userGroup.StartMediaId = dto.StartMediaId;
|
||||
if (dto.UserGroup2AppDtos != null)
|
||||
{
|
||||
foreach (var app in dto.UserGroup2AppDtos)
|
||||
{
|
||||
userGroup.AddAllowedSection(app.AppAlias);
|
||||
}
|
||||
}
|
||||
|
||||
userGroup.ResetDirtyProperties(false);
|
||||
return userGroup;
|
||||
}
|
||||
finally
|
||||
{
|
||||
userGroup.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public static UserGroupDto BuildDto(IUserGroup entity)
|
||||
{
|
||||
var dto = new UserGroupDto
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
DefaultPermissions = entity.Permissions == null ? "" : string.Join("", entity.Permissions),
|
||||
Name = entity.Name,
|
||||
UserGroup2AppDtos = new List<UserGroup2AppDto>(),
|
||||
CreateDate = entity.CreateDate,
|
||||
UpdateDate = entity.UpdateDate,
|
||||
Icon = entity.Icon,
|
||||
StartMediaId = entity.StartMediaId,
|
||||
StartContentId = entity.StartContentId
|
||||
};
|
||||
|
||||
foreach (var app in entity.AllowedSections)
|
||||
{
|
||||
var appDto = new UserGroup2AppDto
|
||||
{
|
||||
AppAlias = app
|
||||
};
|
||||
if (entity.HasIdentity)
|
||||
{
|
||||
appDto.UserGroupId = entity.Id;
|
||||
}
|
||||
|
||||
dto.UserGroup2AppDtos.Add(appDto);
|
||||
}
|
||||
|
||||
if (entity.HasIdentity)
|
||||
dto.Id = short.Parse(entity.Id.ToString());
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
internal class UserTypeFactory
|
||||
{
|
||||
#region Implementation of IEntityFactory<IUserType,UserTypeDto>
|
||||
|
||||
public IUserType BuildEntity(UserTypeDto dto)
|
||||
{
|
||||
var userType = new UserType();
|
||||
|
||||
try
|
||||
{
|
||||
userType.DisableChangeTracking();
|
||||
|
||||
userType.Alias = dto.Alias;
|
||||
userType.Id = dto.Id;
|
||||
userType.Name = dto.Name;
|
||||
userType.Permissions = dto.DefaultPermissions.IsNullOrWhiteSpace()
|
||||
? Enumerable.Empty<string>()
|
||||
: dto.DefaultPermissions.ToCharArray().Select(x => x.ToString(CultureInfo.InvariantCulture));
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
userType.ResetDirtyProperties(false);
|
||||
return userType;
|
||||
}
|
||||
finally
|
||||
{
|
||||
userType.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public UserTypeDto BuildDto(IUserType entity)
|
||||
{
|
||||
var userType = new UserTypeDto
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
DefaultPermissions = entity.Permissions == null ? "" : string.Join("", entity.Permissions),
|
||||
Name = entity.Name
|
||||
};
|
||||
|
||||
if(entity.HasIdentity)
|
||||
userType.Id = short.Parse(entity.Id.ToString());
|
||||
|
||||
return userType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
[MapperFor(typeof(IIdentityUserLogin))]
|
||||
[MapperFor(typeof(IdentityUserLogin))]
|
||||
public sealed class ExternalLoginMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
public ExternalLoginMapper()
|
||||
{
|
||||
BuildMap();
|
||||
}
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.CreateDate, dto => dto.CreateDate);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.LoginProvider, dto => dto.LoginProvider);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.ProviderKey, dto => dto.ProviderKey);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.UserId, dto => dto.UserId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="UserGroup"/> to DTO mapper used to translate the properties of the public api
|
||||
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
|
||||
/// </summary>
|
||||
[MapperFor(typeof(IUserGroup))]
|
||||
[MapperFor(typeof(UserGroup))]
|
||||
public sealed class UserGroupMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
public UserGroupMapper()
|
||||
{
|
||||
BuildMap();
|
||||
}
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.Alias, dto => dto.Alias);
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.Name, dto => dto.Name);
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.Icon, dto => dto.Icon);
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.StartContentId, dto => dto.StartContentId);
|
||||
CacheMap<UserGroup, UserGroupDto>(src => src.StartMediaId, dto => dto.StartMediaId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,9 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
[MapperFor(typeof(IIdentityUserLogin))]
|
||||
[MapperFor(typeof(IdentityUserLogin))]
|
||||
public sealed class ExternalLoginMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache => PropertyInfoCacheInstance;
|
||||
|
||||
protected override void BuildMap()
|
||||
{
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.CreateDate, dto => dto.CreateDate);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.LoginProvider, dto => dto.LoginProvider);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.ProviderKey, dto => dto.ProviderKey);
|
||||
CacheMap<IdentityUserLogin, ExternalLoginDto>(src => src.UserId, dto => dto.UserId);
|
||||
}
|
||||
}
|
||||
|
||||
[MapperFor(typeof(IUser))]
|
||||
[MapperFor(typeof(User))]
|
||||
public sealed class UserMapper : BaseMapper
|
||||
@@ -39,13 +20,16 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<User, UserDto>(src => src.RawPasswordValue, dto => dto.Password);
|
||||
CacheMap<User, UserDto>(src => src.Name, dto => dto.UserName);
|
||||
//NOTE: This column in the db is *not* used!
|
||||
//CacheMap<User, UserDto>(src => src.DefaultPermissions, dto => dto.DefaultPermissions);
|
||||
CacheMap<User, UserDto>(src => src.StartMediaId, dto => dto.MediaStartId);
|
||||
CacheMap<User, UserDto>(src => src.StartContentId, dto => dto.ContentStartId);
|
||||
//CacheMap<User, UserDto>(src => src.DefaultPermissions, dto => dto.DefaultPermissions);
|
||||
CacheMap<User, UserDto>(src => src.IsApproved, dto => dto.Disabled);
|
||||
CacheMap<User, UserDto>(src => src.IsLockedOut, dto => dto.NoConsole);
|
||||
CacheMap<User, UserDto>(src => src.UserType, dto => dto.Type);
|
||||
CacheMap<User, UserDto>(src => src.Language, dto => dto.UserLanguage);
|
||||
CacheMap<User, UserDto>(src => src.CreateDate, dto => dto.CreateDate);
|
||||
CacheMap<User, UserDto>(src => src.UpdateDate, dto => dto.UpdateDate);
|
||||
CacheMap<User, UserDto>(src => src.LastLockoutDate, dto => dto.LastLockoutDate);
|
||||
CacheMap<User, UserDto>(src => src.LastLoginDate, dto => dto.LastLoginDate);
|
||||
CacheMap<User, UserDto>(src => src.LastPasswordChangeDate, dto => dto.LastPasswordChangeDate);
|
||||
CacheMap<User, UserDto>(src => src.SecurityStamp, dto => dto.SecurityStampToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,5 +31,12 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
/// <param name="values"></param>
|
||||
/// <returns>This instance so calls to this method are chainable</returns>
|
||||
IQuery<T> WhereIn(Expression<Func<T, object>> fieldSelector, IEnumerable values);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a set of OR-ed where clauses to the query.
|
||||
/// </summary>
|
||||
/// <param name="predicates"></param>
|
||||
/// <returns>This instance so calls to this method are chainable.</returns>
|
||||
IQuery<T> WhereAny(IEnumerable<Expression<Func<T, bool>>> predicates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
@@ -54,6 +55,50 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a set of OR-ed where clauses to the query.
|
||||
/// </summary>
|
||||
/// <param name="predicates"></param>
|
||||
/// <returns>This instance so calls to this method are chainable.</returns>
|
||||
public virtual IQuery<T> WhereAny(IEnumerable<Expression<Func<T, bool>>> predicates)
|
||||
{
|
||||
if (predicates == null) return this;
|
||||
|
||||
StringBuilder sb = null;
|
||||
List<object> parameters = null;
|
||||
Sql sql = null;
|
||||
foreach (var predicate in predicates)
|
||||
{
|
||||
// see notes in Where()
|
||||
var expressionHelper = new ModelToSqlExpressionVisitor<T>();
|
||||
var whereExpression = expressionHelper.Visit(predicate);
|
||||
|
||||
if (sb == null)
|
||||
{
|
||||
sb = new StringBuilder("(");
|
||||
parameters = new List<object>();
|
||||
sql = new Sql();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(" OR ");
|
||||
sql.Append(" OR ");
|
||||
}
|
||||
|
||||
sb.Append(whereExpression);
|
||||
parameters.AddRange(expressionHelper.GetSqlParameters());
|
||||
sql.Append(whereExpression, expressionHelper.GetSqlParameters());
|
||||
}
|
||||
|
||||
if (sb == null) return this;
|
||||
|
||||
sb.Append(")");
|
||||
//_wheres.Add(Tuple.Create(sb.ToString(), parameters.ToArray()));
|
||||
_wheres.Add(Tuple.Create("(" + sql.SQL + ")", sql.Arguments));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all translated where clauses and their sql parameters
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Override the base content repository so we can change the node object type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It would be nicer if we could separate most of this down into a smaller version of the ContentRepository class, however to do that
|
||||
/// requires quite a lot of work since we'd need to re-organize the interhitance quite a lot or create a helper class to perform a lot of the underlying logic.
|
||||
///
|
||||
/// TODO: Create a helper method to contain most of the underlying logic for the ContentRepository
|
||||
/// </remarks>
|
||||
internal class ContentBlueprintRepository : ContentRepository
|
||||
{
|
||||
public ContentBlueprintRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings)
|
||||
: base(work, cacheHelper, logger, contentTypeRepository, templateRepository, tagRepository, settings)
|
||||
{
|
||||
EnsureUniqueNaming = false; // duplicates are allowed
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId => Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using NPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using NPoco;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
@@ -13,9 +13,6 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
@@ -32,17 +29,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
private readonly CacheHelper _cacheHelper;
|
||||
private PermissionRepository<IContent> _permissionRepository;
|
||||
|
||||
public ContentRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository /*, IContentSection contentSection*/)
|
||||
: base(work, cacheHelper, logger /*, contentSection*/)
|
||||
public ContentRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings)
|
||||
: base(work, cacheHelper, logger)
|
||||
{
|
||||
_contentTypeRepository = contentTypeRepository ?? throw new ArgumentNullException(nameof(contentTypeRepository));
|
||||
_templateRepository = templateRepository ?? throw new ArgumentNullException(nameof(templateRepository));
|
||||
_tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository));
|
||||
_cacheHelper = cacheHelper;
|
||||
|
||||
_publishedQuery = work.Query<IContent>().Where(x => x.Published);
|
||||
_publishedQuery = work.Query<IContent>().Where(x => x.Published); // fixme not used?
|
||||
|
||||
EnsureUniqueNaming = true;
|
||||
EnsureUniqueNaming = settings.EnsureUniqueNaming;
|
||||
}
|
||||
|
||||
protected override ContentRepository This => this;
|
||||
@@ -51,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
// note: is ok to 'new' the repo here as it's a sub-repo really
|
||||
private PermissionRepository<IContent> PermissionRepository => _permissionRepository
|
||||
?? (_permissionRepository = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper));
|
||||
?? (_permissionRepository = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper, Logger));
|
||||
|
||||
#region Overrides of RepositoryBase<IContent>
|
||||
|
||||
@@ -196,7 +193,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM umbracoRedirectUrl WHERE contentKey IN (SELECT uniqueID FROM umbracoNode WHERE id = @Id)",
|
||||
"DELETE FROM cmsTask WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE parentId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
@@ -213,12 +210,21 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId => new Guid(Constants.ObjectTypes.Document);
|
||||
protected override Guid NodeObjectTypeId => Constants.ObjectTypes.DocumentGuid;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of VersionableRepositoryBase<IContent>
|
||||
|
||||
public override IEnumerable<IContent> GetAllVersions(int id)
|
||||
{
|
||||
var sql = GetBaseQuery(false)
|
||||
.Where(GetBaseWhereClause(), new { Id = id })
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
|
||||
|
||||
return MapQueryDtos(Database.Fetch<DocumentDto>(sql), true);
|
||||
}
|
||||
|
||||
public override IContent GetByVersion(Guid versionId)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
@@ -345,24 +351,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
entity.SortOrder = sortOrder;
|
||||
entity.Level = level;
|
||||
|
||||
//Assign the same permissions to it as the parent node
|
||||
// http://issues.umbraco.org/issue/U4-2161
|
||||
var parentPermissions = PermissionRepository.GetPermissionsForEntity(entity.ParentId).ToArray();
|
||||
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
|
||||
// user's default permissions.
|
||||
if (parentPermissions.Any())
|
||||
{
|
||||
var userPermissions = (
|
||||
from perm in parentPermissions
|
||||
from p in perm.AssignedPermissions
|
||||
select new EntityPermissionSet.UserPermission(perm.UserId, p)).ToList();
|
||||
|
||||
PermissionRepository.ReplaceEntityPermissions(new EntityPermissionSet(entity.Id, userPermissions));
|
||||
//flag the entity's permissions changed flag so we can track those changes.
|
||||
//Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
|
||||
((Content)entity).PermissionsChanged = true;
|
||||
}
|
||||
|
||||
//Create the Content specific data - cmsContent
|
||||
var contentDto = dto.ContentVersionDto.ContentDto;
|
||||
contentDto.NodeId = nodeDto.NodeId;
|
||||
@@ -506,9 +494,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
//In order to update the ContentVersion we need to retrieve its primary key id
|
||||
var contentVerDto = Database.SingleOrDefault<ContentVersionDto>("WHERE VersionId = @Version", new { /*Version =*/ entity.Version });
|
||||
contentVersionDto.Id = contentVerDto.Id;
|
||||
|
||||
Database.Update(contentVersionDto);
|
||||
if (contentVerDto != null)
|
||||
{
|
||||
contentVersionDto.Id = contentVerDto.Id;
|
||||
Database.Update(contentVersionDto);
|
||||
}
|
||||
|
||||
Database.Update(dto);
|
||||
}
|
||||
|
||||
@@ -682,21 +674,30 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a single permission to the current content item for the specified user ids
|
||||
/// Assigns a single permission to the current content item for the specified group ids
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="userIds"></param>
|
||||
public void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> userIds)
|
||||
/// <param name="groupIds"></param>
|
||||
public void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> groupIds)
|
||||
{
|
||||
PermissionRepository.AssignEntityPermission(entity, permission, userIds);
|
||||
PermissionRepository.AssignEntityPermission(entity, permission, groupIds);
|
||||
}
|
||||
|
||||
public IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId)
|
||||
public EntityPermissionCollection GetPermissionsForEntity(int entityId)
|
||||
{
|
||||
return PermissionRepository.GetPermissionsForEntity(entityId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update a permission for a content item
|
||||
/// </summary>
|
||||
/// <param name="permission"></param>
|
||||
public void AddOrUpdatePermissions(ContentPermissionSet permission)
|
||||
{
|
||||
PermissionRepository.AddOrUpdate(permission);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged content results
|
||||
/// </summary>
|
||||
|
||||
@@ -137,6 +137,20 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return Database.Fetch<string>(sql);
|
||||
}
|
||||
|
||||
public IEnumerable<int> GetAllContentTypeIds(string[] aliases)
|
||||
{
|
||||
if (aliases.Length == 0) return Enumerable.Empty<int>();
|
||||
|
||||
var sql = Sql()
|
||||
.Select("cmsContentType.nodeId")
|
||||
.From<ContentTypeDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentTypeDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<ContentTypeDto>(dto => aliases.Contains(dto.Alias));
|
||||
|
||||
return Database.Fetch<int>(sql);
|
||||
}
|
||||
|
||||
protected override Sql<SqlContext> GetBaseQuery(bool isCount)
|
||||
{
|
||||
var sql = Sql();
|
||||
|
||||
@@ -1252,7 +1252,7 @@ WHERE cmsContent.nodeId IN (@ids) AND cmsContentType.isContainer=@isContainer",
|
||||
var list = new List<string>
|
||||
{
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContentTypeAllowedContentType WHERE Id = @Id",
|
||||
"DELETE FROM cmsContentTypeAllowedContentType WHERE AllowedId = @Id",
|
||||
|
||||
@@ -223,7 +223,7 @@ AND umbracoNode.id <> @id",
|
||||
throw new DuplicateNameException("A data type with the name " + entity.Name + " already exists");
|
||||
}
|
||||
|
||||
//Updates Modified date and Version Guid
|
||||
//Updates Modified date
|
||||
((DataTypeDefinition)entity).UpdatingEntity();
|
||||
|
||||
//Look up parent to get and set the correct Path if ParentId has changed
|
||||
@@ -263,7 +263,7 @@ AND umbracoNode.id <> @id",
|
||||
Database.Delete<User2NodeNotifyDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Remove Permissions
|
||||
Database.Delete<User2NodePermissionDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
Database.Delete<UserGroup2NodePermissionDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
//Remove associated tags
|
||||
Database.Delete<TagRelationshipDto>("WHERE nodeId = @Id", new { Id = entity.Id });
|
||||
|
||||
@@ -41,17 +41,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public IEnumerable<IUmbracoEntity> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection, IQuery<IUmbracoEntity> filter = null)
|
||||
{
|
||||
var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, sql =>
|
||||
{
|
||||
if (filter != null)
|
||||
{
|
||||
foreach (var filterClaus in filter.GetWhereClauses())
|
||||
foreach (var filterClause in filter.GetWhereClauses())
|
||||
{
|
||||
sql.Where(filterClaus.Item1, filterClaus.Item2);
|
||||
sql.Where(filterClause.Item1, filterClause.Item2);
|
||||
}
|
||||
}
|
||||
}, objectTypeId);
|
||||
@@ -142,9 +142,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
if (filter != null)
|
||||
{
|
||||
foreach (var filterClaus in filter.GetWhereClauses())
|
||||
foreach (var filterClause in filter.GetWhereClauses())
|
||||
{
|
||||
sql.Where(filterClaus.Item1, filterClaus.Item2);
|
||||
sql.Where(filterClause.Item1, filterClause.Item2);
|
||||
}
|
||||
}
|
||||
}, objectTypeId);
|
||||
@@ -171,8 +171,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public IUmbracoEntity GetByKey(Guid key, Guid objectTypeId)
|
||||
{
|
||||
var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
|
||||
var sql = GetFullSqlForEntityType(key, isContent, isMedia, objectTypeId);
|
||||
|
||||
@@ -223,8 +223,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IUmbracoEntity Get(int id, Guid objectTypeId)
|
||||
{
|
||||
var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
|
||||
var sql = GetFullSqlForEntityType(id, isContent, isMedia, objectTypeId);
|
||||
|
||||
@@ -253,22 +253,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids)
|
||||
{
|
||||
return ids.Any()
|
||||
? PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.id in (@ids)", new { /*ids =*/ ids }))
|
||||
return ids.Any()
|
||||
? PerformGetAll(objectTypeId, sql => sql.Where(" umbracoNode.id in (@ids)", new { ids }))
|
||||
: PerformGetAll(objectTypeId);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params Guid[] keys)
|
||||
{
|
||||
return keys.Any()
|
||||
? PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.uniqueID in (@keys)", new { /*keys =*/ keys }))
|
||||
return keys.Any()
|
||||
? PerformGetAll(objectTypeId, sql => sql.Where(" umbracoNode.uniqueID in (@keys)", new { keys }))
|
||||
: PerformGetAll(objectTypeId);
|
||||
}
|
||||
|
||||
private IEnumerable<IUmbracoEntity> PerformGetAll(Guid objectTypeId, Action<Sql> filter = null)
|
||||
{
|
||||
var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, filter);
|
||||
|
||||
if (isMedia)
|
||||
@@ -290,6 +290,27 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return collection.Select(x => x.BuildFromDynamic()).ToList();
|
||||
}
|
||||
|
||||
public virtual IEnumerable<EntityPath> GetAllPaths(Guid objectTypeId, params int[] ids)
|
||||
{
|
||||
return ids.Any()
|
||||
? PerformGetAllPaths(objectTypeId, sql => sql.Append(" AND umbracoNode.id in (@ids)", new { ids }))
|
||||
: PerformGetAllPaths(objectTypeId);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<EntityPath> GetAllPaths(Guid objectTypeId, params Guid[] keys)
|
||||
{
|
||||
return keys.Any()
|
||||
? PerformGetAllPaths(objectTypeId, sql => sql.Append(" AND umbracoNode.uniqueID in (@keys)", new { keys }))
|
||||
: PerformGetAllPaths(objectTypeId);
|
||||
}
|
||||
|
||||
private IEnumerable<EntityPath> PerformGetAllPaths(Guid objectTypeId, Action<Sql> filter = null)
|
||||
{
|
||||
var sql = new Sql("SELECT id, path FROM umbracoNode WHERE umbracoNode.nodeObjectType=@type", new { type = objectTypeId });
|
||||
if (filter != null) filter(sql);
|
||||
return _work.Database.Fetch<EntityPath>(sql);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var sqlClause = GetBase(false, false, null);
|
||||
@@ -306,8 +327,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId)
|
||||
{
|
||||
var isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
var isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, null, objectTypeId);
|
||||
|
||||
|
||||
@@ -39,18 +39,31 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IEnumerable<IContent> GetByPublishedVersion(IQuery<IContent> query);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a single permission to the current content item for the specified user ids
|
||||
/// Assigns a single permission to the current content item for the specified user group ids
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="userIds"></param>
|
||||
void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> userIds);
|
||||
/// <param name="groupIds"></param>
|
||||
void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> groupIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of permissions for the content item
|
||||
/// Gets the explicit list of permissions for the content item
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId);
|
||||
EntityPermissionCollection GetPermissionsForEntity(int entityId);
|
||||
|
||||
///// <summary>
|
||||
///// Gets the implicit/inherited list of permissions for the content item
|
||||
///// </summary>
|
||||
///// <param name="path"></param>
|
||||
///// <returns></returns>
|
||||
//IEnumerable<EntityPermission> GetPermissionsForPath(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add/update a permission for a content item
|
||||
/// </summary>
|
||||
/// <param name="permission"></param>
|
||||
void AddOrUpdatePermissions(ContentPermissionSet permission);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> GetAllContentTypeAliases(params Guid[] objectTypes);
|
||||
|
||||
IEnumerable<int> GetAllContentTypeIds(string[] aliases);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
UmbracoObjectTypes GetObjectType(int id);
|
||||
UmbracoObjectTypes GetObjectType(Guid key);
|
||||
|
||||
IEnumerable<EntityPath> GetAllPaths(Guid objectTypeId, params int[] ids);
|
||||
IEnumerable<EntityPath> GetAllPaths(Guid objectTypeId, params Guid[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged results
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IUserGroupRepository : IRepositoryQueryable<int, IUserGroup>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a group by it's alias
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <returns></returns>
|
||||
IUserGroup Get(string alias);
|
||||
|
||||
/// <summary>
|
||||
/// This is useful when an entire section is removed from config
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
IEnumerable<IUserGroup> GetGroupsAssignedToSection(string sectionAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Used to add or update a user group and assign users to it
|
||||
/// </summary>
|
||||
/// <param name="userGroup"></param>
|
||||
/// <param name="userIds"></param>
|
||||
void AddOrUpdateGroupWithUsers(IUserGroup userGroup, int[] userIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets explicilty defined permissions for the group for specified entities
|
||||
/// </summary>
|
||||
/// <param name="groupIds"></param>
|
||||
/// <param name="entityIds">Array of entity Ids, if empty will return permissions for the group for all entities</param>
|
||||
EntityPermissionCollection GetPermissions(int[] groupIds, params int[] entityIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets explicilt and default permissions (if requested) permissions for the group for specified entities
|
||||
/// </summary>
|
||||
/// <param name="groups"></param>
|
||||
/// <param name="fallbackToDefaultPermissions">If true will include the group's default permissions if no permissions are explicitly assigned</param>
|
||||
/// <param name="nodeIds">Array of entity Ids, if empty will return permissions for the group for all entities</param>
|
||||
EntityPermissionCollection GetPermissions(IReadOnlyUserGroup[] groups, bool fallbackToDefaultPermissions, params int[] nodeIds);
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the same permission set for a single group to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
/// <param name="permissions">Permissions as enumerable list of <see cref="char"/></param>
|
||||
/// <param name="entityIds">Specify the nodes to replace permissions for. If nothing is specified all permissions are removed.</param>
|
||||
void ReplaceGroupPermissions(int groupId, IEnumerable<char> permissions, params int[] entityIds);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the same permission set for a single group to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
/// <param name="permission">Permissions as enumerable list of <see cref="char"/></param>
|
||||
/// <param name="entityIds">Specify the nodes to replace permissions for</param>
|
||||
void AssignGroupPermission(int groupId, char permission, params int[] entityIds);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
@@ -22,47 +24,65 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(string username);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is useful when an entire section is removed from config
|
||||
/// Gets a list of <see cref="IUser"/> objects associated with a given group
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias);
|
||||
/// <param name="groupId">Id of group</param>
|
||||
IEnumerable<IUser> GetAllInGroup(int groupId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged member results
|
||||
/// Gets a list of <see cref="IUser"/> objects not associated with a given group
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
IEnumerable<IUser> GetAllNotInGroup(int groupId);
|
||||
|
||||
[Obsolete("Use the overload with long operators instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IUser, string>> orderBy);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged user results
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <param name="filter"></param>
|
||||
/// <param name="orderDirection"></param>
|
||||
/// <param name="userGroups">Optional parameter to filter by specified user groups</param>
|
||||
/// <param name="userState">Optional parameter to filter by specfied user state</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, Expression<Func<IUser, string>> orderBy);
|
||||
|
||||
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, Expression<Func<IUser, object>> orderBy, Direction orderDirection, string[] userGroups = null, UserState[] userState = null, IQuery<IUser> filter = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user permissions for the specified entities
|
||||
/// Returns a user by username
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds);
|
||||
/// <param name="username"></param>
|
||||
/// <param name="includeSecurityData">
|
||||
/// This is only used for a shim in order to upgrade to 7.7
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A non cached <see cref="IUser"/> instance
|
||||
/// </returns>
|
||||
IUser GetByUsername(string username, bool includeSecurityData);
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the same permission set for a single user to any number of entities
|
||||
/// Returns a user by id
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds);
|
||||
/// <param name="id"></param>
|
||||
/// <param name="includeSecurityData">
|
||||
/// This is only used for a shim in order to upgrade to 7.7
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// A non cached <see cref="IUser"/> instance
|
||||
/// </returns>
|
||||
IUser Get(int id, bool includeSecurityData);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the same permission set for a single user to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
void AssignUserPermission(int userId, char permission, params int[] entityIds);
|
||||
IProfile GetProfile(string username);
|
||||
IProfile GetProfile(int id);
|
||||
IDictionary<UserState, int> GetUserStates();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IUserTypeRepository : IUnitOfWorkRepository, IQueryRepository<int, IUserType>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
"DELETE FROM cmsTask WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE parentId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var list = new[]
|
||||
{
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE parentId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
"DELETE FROM cmsTask WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE parentId = @Id",
|
||||
"DELETE FROM umbracoRelation WHERE childId = @Id",
|
||||
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
|
||||
@@ -398,6 +398,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Overrides of VersionableRepositoryBase<IMembershipUser>
|
||||
|
||||
public override IEnumerable<IMember> GetAllVersions(int id)
|
||||
{
|
||||
var sql = GetBaseQuery(false)
|
||||
.Where(GetBaseWhereClause(), new { Id = id })
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
|
||||
|
||||
return MapQueryDtos(Database.Fetch<MemberDto>(sql), true);
|
||||
}
|
||||
|
||||
public override IMember GetByVersion(Guid versionId)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
var l = (List<string>)base.GetDeleteClauses(); // we know it's a list
|
||||
var l = (List<string>) base.GetDeleteClauses(); // we know it's a list
|
||||
l.Add("DELETE FROM cmsMemberType WHERE NodeId = @Id");
|
||||
l.Add("DELETE FROM cmsContentType WHERE nodeId = @Id");
|
||||
l.Add("DELETE FROM umbracoNode WHERE id = @Id");
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core.Events;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using CacheKeys = Umbraco.Core.Cache.CacheKeys;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -19,202 +18,207 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// A (sub) repository that exposes functionality to modify assigned permissions to a node
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
internal class PermissionRepository<TEntity>
|
||||
/// <remarks>
|
||||
/// This repo implements the base <see cref="NPocoRepositoryBase{TId,TEntity}"/> class so that permissions can be queued to be persisted
|
||||
/// like the normal repository pattern but the standard repository Get commands don't apply and will throw <see cref="NotImplementedException"/>
|
||||
/// </remarks>
|
||||
internal class PermissionRepository<TEntity> : NPocoRepositoryBase<int, ContentPermissionSet>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly IScopeUnitOfWork _unitOfWork;
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
|
||||
internal PermissionRepository(IScopeUnitOfWork unitOfWork, CacheHelper cache)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
//Make this repository use an isolated cache
|
||||
_runtimeCache = cache.IsolatedRuntimeCache.GetOrCreateCache<EntityPermission>();
|
||||
}
|
||||
|
||||
private ISqlSyntaxProvider SqlSyntax => _unitOfWork.SqlSyntax;
|
||||
public PermissionRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger)
|
||||
: base(work, cache, logger)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Returns permissions for a given user for any number of nodes
|
||||
/// Returns explicitly defined permissions for a user group for any number of nodes
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groupIds">
|
||||
/// The group ids to lookup permissions for
|
||||
/// </param>
|
||||
/// <param name="entityIds"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds)
|
||||
{
|
||||
var entityIdKey = string.Join(",", entityIds.Select(x => x.ToString(CultureInfo.InvariantCulture)));
|
||||
return _runtimeCache.GetCacheItem<IEnumerable<EntityPermission>>(
|
||||
string.Format("{0}{1}{2}", CacheKeys.UserPermissionsCacheKey, userId, entityIdKey),
|
||||
() =>
|
||||
/// <remarks>
|
||||
/// This method will not support passing in more than 2000 group Ids
|
||||
/// </remarks>
|
||||
public EntityPermissionCollection GetPermissionsForEntities(int[] groupIds, params int[] entityIds)
|
||||
{
|
||||
var result = new EntityPermissionCollection();
|
||||
|
||||
var whereBuilder = new StringBuilder();
|
||||
foreach (var groupOfGroupIds in groupIds.InGroupsOf(2000))
|
||||
{
|
||||
//copy local
|
||||
var localIds = groupOfGroupIds.ToArray();
|
||||
|
||||
//where userId = @userId AND
|
||||
whereBuilder.Append(SqlSyntax.GetQuotedColumnName("userId"));
|
||||
whereBuilder.Append("=");
|
||||
whereBuilder.Append(userId);
|
||||
|
||||
if (entityIds.Any())
|
||||
{
|
||||
whereBuilder.Append(" AND ");
|
||||
|
||||
//where nodeId = @nodeId1 OR nodeId = @nodeId2, etc...
|
||||
whereBuilder.Append("(");
|
||||
for (var index = 0; index < entityIds.Length; index++)
|
||||
{
|
||||
var entityId = entityIds[index];
|
||||
whereBuilder.Append(SqlSyntax.GetQuotedColumnName("nodeId"));
|
||||
whereBuilder.Append("=");
|
||||
whereBuilder.Append(entityId);
|
||||
if (index < entityIds.Length - 1)
|
||||
{
|
||||
whereBuilder.Append(" OR ");
|
||||
}
|
||||
}
|
||||
whereBuilder.Append(")");
|
||||
}
|
||||
|
||||
var sql = _unitOfWork.Sql()
|
||||
if (entityIds.Length == 0)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<User2NodePermissionDto>()
|
||||
.Where(whereBuilder.ToString());
|
||||
|
||||
//ToArray() to ensure it's all fetched from the db once.
|
||||
var result = _unitOfWork.Database.Fetch<User2NodePermissionDto>(sql).ToArray();
|
||||
return ConvertToPermissionList(result);
|
||||
|
||||
},
|
||||
//Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will only have this exist in cache for 20 minutes,
|
||||
// then it will refresh from the database.
|
||||
new TimeSpan(0, 20, 0),
|
||||
//Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will make this priority below average
|
||||
priority: CacheItemPriority.BelowNormal);
|
||||
.From<UserGroup2NodePermissionDto>()
|
||||
.Where<UserGroup2NodePermissionDto>(dto => localIds.Contains(dto.UserGroupId));
|
||||
var permissions = UnitOfWork.Database.Fetch<UserGroup2NodePermissionDto>(sql);
|
||||
foreach (var permission in ConvertToPermissionList(permissions))
|
||||
{
|
||||
result.Add(permission);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//iterate in groups of 2000 since we don't want to exceed the max SQL param count
|
||||
foreach (var groupOfEntityIds in entityIds.InGroupsOf(2000))
|
||||
{
|
||||
var ids = groupOfEntityIds;
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<UserGroup2NodePermissionDto>()
|
||||
.Where<UserGroup2NodePermissionDto>(dto => localIds.Contains(dto.UserGroupId) && ids.Contains(dto.NodeId));
|
||||
var permissions = UnitOfWork.Database.Fetch<UserGroup2NodePermissionDto>(sql);
|
||||
foreach (var permission in ConvertToPermissionList(permissions))
|
||||
{
|
||||
result.Add(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns permissions for all users for a given entity
|
||||
/// Returns permissions directly assigned to the content items for all user groups
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId)
|
||||
public IEnumerable<EntityPermission> GetPermissionsForEntities(int[] entityIds)
|
||||
{
|
||||
var sql = _unitOfWork.Sql()
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<User2NodePermissionDto>()
|
||||
.Where<User2NodePermissionDto>(dto => dto.NodeId == entityId)
|
||||
.OrderBy<User2NodePermissionDto>(dto => dto.NodeId);
|
||||
.From<UserGroup2NodePermissionDto>()
|
||||
.Where<UserGroup2NodePermissionDto>(dto => entityIds.Contains(dto.NodeId))
|
||||
.OrderBy<UserGroup2NodePermissionDto>(dto => dto.NodeId);
|
||||
|
||||
//ToArray() to ensure it's all fetched from the db once.
|
||||
var result = _unitOfWork.Database.Fetch<User2NodePermissionDto>(sql).ToArray();
|
||||
var result = UnitOfWork.Database.Fetch<UserGroup2NodePermissionDto>(sql);
|
||||
return ConvertToPermissionList(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the same permission set for a single user to any number of entities
|
||||
/// Returns permissions directly assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
public EntityPermissionCollection GetPermissionsForEntity(int entityId)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<UserGroup2NodePermissionDto>()
|
||||
.Where<UserGroup2NodePermissionDto>(dto => dto.NodeId == entityId)
|
||||
.OrderBy<UserGroup2NodePermissionDto>(dto => dto.NodeId);
|
||||
|
||||
var result = UnitOfWork.Database.Fetch<UserGroup2NodePermissionDto>(sql);
|
||||
return ConvertToPermissionList(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the same permission set for a single group to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <param name="permissions"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
/// <remarks>
|
||||
/// This will first clear the permissions for this user and entities and recreate them
|
||||
/// </remarks>
|
||||
public void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds)
|
||||
public void ReplacePermissions(int groupId, IEnumerable<char> permissions, params int[] entityIds)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
if (entityIds.Length == 0)
|
||||
return;
|
||||
|
||||
var db = UnitOfWork.Database;
|
||||
|
||||
//we need to batch these in groups of 2000 so we don't exceed the max 2100 limit
|
||||
var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND nodeId in (@nodeIds)";
|
||||
foreach (var idGroup in entityIds.InGroupsOf(2000))
|
||||
{
|
||||
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND nodeId in (@nodeIds)",
|
||||
new { userId = userId, nodeIds = idGroup });
|
||||
db.Execute(sql, new { groupId, nodeIds = idGroup });
|
||||
}
|
||||
|
||||
var toInsert = new List<User2NodePermissionDto>();
|
||||
var toInsert = new List<UserGroup2NodePermissionDto>();
|
||||
foreach (var p in permissions)
|
||||
{
|
||||
foreach (var e in entityIds)
|
||||
{
|
||||
toInsert.Add(new User2NodePermissionDto
|
||||
toInsert.Add(new UserGroup2NodePermissionDto
|
||||
{
|
||||
NodeId = e,
|
||||
Permission = p.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = userId
|
||||
UserGroupId = groupId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
db.BulkInsertRecords(toInsert);
|
||||
|
||||
//Raise the event
|
||||
_unitOfWork.Events.Dispatch(AssignedPermissions, this, new SaveEventArgs<EntityPermission>(ConvertToPermissionList(toInsert), false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns one permission for a user to many entities
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="groupId"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="entityIds"></param>
|
||||
public void AssignUserPermission(int userId, char permission, params int[] entityIds)
|
||||
public void AssignPermission(int groupId, char permission, params int[] entityIds)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
var db = UnitOfWork.Database;
|
||||
|
||||
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND permission=@permission AND nodeId in (@entityIds)",
|
||||
new
|
||||
{
|
||||
userId = userId,
|
||||
permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
entityIds = entityIds
|
||||
});
|
||||
var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND permission=@permission AND nodeId in (@entityIds)";
|
||||
db.Execute(sql,
|
||||
new
|
||||
{
|
||||
groupId,
|
||||
permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
entityIds
|
||||
});
|
||||
|
||||
var actions = entityIds.Select(id => new User2NodePermissionDto
|
||||
var actions = entityIds.Select(id => new UserGroup2NodePermissionDto
|
||||
{
|
||||
NodeId = id,
|
||||
Permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = userId
|
||||
UserGroupId = groupId
|
||||
}).ToArray();
|
||||
|
||||
db.BulkInsertRecords(actions);
|
||||
|
||||
//Raise the event
|
||||
_unitOfWork.Events.Dispatch(AssignedPermissions, this, new SaveEventArgs<EntityPermission>(ConvertToPermissionList(actions), false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns one permission to an entity for multiple users
|
||||
/// Assigns one permission to an entity for multiple groups
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="userIds"></param>
|
||||
public void AssignEntityPermission(TEntity entity, char permission, IEnumerable<int> userIds)
|
||||
/// <param name="groupIds"></param>
|
||||
public void AssignEntityPermission(TEntity entity, char permission, IEnumerable<int> groupIds)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
var db = UnitOfWork.Database;
|
||||
var groupIdsA = groupIds.ToArray();
|
||||
|
||||
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId AND permission=@permission AND userId in (@userIds)",
|
||||
const string sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId AND permission = @permission AND userGroupId in (@groupIds)";
|
||||
db.Execute(sql,
|
||||
new
|
||||
{
|
||||
nodeId = entity.Id,
|
||||
permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
userIds = userIds
|
||||
groupIdsA
|
||||
});
|
||||
|
||||
var actions = userIds.Select(id => new User2NodePermissionDto
|
||||
var actions = groupIdsA.Select(id => new UserGroup2NodePermissionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = id
|
||||
UserGroupId = id
|
||||
}).ToArray();
|
||||
|
||||
db.BulkInsertRecords(actions);
|
||||
|
||||
//Raise the event
|
||||
_unitOfWork.Events.Dispatch(AssignedPermissions, this, new SaveEventArgs<EntityPermission>(ConvertToPermissionList(actions), false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns permissions to an entity for multiple users/permission entries
|
||||
/// Assigns permissions to an entity for multiple group/permission entries
|
||||
/// </summary>
|
||||
/// <param name="permissionSet">
|
||||
/// </param>
|
||||
@@ -223,41 +227,109 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </remarks>
|
||||
public void ReplaceEntityPermissions(EntityPermissionSet permissionSet)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
var db = UnitOfWork.Database;
|
||||
|
||||
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId", new { nodeId = permissionSet.EntityId });
|
||||
const string sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId";
|
||||
db.Execute(sql, new { nodeId = permissionSet.EntityId });
|
||||
|
||||
var actions = permissionSet.UserPermissionsSet.Select(p => new User2NodePermissionDto
|
||||
var toInsert = new List<UserGroup2NodePermissionDto>();
|
||||
foreach (var entityPermission in permissionSet.PermissionsSet)
|
||||
{
|
||||
NodeId = permissionSet.EntityId,
|
||||
Permission = p.Permission,
|
||||
UserId = p.UserId
|
||||
}).ToArray();
|
||||
foreach (var permission in entityPermission.AssignedPermissions)
|
||||
{
|
||||
toInsert.Add(new UserGroup2NodePermissionDto
|
||||
{
|
||||
NodeId = permissionSet.EntityId,
|
||||
Permission = permission,
|
||||
UserGroupId = entityPermission.UserGroupId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
db.BulkInsertRecords(actions);
|
||||
|
||||
//Raise the event
|
||||
_unitOfWork.Events.Dispatch(AssignedPermissions, this, new SaveEventArgs<EntityPermission>(ConvertToPermissionList(actions), false));
|
||||
db.BulkInsertRecords(toInsert);
|
||||
}
|
||||
|
||||
private static IEnumerable<EntityPermission> ConvertToPermissionList(IEnumerable<User2NodePermissionDto> result)
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
|
||||
protected override ContentPermissionSet PerformGet(int id)
|
||||
{
|
||||
var permissions = new List<EntityPermission>();
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentPermissionSet> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<ContentPermissionSet> PerformGetByQuery(IQuery<ContentPermissionSet> query)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override Sql<SqlContext> GetBaseQuery(bool isCount)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId => throw new WontImplementException();
|
||||
|
||||
protected override void PersistDeletedItem(ContentPermissionSet entity)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Used to add or update entity permissions during a content item being updated
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
protected override void PersistNewItem(ContentPermissionSet entity)
|
||||
{
|
||||
//does the same thing as update
|
||||
PersistUpdatedItem(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to add or update entity permissions during a content item being updated
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
protected override void PersistUpdatedItem(ContentPermissionSet entity)
|
||||
{
|
||||
var asAggregateRoot = (IAggregateRoot)entity;
|
||||
if (asAggregateRoot.HasIdentity == false)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create permissions for an entity without an Id");
|
||||
}
|
||||
|
||||
ReplaceEntityPermissions(entity);
|
||||
}
|
||||
|
||||
private static EntityPermissionCollection ConvertToPermissionList(IEnumerable<UserGroup2NodePermissionDto> result)
|
||||
{
|
||||
var permissions = new EntityPermissionCollection();
|
||||
var nodePermissions = result.GroupBy(x => x.NodeId);
|
||||
foreach (var np in nodePermissions)
|
||||
{
|
||||
var userPermissions = np.GroupBy(x => x.UserId);
|
||||
foreach (var up in userPermissions)
|
||||
var userGroupPermissions = np.GroupBy(x => x.UserGroupId);
|
||||
foreach (var permission in userGroupPermissions)
|
||||
{
|
||||
var perms = up.Select(x => x.Permission).ToArray();
|
||||
permissions.Add(new EntityPermission(up.Key, up.First().NodeId, perms));
|
||||
var perms = permission.Select(x => x.Permission).Distinct().ToArray();
|
||||
permissions.Add(new EntityPermission(permission.Key, np.Key, perms));
|
||||
}
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
// todo - understand why we need this repository-level event, move it back to service
|
||||
|
||||
public static event TypedEventHandler<PermissionRepository<TEntity>, SaveEventArgs<EntityPermission>> AssignedPermissions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return Database.Fetch<TDto>(sql).Select(ConvertToEntity);
|
||||
}
|
||||
|
||||
protected override sealed IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query)
|
||||
protected sealed override IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<TEntity>(sqlClause, query);
|
||||
@@ -76,22 +76,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Not implemented and not required
|
||||
|
||||
protected override sealed IEnumerable<string> GetDeleteClauses()
|
||||
protected sealed override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override sealed Guid NodeObjectTypeId
|
||||
protected sealed override Guid NodeObjectTypeId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
protected override sealed void PersistNewItem(TEntity entity)
|
||||
protected sealed override void PersistNewItem(TEntity entity)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override sealed void PersistUpdatedItem(TEntity entity)
|
||||
protected sealed override void PersistUpdatedItem(TEntity entity)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var list = new List<string>
|
||||
{
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @Id",
|
||||
"UPDATE cmsDocument SET templateId = NULL WHERE templateId = @Id",
|
||||
"DELETE FROM cmsDocumentType WHERE templateNodeId = @Id",
|
||||
"DELETE FROM cmsTemplate WHERE nodeId = @Id",
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the UserGroupRepository for doing CRUD operations for <see cref="IUserGroup"/>
|
||||
/// </summary>
|
||||
internal class UserGroupRepository : NPocoRepositoryBase<int, IUserGroup>, IUserGroupRepository
|
||||
{
|
||||
private readonly UserGroupWithUsersRepository _userGroupWithUsersRepository;
|
||||
private readonly PermissionRepository<IContent> _permissionRepository;
|
||||
|
||||
public UserGroupRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger)
|
||||
: base(work, cacheHelper, logger)
|
||||
{
|
||||
_userGroupWithUsersRepository = new UserGroupWithUsersRepository(this, work, cacheHelper, logger);
|
||||
_permissionRepository = new PermissionRepository<IContent>(work, cacheHelper, logger);
|
||||
}
|
||||
|
||||
public const string GetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_";
|
||||
public static string GetByAliasCacheKey(string alias)
|
||||
{
|
||||
return GetByAliasCacheKeyPrefix + alias;
|
||||
}
|
||||
|
||||
public IUserGroup Get(string alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
//need to do a simple query to get the id - put this cache
|
||||
var id = IsolatedCache.GetCacheItem<int>(GetByAliasCacheKey(alias), () =>
|
||||
{
|
||||
var groupId = Database.ExecuteScalar<int?>("SELECT id FROM umbracoUserGroup WHERE userGroupAlias=@alias", new { alias });
|
||||
if (groupId.HasValue == false) throw new InvalidOperationException("No group found with alias " + alias);
|
||||
return groupId.Value;
|
||||
});
|
||||
|
||||
//return from the normal method which will cache
|
||||
return Get(id);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
//if this is caught it's because we threw this in the caching method
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IUserGroup> GetGroupsAssignedToSection(string sectionAlias)
|
||||
{
|
||||
//Here we're building up a query that looks like this, a sub query is required because the resulting structure
|
||||
// needs to still contain all of the section rows per user group.
|
||||
|
||||
//SELECT *
|
||||
//FROM [umbracoUserGroup]
|
||||
//LEFT JOIN [umbracoUserGroup2App]
|
||||
//ON [umbracoUserGroup].[id] = [umbracoUserGroup2App].[user]
|
||||
//WHERE umbracoUserGroup.id IN (SELECT umbracoUserGroup.id
|
||||
// FROM [umbracoUserGroup]
|
||||
// LEFT JOIN [umbracoUserGroup2App]
|
||||
// ON [umbracoUserGroup].[id] = [umbracoUserGroup2App].[user]
|
||||
// WHERE umbracoUserGroup2App.app = 'content')
|
||||
|
||||
var sql = GetBaseQuery(QueryType.Many);
|
||||
var innerSql = GetBaseQuery(QueryType.Ids);
|
||||
innerSql.Where("umbracoUserGroup2App.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
|
||||
sql.Where($"umbracoUserGroup.id IN ({innerSql.SQL})");
|
||||
AppendGroupBy(sql);
|
||||
|
||||
return ConvertFromDtos(Database.Fetch<UserGroupDto>(sql));
|
||||
}
|
||||
|
||||
public void AddOrUpdateGroupWithUsers(IUserGroup userGroup, int[] userIds)
|
||||
{
|
||||
_userGroupWithUsersRepository.AddOrUpdate(new UserGroupWithUsers(userGroup, userIds));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets explicilty defined permissions for the group for specified entities
|
||||
/// </summary>
|
||||
/// <param name="groupIds"></param>
|
||||
/// <param name="entityIds">Array of entity Ids, if empty will return permissions for the group for all entities</param>
|
||||
public EntityPermissionCollection GetPermissions(int[] groupIds, params int[] entityIds)
|
||||
{
|
||||
return _permissionRepository.GetPermissionsForEntities(groupIds, entityIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets explicilt and default permissions (if requested) permissions for the group for specified entities
|
||||
/// </summary>
|
||||
/// <param name="groups"></param>
|
||||
/// <param name="fallbackToDefaultPermissions">If true will include the group's default permissions if no permissions are explicitly assigned</param>
|
||||
/// <param name="nodeIds">Array of entity Ids, if empty will return permissions for the group for all entities</param>
|
||||
public EntityPermissionCollection GetPermissions(IReadOnlyUserGroup[] groups, bool fallbackToDefaultPermissions, params int[] nodeIds)
|
||||
{
|
||||
if (groups == null) throw new ArgumentNullException(nameof(groups));
|
||||
|
||||
var groupIds = groups.Select(x => x.Id).ToArray();
|
||||
var explicitPermissions = GetPermissions(groupIds, nodeIds);
|
||||
var result = new EntityPermissionCollection(explicitPermissions);
|
||||
|
||||
// If requested, and no permissions are assigned to a particular node, then we will fill in those permissions with the group's defaults
|
||||
if (fallbackToDefaultPermissions)
|
||||
{
|
||||
//if no node ids are passed in, then we need to determine the node ids for the explicit permissions set
|
||||
nodeIds = nodeIds.Length == 0
|
||||
? explicitPermissions.Select(x => x.EntityId).Distinct().ToArray()
|
||||
: nodeIds;
|
||||
|
||||
//if there are still no nodeids we can just exit
|
||||
if (nodeIds.Length == 0)
|
||||
return result;
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
foreach (var nodeId in nodeIds)
|
||||
{
|
||||
//TODO: We could/should change the EntityPermissionsCollection into a KeyedCollection and they key could be
|
||||
// a struct of the nodeid + groupid so then we don't actually allocate this class just to check if it's not
|
||||
// going to be included in the result!
|
||||
|
||||
var defaultPermission = new EntityPermission(group.Id, nodeId, group.Permissions.ToArray(), isDefaultPermissions: true);
|
||||
//Since this is a hashset, this will not add anything that already exists by group/node combination
|
||||
result.Add(defaultPermission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the same permission set for a single group to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
/// <param name="permissions">Permissions as enumerable list of <see cref="char"/> If nothing is specified all permissions are removed.</param>
|
||||
/// <param name="entityIds">Specify the nodes to replace permissions for. </param>
|
||||
public void ReplaceGroupPermissions(int groupId, IEnumerable<char> permissions, params int[] entityIds)
|
||||
{
|
||||
_permissionRepository.ReplacePermissions(groupId, permissions, entityIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the same permission set for a single group to any number of entities
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
/// <param name="permission">Permissions as enumerable list of <see cref="char"/></param>
|
||||
/// <param name="entityIds">Specify the nodes to replace permissions for</param>
|
||||
public void AssignGroupPermission(int groupId, char permission, params int[] entityIds)
|
||||
{
|
||||
_permissionRepository.AssignPermission(groupId, permission, entityIds);
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,IUserGroup>
|
||||
|
||||
protected override IUserGroup PerformGet(int id)
|
||||
{
|
||||
var sql = GetBaseQuery(QueryType.Single);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
AppendGroupBy(sql);
|
||||
|
||||
var dto = Database.Fetch<UserGroupDto>(sql).FirstOrDefault();
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var userGroup = UserGroupFactory.BuildEntity(dto);
|
||||
return userGroup;
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUserGroup> PerformGetAll(params int[] ids)
|
||||
{
|
||||
var sql = GetBaseQuery(QueryType.Many);
|
||||
|
||||
if (ids.Any())
|
||||
sql.WhereIn<UserDto>(x => x.Id, ids);
|
||||
else
|
||||
sql.Where<UserGroupDto>(x => x.Id >= 0);
|
||||
|
||||
AppendGroupBy(sql);
|
||||
|
||||
var dtos = Database.Fetch<UserGroupDto>(sql);
|
||||
return ConvertFromDtos(dtos);
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUserGroup> PerformGetByQuery(IQuery<IUserGroup> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery(QueryType.Many);
|
||||
var translator = new SqlTranslator<IUserGroup>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
AppendGroupBy(sql);
|
||||
|
||||
var dtos = Database.Fetch<UserGroupDto>(sql);
|
||||
return ConvertFromDtos(dtos);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of NPocoRepositoryBase<int,IUserGroup>
|
||||
|
||||
protected Sql<SqlContext> GetBaseQuery(QueryType type)
|
||||
{
|
||||
var sql = Sql();
|
||||
var addFrom = false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QueryType.Count:
|
||||
sql
|
||||
.SelectCount()
|
||||
.From<UserGroupDto>();
|
||||
break;
|
||||
case QueryType.Ids:
|
||||
sql
|
||||
.Select("umbracoUserGroup.id");
|
||||
addFrom = true;
|
||||
break;
|
||||
case QueryType.Single:
|
||||
case QueryType.Many:
|
||||
sql
|
||||
.Select<UserGroupDto>(r => r.Select<UserGroup2AppDto>())
|
||||
.Append(", COUNT(umbracoUser2UserGroup.UserId)"); // vs COUNT(umbracoUser.Id) - removes a JOIN
|
||||
addFrom = true;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException(type.ToString());
|
||||
}
|
||||
|
||||
if (addFrom)
|
||||
sql
|
||||
.From<UserGroupDto>()
|
||||
.LeftJoin<UserGroup2AppDto>()
|
||||
.On<UserGroupDto, UserGroup2AppDto>(left => left.Id, right => right.UserGroupId)
|
||||
.LeftJoin<User2UserGroupDto>()
|
||||
.On<User2UserGroupDto, UserGroupDto>(left => left.UserGroupId, right => right.Id)
|
||||
/*.LeftJoin<UserDto>()
|
||||
.On<UserDto, User2UserGroupDto>(left => left.Id, right => right.UserId)*/;
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected override Sql<SqlContext> GetBaseQuery(bool isCount)
|
||||
{
|
||||
return GetBaseQuery(isCount ? QueryType.Count : QueryType.Many);
|
||||
|
||||
// var sql = Sql();
|
||||
|
||||
// if (isCount)
|
||||
// {
|
||||
// sql.Select("COUNT(*)").From<UserGroupDto>();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return GetBaseQuery(@"umbracoUserGroup.createDate, umbracoUserGroup.icon, umbracoUserGroup.id, umbracoUserGroup.startContentId,
|
||||
//umbracoUserGroup.startMediaId, umbracoUserGroup.updateDate, umbracoUserGroup.userGroupAlias, umbracoUserGroup.userGroupDefaultPermissions,
|
||||
//umbracoUserGroup.userGroupName, COUNT(umbracoUser.id) AS UserCount, umbracoUserGroup2App.app, umbracoUserGroup2App.userGroupId");
|
||||
// }
|
||||
// return sql;
|
||||
}
|
||||
|
||||
//protected Sql<SqlContext> GetBaseQuery(string columns)
|
||||
//{
|
||||
// var sql = Sql()
|
||||
// .Select(columns)
|
||||
// .From<UserGroupDto>()
|
||||
// .LeftJoin<UserGroup2AppDto>()
|
||||
// .On<UserGroupDto, UserGroup2AppDto>(left => left.Id, right => right.UserGroupId)
|
||||
// .LeftJoin<User2UserGroupDto>()
|
||||
// .On<User2UserGroupDto, UserGroupDto>(left => left.UserGroupId, right => right.Id)
|
||||
// .LeftJoin<UserDto>()
|
||||
// .On<UserDto, User2UserGroupDto>(left => left.Id, right => right.UserId);
|
||||
|
||||
// return sql;
|
||||
//}
|
||||
|
||||
private static void AppendGroupBy(Sql sql)
|
||||
{
|
||||
sql.GroupBy(@"umbracoUserGroup.createDate, umbracoUserGroup.icon, umbracoUserGroup.id, umbracoUserGroup.startContentId,
|
||||
umbracoUserGroup.startMediaId, umbracoUserGroup.updateDate, umbracoUserGroup.userGroupAlias, umbracoUserGroup.userGroupDefaultPermissions,
|
||||
umbracoUserGroup.userGroupName, umbracoUserGroup2App.app, umbracoUserGroup2App.userGroupId");
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
return "umbracoUserGroup.id = @Id";
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
var list = new List<string>
|
||||
{
|
||||
"DELETE FROM umbracoUser2UserGroup WHERE userGroupId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2App WHERE userGroupId = @Id",
|
||||
"DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @Id",
|
||||
"DELETE FROM umbracoUserGroup WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId => throw new WontImplementException();
|
||||
|
||||
protected override void PersistNewItem(IUserGroup entity)
|
||||
{
|
||||
((UserGroup) entity).AddingEntity();
|
||||
|
||||
var userGroupDto = UserGroupFactory.BuildDto(entity);
|
||||
|
||||
var id = Convert.ToInt32(Database.Insert(userGroupDto));
|
||||
entity.Id = id;
|
||||
|
||||
PersistAllowedSections(entity);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(IUserGroup entity)
|
||||
{
|
||||
((UserGroup) entity).UpdatingEntity();
|
||||
|
||||
var userGroupDto = UserGroupFactory.BuildDto(entity);
|
||||
|
||||
Database.Update(userGroupDto);
|
||||
|
||||
PersistAllowedSections(entity);
|
||||
}
|
||||
|
||||
private void PersistAllowedSections(IUserGroup entity)
|
||||
{
|
||||
var userGroup = (UserGroup) entity;
|
||||
|
||||
// First delete all
|
||||
Database.Delete<UserGroup2AppDto>("WHERE UserGroupId = @UserGroupId", new { UserGroupId = userGroup.Id });
|
||||
|
||||
// Then re-add any associated with the group
|
||||
foreach (var app in userGroup.AllowedSections)
|
||||
{
|
||||
var dto = new UserGroup2AppDto
|
||||
{
|
||||
UserGroupId = userGroup.Id,
|
||||
AppAlias = app
|
||||
};
|
||||
Database.Insert(dto);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static IEnumerable<IUserGroup> ConvertFromDtos(IEnumerable<UserGroupDto> dtos)
|
||||
{
|
||||
return dtos.Select(UserGroupFactory.BuildEntity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// used to persist a user group with associated users at once
|
||||
/// </summary>
|
||||
private class UserGroupWithUsers : Entity, IAggregateRoot
|
||||
{
|
||||
public UserGroupWithUsers(IUserGroup userGroup, int[] userIds)
|
||||
{
|
||||
UserGroup = userGroup;
|
||||
UserIds = userIds;
|
||||
}
|
||||
|
||||
public override bool HasIdentity
|
||||
{
|
||||
get => UserGroup.HasIdentity;
|
||||
protected set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public IUserGroup UserGroup { get; }
|
||||
public int[] UserIds { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// used to persist a user group with associated users at once
|
||||
/// </summary>
|
||||
private class UserGroupWithUsersRepository : NPocoRepositoryBase<int, UserGroupWithUsers>
|
||||
{
|
||||
private readonly UserGroupRepository _userGroupRepo;
|
||||
|
||||
public UserGroupWithUsersRepository(UserGroupRepository userGroupRepo, IScopeUnitOfWork work, CacheHelper cache, ILogger logger)
|
||||
: base(work, cache, logger)
|
||||
{
|
||||
_userGroupRepo = userGroupRepo;
|
||||
}
|
||||
|
||||
#region Not implemented (don't need to for the purposes of this repo)
|
||||
|
||||
protected override UserGroupWithUsers PerformGet(int id)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<UserGroupWithUsers> PerformGetAll(params int[] ids)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<UserGroupWithUsers> PerformGetByQuery(IQuery<UserGroupWithUsers> query)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override Sql<SqlContext> GetBaseQuery(bool isCount)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId => throw new WontImplementException();
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void PersistNewItem(UserGroupWithUsers entity)
|
||||
{
|
||||
//save the user group
|
||||
_userGroupRepo.PersistNewItem(entity.UserGroup);
|
||||
|
||||
if (entity.UserIds == null)
|
||||
return;
|
||||
|
||||
//now the user association
|
||||
RemoveAllUsersFromGroup(entity.UserGroup.Id);
|
||||
AddUsersToGroup(entity.UserGroup.Id, entity.UserIds);
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(UserGroupWithUsers entity)
|
||||
{
|
||||
//save the user group
|
||||
_userGroupRepo.PersistUpdatedItem(entity.UserGroup);
|
||||
|
||||
if (entity.UserIds == null)
|
||||
return;
|
||||
|
||||
//now the user association
|
||||
RemoveAllUsersFromGroup(entity.UserGroup.Id);
|
||||
AddUsersToGroup(entity.UserGroup.Id, entity.UserIds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all users from a group
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
private void RemoveAllUsersFromGroup(int groupId)
|
||||
{
|
||||
Database.Delete<User2UserGroupDto>("WHERE userGroupId = @groupId", new { groupId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a set of users to a group
|
||||
/// </summary>
|
||||
/// <param name="groupId">Id of group</param>
|
||||
/// <param name="userIds">Ids of users</param>
|
||||
private void AddUsersToGroup(int groupId, int[] userIds)
|
||||
{
|
||||
//TODO: Check if the user exists?
|
||||
foreach (var userId in userIds)
|
||||
{
|
||||
var dto = new User2UserGroupDto
|
||||
{
|
||||
UserGroupId = groupId,
|
||||
UserId = userId,
|
||||
};
|
||||
Database.Insert(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Web.Security;
|
||||
using NPoco;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
@@ -17,6 +18,7 @@ using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -28,14 +30,24 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
private readonly IUserTypeRepository _userTypeRepository;
|
||||
private readonly CacheHelper _cacheHelper;
|
||||
private readonly IMapperCollection _mapperCollection;
|
||||
private readonly IDictionary<string, string> _passwordConfig;
|
||||
private PermissionRepository<IContent> _permissionRepository;
|
||||
|
||||
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IUserTypeRepository userTypeRepository, IMapperCollection mapperCollection)
|
||||
public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IUserTypeRepository userTypeRepository, IMapperCollection mapperCollection, IDictionary<string, string> passwordConfig = null)
|
||||
: base(work, cacheHelper, logger)
|
||||
{
|
||||
_userTypeRepository = userTypeRepository;
|
||||
_mapperCollection = mapperCollection;
|
||||
_cacheHelper = cacheHelper;
|
||||
|
||||
if (passwordConfig == null)
|
||||
{
|
||||
var userMembershipProvider = MembershipProviderExtensions.GetUsersMembershipProvider();
|
||||
passwordConfig = userMembershipProvider == null || userMembershipProvider.PasswordFormat != MembershipPasswordFormat.Hashed
|
||||
? null
|
||||
: new Dictionary<string, string> { { "hashAlgorithm", Membership.HashAlgorithmType } };
|
||||
}
|
||||
_passwordConfig = passwordConfig;
|
||||
}
|
||||
|
||||
// note: is ok to 'new' the repo here as it's a sub-repo really
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the UserTypeRepository for doing CRUD operations for <see cref="IUserType"/>
|
||||
/// </summary>
|
||||
internal class UserTypeRepository : NPocoRepositoryBase<int, IUserType>, IUserTypeRepository
|
||||
{
|
||||
public UserTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger)
|
||||
: base(work, cache, logger)
|
||||
{
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,IUserType>
|
||||
|
||||
protected override IUserType PerformGet(int id)
|
||||
{
|
||||
return GetAll(new[] {id}).FirstOrDefault();
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUserType> PerformGetAll(params int[] ids)
|
||||
{
|
||||
var userTypeFactory = new UserTypeFactory();
|
||||
|
||||
var sql = GetBaseQuery(false);
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
sql.Where("umbracoUserType.id in (@ids)", new { ids = ids });
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Where<UserTypeDto>(x => x.Id >= 0);
|
||||
}
|
||||
|
||||
var dtos = Database.Fetch<UserTypeDto>(sql);
|
||||
return dtos.Select(userTypeFactory.BuildEntity).ToArray();
|
||||
}
|
||||
|
||||
protected override IEnumerable<IUserType> PerformGetByQuery(IQuery<IUserType> query)
|
||||
{
|
||||
var userTypeFactory = new UserTypeFactory();
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IUserType>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var dtos = Database.Fetch<UserTypeDto>(sql);
|
||||
|
||||
return dtos.Select(userTypeFactory.BuildEntity).ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of NPocoRepositoryBase<int,IUserType>
|
||||
|
||||
protected override Sql<SqlContext> GetBaseQuery(bool isCount)
|
||||
{
|
||||
var sql = Sql();
|
||||
|
||||
sql = isCount
|
||||
? sql.SelectCount()
|
||||
: sql.Select<UserTypeDto>();
|
||||
|
||||
sql
|
||||
.From<UserTypeDto>();
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
return "umbracoUserType.id = @Id";
|
||||
}
|
||||
|
||||
protected override IEnumerable<string> GetDeleteClauses()
|
||||
{
|
||||
var list = new List<string>
|
||||
{
|
||||
"DELETE FROM umbracoUser WHERE userType = @Id",
|
||||
"DELETE FROM umbracoUserType WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override Guid NodeObjectTypeId
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
protected override void PersistNewItem(IUserType entity)
|
||||
{
|
||||
var userTypeFactory = new UserTypeFactory();
|
||||
var userTypeDto = userTypeFactory.BuildDto(entity);
|
||||
|
||||
var id = Convert.ToInt32(Database.Insert(userTypeDto));
|
||||
entity.Id = id;
|
||||
}
|
||||
|
||||
protected override void PersistUpdatedItem(IUserType entity)
|
||||
{
|
||||
var userTypeFactory = new UserTypeFactory();
|
||||
var userTypeDto = userTypeFactory.BuildDto(entity);
|
||||
|
||||
Database.Update(userTypeDto);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -50,22 +50,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the <see cref="TEntity"/> to retrieve versions from</param>
|
||||
/// <returns>An enumerable list of the same <see cref="TEntity"/> object with different versions</returns>
|
||||
public virtual IEnumerable<TEntity> GetAllVersions(int id)
|
||||
{
|
||||
var sql = Sql()
|
||||
.SelectAll()
|
||||
.From<ContentVersionDto>()
|
||||
.InnerJoin<ContentDto>()
|
||||
.On<ContentVersionDto, ContentDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<ContentDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
|
||||
.Where<NodeDto>(x => x.NodeId == id)
|
||||
.OrderByDescending<ContentVersionDto>(x => x.VersionDate);
|
||||
|
||||
var dtos = Database.Fetch<ContentVersionDto>(sql);
|
||||
return dtos.Select(x => GetByVersion(x.VersionId));
|
||||
}
|
||||
public abstract IEnumerable<TEntity> GetAllVersions(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all version Ids for the given content item ordered so latest is first
|
||||
|
||||
@@ -23,13 +23,15 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
private readonly MediaFileSystem _mediaFileSystem;
|
||||
private IQuery<IContent> _queryNotTrashed;
|
||||
private readonly IdkMap _idkMap;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ContentService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, MediaFileSystem mediaFileSystem)
|
||||
public ContentService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, MediaFileSystem mediaFileSystem, IdkMap idkMap)
|
||||
: base(provider, logger, eventMessagesFactory)
|
||||
{
|
||||
_mediaFileSystem = mediaFileSystem;
|
||||
_idkMap = idkMap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -105,36 +107,34 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a single permission to the current content item for the specified user ids
|
||||
/// Assigns a single permission to the current content item for the specified group ids
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="permission"></param>
|
||||
/// <param name="userIds"></param>
|
||||
public void AssignContentPermission(IContent entity, char permission, IEnumerable<int> userIds)
|
||||
/// <param name="groupIds"></param>
|
||||
public void AssignContentPermission(IContent entity, char permission, IEnumerable<int> groupIds)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
uow.WriteLock(Constants.Locks.ContentTree);
|
||||
var repo = uow.CreateRepository<IContentRepository>();
|
||||
repo.AssignEntityPermission(entity, permission, userIds);
|
||||
repo.AssignEntityPermission(entity, permission, groupIds);
|
||||
uow.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of permissions for the content item
|
||||
/// Returns implicit/inherited permissions assigned to the content item for all user groups
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<EntityPermission> GetPermissionsForEntity(IContent content)
|
||||
public EntityPermissionCollection GetPermissionsForEntity(IContent content)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
uow.ReadLock(Constants.Locks.ContentTree);
|
||||
var repo = uow.CreateRepository<IContentRepository>();
|
||||
var perms = repo.GetPermissionsForEntity(content.Id);
|
||||
uow.Complete();
|
||||
return perms;
|
||||
return repo.GetPermissionsForEntity(content.Id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
if (withIdentity)
|
||||
{
|
||||
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content)))
|
||||
if (uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content), "Saving"))
|
||||
{
|
||||
content.WasCancelled = true;
|
||||
return;
|
||||
@@ -326,16 +326,16 @@ namespace Umbraco.Core.Services
|
||||
|
||||
uow.Flush(); // need everything so we can serialize
|
||||
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false));
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false), "Saved");
|
||||
uow.Events.Dispatch(TreeChanged, this, new TreeChange<IContent>(content, TreeChangeTypes.RefreshNode).ToEventArgs());
|
||||
}
|
||||
|
||||
uow.Events.Dispatch(Created, this, new NewEventArgs<IContent>(content, false, content.ContentType.Alias, parent));
|
||||
|
||||
var msg = withIdentity
|
||||
? "Content '{0}' was created with Id {1}"
|
||||
: "Content '{0}' was created";
|
||||
Audit(uow, AuditType.New, string.Format(msg, content.Name, content.Id), content.CreatorId, content.Id);
|
||||
if (withIdentity == false)
|
||||
return;
|
||||
|
||||
Audit(uow, AuditType.New, $"Content '{content.Name}' was created with Id {content.Id}", content.CreatorId, content.Id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -386,13 +386,13 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent GetById(Guid key)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
uow.ReadLock(Constants.Locks.ContentTree);
|
||||
var repository = uow.CreateRepository<IContentRepository>();
|
||||
var query = uow.Query<IContent>().Where(x => x.Key == key);
|
||||
return repository.GetByQuery(query).SingleOrDefault();
|
||||
}
|
||||
// the repository implements a cache policy on int identifiers, not guids,
|
||||
// and we are not changing it now, but we still would like to rely on caching
|
||||
// instead of running a full query against the database, so relying on the
|
||||
// id-key map, which is fast.
|
||||
|
||||
var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Document);
|
||||
return a.Success ? GetById(a.Result) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -942,7 +942,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content, evtMsgs)))
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content, evtMsgs), "Saving"))
|
||||
{
|
||||
uow.Complete();
|
||||
return OperationStatus.Attempt.Cancel(evtMsgs);
|
||||
@@ -970,7 +970,7 @@ namespace Umbraco.Core.Services
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
if (raiseEvents)
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs));
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs), "Saved");
|
||||
var changeType = isNew ? TreeChangeTypes.RefreshBranch : TreeChangeTypes.RefreshNode;
|
||||
uow.Events.Dispatch(TreeChanged, this, new TreeChange<IContent>(content, changeType).ToEventArgs());
|
||||
Audit(uow, AuditType.Save, "Save Content performed by user", userId, content.Id);
|
||||
@@ -1009,7 +1009,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(contentsA, evtMsgs)))
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(contentsA, evtMsgs), "Saving"))
|
||||
{
|
||||
uow.Complete();
|
||||
return OperationStatus.Attempt.Cancel(evtMsgs);
|
||||
@@ -1035,7 +1035,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(contentsA, false, evtMsgs));
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(contentsA, false, evtMsgs), "Saved");
|
||||
uow.Events.Dispatch(TreeChanged, this, treeChanges.ToEventArgs());
|
||||
Audit(uow, AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
|
||||
|
||||
@@ -1670,8 +1670,20 @@ namespace Umbraco.Core.Services
|
||||
copy.CreatorId = userId;
|
||||
copy.WriterId = userId;
|
||||
|
||||
//get the current permissions, if there are any explicit ones they need to be copied
|
||||
var currentPermissions = GetPermissionsForEntity(content);
|
||||
currentPermissions.RemoveWhere(p => p.IsDefaultPermissions);
|
||||
|
||||
// save and flush because we need the ID for the recursive Copying events
|
||||
repository.AddOrUpdate(copy);
|
||||
|
||||
//add permissions
|
||||
if (currentPermissions.Count > 0)
|
||||
{
|
||||
var permissionSet = new ContentPermissionSet(copy, currentPermissions);
|
||||
repository.AddOrUpdatePermissions(permissionSet);
|
||||
}
|
||||
|
||||
uow.Flush();
|
||||
|
||||
// keep track of copies
|
||||
@@ -1818,7 +1830,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(itemsA)))
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(itemsA), "Saving"))
|
||||
return false;
|
||||
|
||||
var published = new List<IContent>();
|
||||
@@ -1855,7 +1867,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(saved, false));
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(saved, false), "Saved");
|
||||
|
||||
uow.Events.Dispatch(TreeChanged, this, saved.Select(x => new TreeChange<IContent>(x, TreeChangeTypes.RefreshNode)).ToEventArgs());
|
||||
|
||||
@@ -2038,7 +2050,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content)))
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, new SaveEventArgs<IContent>(content), "Saving"))
|
||||
{
|
||||
uow.Complete();
|
||||
return Attempt.Fail(new PublishStatus(PublishStatusType.FailedCancelledByEvent, evtMsgs, content));
|
||||
@@ -2067,7 +2079,7 @@ namespace Umbraco.Core.Services
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
if (raiseEvents) // always
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs));
|
||||
uow.Events.Dispatch(Saved, this, new SaveEventArgs<IContent>(content, false, evtMsgs), "Saved");
|
||||
|
||||
if (status.Success == false)
|
||||
{
|
||||
@@ -2234,6 +2246,16 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
internal static event TypedEventHandler<IContentService, TreeChange<IContent>.EventArgs> TreeChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after a blueprint has been saved.
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentService, SaveEventArgs<IContent>> SavedBlueprint;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after a blueprint has been deleted.
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentService, DeleteEventArgs<IContent>> DeletedBlueprint;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Publishing Strategies
|
||||
@@ -2599,6 +2621,115 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
return GetContentType(uow, contentTypeAlias);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Blueprints
|
||||
|
||||
public IContent GetBlueprintById(int id)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
uow.ReadLock(Constants.Locks.ContentTree);
|
||||
var repository = uow.CreateRepository<IContentBlueprintRepository>();
|
||||
var blueprint = repository.Get(id);
|
||||
if (blueprint != null)
|
||||
((Content) blueprint).IsBlueprint = true;
|
||||
return blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
public IContent GetBlueprintById(Guid id)
|
||||
{
|
||||
// the repository implements a cache policy on int identifiers, not guids,
|
||||
// and we are not changing it now, but we still would like to rely on caching
|
||||
// instead of running a full query against the database, so relying on the
|
||||
// id-key map, which is fast.
|
||||
|
||||
var a = _idkMap.GetIdForKey(id, UmbracoObjectTypes.DocumentBlueprint);
|
||||
return a.Success ? GetBlueprintById(a.Result) : null;
|
||||
}
|
||||
|
||||
public void SaveBlueprint(IContent content, int userId = 0)
|
||||
{
|
||||
//always ensure the blueprint is at the root
|
||||
if (content.ParentId != -1)
|
||||
content.ParentId = -1;
|
||||
|
||||
((Content) content).IsBlueprint = true;
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
uow.WriteLock(Constants.Locks.ContentTree);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(content.Name))
|
||||
{
|
||||
throw new ArgumentException("Cannot save content blueprint with empty name.");
|
||||
}
|
||||
|
||||
var repository = uow.CreateRepository<IContentBlueprintRepository>();
|
||||
|
||||
if (content.HasIdentity == false)
|
||||
{
|
||||
content.CreatorId = userId;
|
||||
}
|
||||
content.WriterId = userId;
|
||||
|
||||
repository.AddOrUpdate(content);
|
||||
|
||||
uow.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs<IContent>(content), "SavedBlueprint");
|
||||
|
||||
uow.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteBlueprint(IContent content, int userId = 0)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork())
|
||||
{
|
||||
uow.WriteLock(Constants.Locks.ContentTree);
|
||||
var repository = uow.CreateRepository<IContentBlueprintRepository>();
|
||||
repository.Delete(content);
|
||||
uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs<IContent>(content), "DeletedBlueprint");
|
||||
uow.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = 0)
|
||||
{
|
||||
if (blueprint == null) throw new ArgumentNullException(nameof(blueprint));
|
||||
|
||||
var contentType = blueprint.ContentType;
|
||||
var content = new Content(name, -1, contentType);
|
||||
content.Path = string.Concat(content.ParentId.ToString(), ",", content.Id);
|
||||
|
||||
content.CreatorId = userId;
|
||||
content.WriterId = userId;
|
||||
|
||||
foreach (var property in blueprint.Properties)
|
||||
content.SetValue(property.Alias, property.Value);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
public IEnumerable<IContent> GetBlueprintsForContentTypes(params int[] documentTypeIds)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = uow.CreateRepository<IContentBlueprintRepository>();
|
||||
|
||||
var query = uow.Query<IContent>();
|
||||
if (documentTypeIds.Length > 0)
|
||||
{
|
||||
query.Where(x => documentTypeIds.Contains(x.ContentTypeId));
|
||||
}
|
||||
return repository.GetByQuery(query).Select(x =>
|
||||
{
|
||||
((Content) x).IsBlueprint = true;
|
||||
return x;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="contentId"></param>
|
||||
public static void RemoveContentPermissions(this IContentService contentService, int contentId)
|
||||
{
|
||||
contentService.ReplaceContentPermissions(new EntityPermissionSet(contentId, Enumerable.Empty<EntityPermissionSet.UserPermission>()));
|
||||
contentService.ReplaceContentPermissions(new EntityPermissionSet(contentId, new EntityPermissionCollection()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Core.Services
|
||||
/// Gets all content type aliases accross content, media and member types.
|
||||
/// </summary>
|
||||
/// <param name="guids">Optional object types guid to restrict to content, and/or media, and/or member types.</param>
|
||||
/// <returns>All property type aliases.</returns>
|
||||
/// <returns>All content type aliases.</returns>
|
||||
/// <remarks>Beware! Works accross content, media and member types.</remarks>
|
||||
public IEnumerable<string> GetAllContentTypeAliases(params Guid[] guids)
|
||||
{
|
||||
@@ -66,5 +66,23 @@ namespace Umbraco.Core.Services
|
||||
return repo.GetAllContentTypeAliases(guids);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all content type id for aliases accross content, media and member types.
|
||||
/// </summary>
|
||||
/// <param name="aliases">Aliases to look for.</param>
|
||||
/// <returns>All content type ids.</returns>
|
||||
/// <remarks>Beware! Works accross content, media and member types.</remarks>
|
||||
public IEnumerable<int> GetAllContentTypeIds(string[] aliases)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
// that one is special because it works accross content, media and member types
|
||||
uow.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes);
|
||||
var repo = uow.CreateRepository<IContentTypeRepository>();
|
||||
return repo.GetAllContentTypeIds(aliases);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Events;
|
||||
@@ -19,19 +21,19 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
public class EntityService : ScopeRepositoryService, IEntityService
|
||||
{
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>> _supportedObjectTypes;
|
||||
private IQuery<IUmbracoEntity> _queryRootEntity;
|
||||
private readonly IdkMap _idkMap;
|
||||
|
||||
public EntityService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory,
|
||||
IContentService contentService, IContentTypeService contentTypeService,
|
||||
IMediaService mediaService, IMediaTypeService mediaTypeService,
|
||||
IDataTypeService dataTypeService,
|
||||
IMemberService memberService, IMemberTypeService memberTypeService,
|
||||
IMemberService memberService, IMemberTypeService memberTypeService, IdkMap idkMap)
|
||||
IRuntimeCacheProvider runtimeCache)
|
||||
: base(provider, logger, eventMessagesFactory)
|
||||
{
|
||||
_runtimeCache = runtimeCache;
|
||||
_idkMap = idkMap;
|
||||
|
||||
_supportedObjectTypes = new Dictionary<string, Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>>
|
||||
{
|
||||
@@ -42,27 +44,6 @@ namespace Umbraco.Core.Services
|
||||
{typeof (IMediaType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MediaType, mediaTypeService.Get)},
|
||||
{typeof (IMember).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.Member, memberService.GetById)},
|
||||
{typeof (IMemberType).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.MemberType, memberTypeService.Get)},
|
||||
//{typeof (IUmbracoEntity).FullName, new Tuple<UmbracoObjectTypes, Func<int, IUmbracoEntity>>(UmbracoObjectTypes.EntityContainer, id =>
|
||||
//{
|
||||
// using (var uow = UowProvider.GetUnitOfWork())
|
||||
// {
|
||||
// var found = uow.Database.FirstOrDefault<NodeDto>("SELECT * FROM umbracoNode WHERE id=@id", new { id = id });
|
||||
// return found == null ? null : new UmbracoEntity(found.Trashed)
|
||||
// {
|
||||
// Id = found.NodeId,
|
||||
// Name = found.Text,
|
||||
// Key = found.UniqueId,
|
||||
// SortOrder = found.SortOrder,
|
||||
// Path = found.Path,
|
||||
// NodeObjectTypeId = found.NodeObjectType.Value,
|
||||
// CreateDate = found.CreateDate,
|
||||
// CreatorId = found.UserId.Value,
|
||||
// Level = found.Level,
|
||||
// ParentId = found.ParentId
|
||||
// };
|
||||
// }
|
||||
|
||||
//})}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,21 +64,12 @@ namespace Umbraco.Core.Services
|
||||
/// <returns></returns>
|
||||
public Attempt<int> GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
|
||||
return _idkMap.GetIdForKey(key, umbracoObjectType);
|
||||
}
|
||||
|
||||
var sql = uow.Sql()
|
||||
.Select("id")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.UniqueId == key && x.NodeObjectType == nodeObjectType);
|
||||
|
||||
return uow.Database.ExecuteScalar<int?>(sql);
|
||||
}
|
||||
});
|
||||
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<int>.Fail();
|
||||
public Attempt<int> GetIdForUdi(Udi udi)
|
||||
{
|
||||
return _idkMap.GetIdForUdi(udi);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -108,29 +80,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns></returns>
|
||||
public Attempt<Guid> GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType);
|
||||
|
||||
var sql = uow.Sql()
|
||||
.Select("uniqueID")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeId == id && x.NodeObjectType == nodeObjectType);
|
||||
return uow.Database.ExecuteScalar<Guid?>(sql);
|
||||
}
|
||||
});
|
||||
return result.HasValue ? Attempt.Succeed(result.Value) : Attempt<Guid>.Fail();
|
||||
}
|
||||
|
||||
private static Guid GetNodeObjectTypeGuid(UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var guid = umbracoObjectType.GetGuid();
|
||||
if (guid == Guid.Empty)
|
||||
throw new NotSupportedException("Unsupported object type (" + umbracoObjectType + ").");
|
||||
|
||||
return guid;
|
||||
return _idkMap.GetKeyForId(id, umbracoObjectType);
|
||||
}
|
||||
|
||||
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true)
|
||||
@@ -433,7 +383,47 @@ namespace Umbraco.Core.Services
|
||||
IQuery<IUmbracoEntity> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = repository.Query.Where(x => x.Name.Contains(filter));
|
||||
filterQuery = uow.Query<IUmbracoEntity>().Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a paged collection of descendants.
|
||||
/// </summary>
|
||||
public IEnumerable<IUmbracoEntity> GetPagedDescendants(IEnumerable<int> ids, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||
{
|
||||
totalRecords = 0;
|
||||
|
||||
var idsA = ids.ToArray();
|
||||
if (idsA.Length == 0)
|
||||
return Enumerable.Empty<IUmbracoEntity>();
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = uow.CreateRepository<IEntityRepository>();
|
||||
|
||||
var query = uow.Query<IUmbracoEntity>();
|
||||
if (idsA.All(x => x != Constants.System.Root))
|
||||
{
|
||||
var clauses = new List<Expression<Func<IUmbracoEntity, bool>>>();
|
||||
foreach (var id in idsA)
|
||||
{
|
||||
var qid = id;
|
||||
clauses.Add(x => x.Path.SqlContains(string.Format(",{0},", qid), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar));
|
||||
}
|
||||
query.WhereAny(clauses);
|
||||
}
|
||||
|
||||
IQuery<IUmbracoEntity> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
filterQuery = uow.Query<IUmbracoEntity>().Where(x => x.Name.Contains(filter));
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
@@ -547,6 +537,36 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params int[] ids)
|
||||
{
|
||||
var entityType = GetEntityType(umbracoObjectType);
|
||||
var typeFullName = entityType.FullName;
|
||||
if (_supportedObjectTypes.ContainsKey(typeFullName) == false)
|
||||
throw new NotSupportedException("The passed in type is not supported.);
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = uow.CreateRepository<IEntityRepository>();
|
||||
return repository.GetAllPaths(objectTypeId, ids);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<EntityPath> GetAllPaths(UmbracoObjectTypes umbracoObjectType, params Guid[] keys)
|
||||
{
|
||||
var entityType = GetEntityType(umbracoObjectType);
|
||||
var typeFullName = entityType.FullName;
|
||||
if (_supportedObjectTypes.ContainsKey(typeFullName) == false)
|
||||
throw new NotSupportedException("The passed in type is not supported.);
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = uow.CreateRepository<IEntityRepository>();
|
||||
return repository.GetAllPaths(objectTypeId, keys);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IUmbracoEntity"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -22,13 +22,15 @@ namespace Umbraco.Core.Services
|
||||
public class MediaService : ScopeRepositoryService, IMediaService, IMediaServiceOperations
|
||||
{
|
||||
private readonly MediaFileSystem _mediaFileSystem;
|
||||
private readonly IdkMap _idkMap;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public MediaService(IScopeUnitOfWorkProvider provider, MediaFileSystem mediaFileSystem, ILogger logger, IEventMessagesFactory eventMessagesFactory)
|
||||
public MediaService(IScopeUnitOfWorkProvider provider, MediaFileSystem mediaFileSystem, ILogger logger, IEventMessagesFactory eventMessagesFactory, IdkMap idkMap)
|
||||
: base(provider, logger, eventMessagesFactory)
|
||||
{
|
||||
_mediaFileSystem = mediaFileSystem;
|
||||
_idkMap = idkMap;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -330,13 +332,13 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia GetById(Guid key)
|
||||
{
|
||||
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
|
||||
{
|
||||
uow.ReadLock(Constants.Locks.MediaTree);
|
||||
var repository = uow.CreateRepository<IMediaRepository>();
|
||||
var query = uow.Query<IMedia>().Where(x => x.Key == key);
|
||||
return repository.GetByQuery(query).SingleOrDefault();
|
||||
}
|
||||
// the repository implements a cache policy on int identifiers, not guids,
|
||||
// and we are not changing it now, but we still would like to rely on caching
|
||||
// instead of running a full query against the database, so relying on the
|
||||
// id-key map, which is fast.
|
||||
|
||||
var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Media);
|
||||
return a.Success ? GetById(a.Result) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -582,17 +582,27 @@
|
||||
<Compile Include="Models\MediaType.cs" />
|
||||
<Compile Include="Models\Member.cs" />
|
||||
<Compile Include="Models\MemberGroup.cs" />
|
||||
<Compile Include="Models\Membership\ContentPermissionSet.cs" />
|
||||
<Compile Include="Models\Membership\EntityPermission.cs" />
|
||||
<Compile Include="Models\Membership\EntityPermissionCollection.cs" />
|
||||
<Compile Include="Models\Membership\EntityPermissionSet.cs" />
|
||||
<Compile Include="Models\Membership\IMembershipUser.cs" />
|
||||
<Compile Include="Models\Membership\IProfile.cs" />
|
||||
<Compile Include="Models\Membership\IReadOnlyUserGroup.cs" />
|
||||
<Compile Include="Models\Membership\IUser.cs" />
|
||||
<Compile Include="Models\Membership\IUserGroup.cs" />
|
||||
<Compile Include="Models\Membership\IUserType.cs" />
|
||||
<Compile Include="Models\Membership\MemberCountType.cs" />
|
||||
<Compile Include="Models\Membership\MembershipScenario.cs" />
|
||||
<Compile Include="Models\Membership\MembershipUserExtensions.cs" />
|
||||
<Compile Include="Models\Membership\ReadOnlyUserGroup.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
|
||||
<Compile Include="Models\Membership\User.cs" />
|
||||
<Compile Include="Models\Membership\UserGroup.cs" />
|
||||
<Compile Include="Models\Membership\UserGroupExtensions.cs" />
|
||||
<Compile Include="Models\Membership\UserProfile.cs" />
|
||||
<Compile Include="Models\Membership\UserState.cs" />
|
||||
<Compile Include="Models\Membership\UserType.cs" />
|
||||
<Compile Include="Models\MemberType.cs" />
|
||||
<Compile Include="Models\MemberTypePropertyProfileAccess.cs" />
|
||||
@@ -691,10 +701,13 @@
|
||||
<Compile Include="Models\Rdbms\TaskDto.cs" />
|
||||
<Compile Include="Models\Rdbms\TaskTypeDto.cs" />
|
||||
<Compile Include="Models\Rdbms\TemplateDto.cs" />
|
||||
<Compile Include="Models\Rdbms\User2AppDto.cs" />
|
||||
<Compile Include="Models\Rdbms\User2NodeNotifyDto.cs" />
|
||||
<Compile Include="Models\Rdbms\User2NodePermissionDto.cs" />
|
||||
<Compile Include="Models\Rdbms\User2UserGroupDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserGroup2AppDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserGroup2NodePermissionDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserGroupDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserStartNodeDto.cs" />
|
||||
<Compile Include="Models\Rdbms\UserTypeDto.cs" />
|
||||
<Compile Include="Models\RedirectUrl.cs" />
|
||||
<Compile Include="Models\Relation.cs" />
|
||||
@@ -798,7 +811,7 @@
|
||||
<Compile Include="Persistence\Factories\TemplateFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\UmbracoEntityFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\UserFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\UserTypeFactory.cs" />
|
||||
<Compile Include="Persistence\Factories\UserGroupFactory.cs" />
|
||||
<Compile Include="Persistence\FaultHandling\ITransientErrorDetectionStrategy.cs" />
|
||||
<Compile Include="Persistence\FaultHandling\RetryingEventArgs.cs" />
|
||||
<Compile Include="Persistence\FaultHandling\RetryLimitExceededException.cs" />
|
||||
@@ -824,6 +837,7 @@
|
||||
<Compile Include="Persistence\Mappers\DictionaryTranslationMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\DomainMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\DtoMapModel.cs" />
|
||||
<Compile Include="Persistence\Mappers\ExternalLoginMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\IMapperCollection.cs" />
|
||||
<Compile Include="Persistence\Mappers\LanguageMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\MacroMapper.cs" />
|
||||
@@ -847,6 +861,7 @@
|
||||
<Compile Include="Persistence\Mappers\TaskTypeMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\TemplateMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\UmbracoEntityMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\UserGroupMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\UserMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\UserSectionMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\UserTypeMapper.cs" />
|
||||
@@ -1079,6 +1094,7 @@
|
||||
<Compile Include="Persistence\Querying\ValuePropertyMatchType.cs" />
|
||||
<Compile Include="Persistence\RecordPersistenceType.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\ContentBlueprintRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\ContentRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\ContentTypeRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\ContentTypeRepositoryBase.cs" />
|
||||
@@ -1285,17 +1301,23 @@
|
||||
<Compile Include="Security\BackOfficeUserManagerMarker.cs" />
|
||||
<Compile Include="Security\BackOfficeUserPasswordCheckerResult.cs" />
|
||||
<Compile Include="Security\BackOfficeUserStore.cs" />
|
||||
<Compile Include="Security\BackOfficeUserValidator.cs" />
|
||||
<Compile Include="Security\EmailService.cs" />
|
||||
<Compile Include="Security\IBackOfficeUserManagerMarker.cs" />
|
||||
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
|
||||
<Compile Include="Security\IMembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\IUmbracoMemberTypeMembershipProvider.cs" />
|
||||
<Compile Include="Security\IUserAwarePasswordHasher.cs" />
|
||||
<Compile Include="Security\IUsersMembershipProvider.cs" />
|
||||
<Compile Include="Security\MembershipPasswordHasher.cs" />
|
||||
<Compile Include="Security\MachineKeyGenerator.cs" />
|
||||
<Compile Include="Security\MembershipProviderBase.cs" />
|
||||
<Compile Include="Security\MembershipProviderExtensions.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordValidator.cs" />
|
||||
<Compile Include="Security\OwinExtensions.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
|
||||
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
|
||||
<Compile Include="Security\UserAwareMembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\UserData.cs" />
|
||||
<Compile Include="SemVersionExtensions.cs" />
|
||||
<Compile Include="Serialization\AbstractSerializationService.cs" />
|
||||
@@ -1344,6 +1366,7 @@
|
||||
<Compile Include="Services\IContentTypeService.cs" />
|
||||
<Compile Include="Services\IContentTypeServiceBase.cs" />
|
||||
<Compile Include="Services\IDataTypeService.cs" />
|
||||
<Compile Include="Services\IdkMap.cs" />
|
||||
<Compile Include="Services\IDomainService.cs" />
|
||||
<Compile Include="Services\IEntityService.cs" />
|
||||
<Compile Include="Services\IExternalLoginService.cs" />
|
||||
@@ -1494,6 +1517,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="FileResources\BlockingWeb.config" />
|
||||
<None Include="Models\Rdbms\UserDto.cs.orig" />
|
||||
<None Include="Models\Rdbms\UserTypeDto.cs.orig" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
Reference in New Issue
Block a user