From efab275c99ccccffb844b8c1b3865330dc44d371 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 27 Jan 2015 19:47:30 +1100 Subject: [PATCH] Fixes: U4-6188 umbracoNode.uniqueId needs to be changed to not allow nulls, U4-6187 umbracoNode.uniqueID needs a Unique index - currently it is a non-unique index, Gets the public access repository built and started testing --- src/Umbraco.Core/Models/EntityBase/Entity.cs | 2 +- src/Umbraco.Core/Models/PublicAccessEntry.cs | 177 ++++++++++++ src/Umbraco.Core/Models/PublicAccessRule.cs | 81 ++++++ src/Umbraco.Core/Models/Rdbms/AccessDto.cs | 36 ++- .../Models/Rdbms/AccessRuleDto.cs | 17 +- src/Umbraco.Core/Models/Rdbms/NodeDto.cs | 6 +- .../Persistence/Factories/ContentFactory.cs | 5 +- .../Factories/ContentTypeFactory.cs | 5 +- .../Factories/DataTypeDefinitionFactory.cs | 5 +- .../Persistence/Factories/MediaFactory.cs | 5 +- .../Persistence/Factories/MediaTypeFactory.cs | 5 +- .../Persistence/Factories/MemberFactory.cs | 5 +- .../Factories/MemberGroupFactory.cs | 2 +- .../Factories/PublicAccessEntryFactory.cs | 55 ++++ .../Persistence/Factories/TemplateFactory.cs | 2 +- .../Factories/UmbracoEntityFactory.cs | 2 +- .../AddPublicAccessTables.cs | 34 ++- .../UpdateUniqueIdToHaveCorrectIndexType.cs | 22 ++ .../Relators/AccessRulesRelator.cs | 43 +++ .../Repositories/ContentRepository.cs | 18 ++ .../Interfaces/IPublicAccessRepository.cs | 10 + .../Interfaces/ITaskRepository.cs | 5 - .../Interfaces/ITaskTypeRepository.cs | 9 + .../Repositories/PetaPocoRepositoryBase.cs | 8 +- .../Repositories/PublicAccessRepository.cs | 153 +++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 8 + .../Repositories/ContentRepositoryTest.cs | 8 +- .../PublicAccessRepositoryTest.cs | 259 ++++++++++++++++++ .../Repositories/TaskRepositoryTest.cs | 4 + src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + .../config/ClientDependency.config | 2 +- 31 files changed, 927 insertions(+), 67 deletions(-) create mode 100644 src/Umbraco.Core/Models/PublicAccessEntry.cs create mode 100644 src/Umbraco.Core/Models/PublicAccessRule.cs create mode 100644 src/Umbraco.Core/Persistence/Factories/PublicAccessEntryFactory.cs create mode 100644 src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs create mode 100644 src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/IPublicAccessRepository.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskTypeRepository.cs create mode 100644 src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs create mode 100644 src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index 315e2697c0..1551f29f86 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -59,7 +59,7 @@ namespace Umbraco.Core.Models.EntityBase /// The key is currectly used to store the Unique Id from the /// umbracoNode table, which many of the entities are based on. [DataMember] - public Guid Key + public virtual Guid Key { get { diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs new file mode 100644 index 0000000000..948f33bc03 --- /dev/null +++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + [Serializable] + [DataContract(IsReference = true)] + public class PublicAccessEntry : Entity, IAggregateRoot + { + private readonly ObservableCollection _ruleCollection; + private Guid _protectedNodeId; + private Guid _noAccessNodeId; + private Guid _loginNodeId; + private readonly List _removedRules = new List(); + + public PublicAccessEntry(IContent protectedNode, IContent loginNode, IContent noAccessNode, IEnumerable ruleCollection) + { + LoginNodeId = loginNode.Key; + NoAccessNodeId = noAccessNode.Key; + _protectedNodeId = protectedNode.Key; + + _ruleCollection = new ObservableCollection(ruleCollection); + _ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged; + } + + public PublicAccessEntry(Guid id, Guid protectedNodeId, Guid loginNodeId, Guid noAccessNodeId, IEnumerable ruleCollection) + { + Key = id; + + LoginNodeId = loginNodeId; + NoAccessNodeId = noAccessNodeId; + _protectedNodeId = protectedNodeId; + + _ruleCollection = new ObservableCollection(ruleCollection); + _ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged; + } + + void _ruleCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + OnPropertyChanged(AllowedSectionsSelector); + + //if (e.Action == NotifyCollectionChangedAction.Add) + //{ + // var item = e.NewItems.Cast().First(); + + // if (_addedSections.Contains(item) == false) + // { + // _addedSections.Add(item); + // } + //} + + if (e.Action == NotifyCollectionChangedAction.Remove) + { + var item = e.OldItems.Cast().First(); + + if (_removedRules.Contains(item.Key) == false) + { + _removedRules.Add(item.Key); + } + + } + } + + private static readonly PropertyInfo ProtectedNodeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ProtectedNodeId); + private static readonly PropertyInfo LoginNodeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.LoginNodeId); + private static readonly PropertyInfo NoAccessNodeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.NoAccessNodeId); + private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo>(x => x.Rules); + + internal IEnumerable RemovedRules + { + get { return _removedRules; } + } + + public IEnumerable Rules + { + get { return _ruleCollection; } + } + + public PublicAccessRule AddRule(string claim, string claimType) + { + var rule = new PublicAccessRule + { + AccessEntryId = Key, + Claim = claim, + ClaimType = claimType + }; + _ruleCollection.Add(rule); + return rule; + } + + public void RemoveRule(PublicAccessRule rule) + { + _ruleCollection.Remove(rule); + } + + /// + /// Method to call on entity saved when first added + /// + internal override void AddingEntity() + { + if (Key == default(Guid)) + { + Key = Guid.NewGuid(); + } + base.AddingEntity(); + } + + [DataMember] + public sealed override Guid Key + { + get { return base.Key; } + set + { + base.Key = value; + HasIdentity = true; + } + } + + [DataMember] + public Guid LoginNodeId + { + get { return _loginNodeId; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _loginNodeId = value; + return _loginNodeId; + }, _loginNodeId, LoginNodeIdSelector); + } + } + + [DataMember] + public Guid NoAccessNodeId + { + get { return _noAccessNodeId; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _noAccessNodeId = value; + return _noAccessNodeId; + }, _noAccessNodeId, NoAccessNodeIdSelector); + } + } + + [DataMember] + public Guid ProtectedNodeId + { + get { return _protectedNodeId; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _protectedNodeId = value; + return _protectedNodeId; + }, _protectedNodeId, ProtectedNodeIdSelector); + } + } + + public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties) + { + _removedRules.Clear(); + base.ResetDirtyProperties(rememberPreviouslyChangedProperties); + foreach (var publicAccessRule in _ruleCollection) + { + publicAccessRule.ResetDirtyProperties(rememberPreviouslyChangedProperties); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/PublicAccessRule.cs b/src/Umbraco.Core/Models/PublicAccessRule.cs new file mode 100644 index 0000000000..aefa681794 --- /dev/null +++ b/src/Umbraco.Core/Models/PublicAccessRule.cs @@ -0,0 +1,81 @@ +using System; +using System.Reflection; +using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models +{ + [Serializable] + [DataContract(IsReference = true)] + public class PublicAccessRule : Entity + { + private string _claim; + private string _claimType; + + public PublicAccessRule(Guid id, Guid accessEntryId) + { + AccessEntryId = accessEntryId; + Key = id; + Id = Key.GetHashCode(); + } + + public PublicAccessRule() + { + } + + private static readonly PropertyInfo ClaimSelector = ExpressionHelper.GetPropertyInfo(x => x.Claim); + private static readonly PropertyInfo ClaimTypeSelector = ExpressionHelper.GetPropertyInfo(x => x.ClaimType); + + public sealed override Guid Key + { + get { return base.Key; } + set + { + base.Key = value; + HasIdentity = true; + } + } + + public Guid AccessEntryId { get; internal set; } + + /// + /// Method to call on entity saved when first added + /// + internal override void AddingEntity() + { + if (Key == default(Guid)) + { + Key = Guid.NewGuid(); + } + base.AddingEntity(); + } + + public string Claim + { + get { return _claim; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _claim = value; + return _claim; + }, _claim, ClaimSelector); + } + } + + public string ClaimType + { + get { return _claimType; } + set + { + SetPropertyValueAndDetectChanges(o => + { + _claimType = value; + return _claimType; + }, _claimType, ClaimTypeSelector); + } + } + + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/AccessDto.cs b/src/Umbraco.Core/Models/Rdbms/AccessDto.cs index 486b755095..2c587946a1 100644 --- a/src/Umbraco.Core/Models/Rdbms/AccessDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/AccessDto.cs @@ -1,27 +1,43 @@ -using Umbraco.Core.Persistence; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Security.AccessControl; +using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoAccess")] - [PrimaryKey("id")] + [PrimaryKey("id", autoIncrement = false)] [ExplicitColumns] internal class AccessDto { [Column("id")] - [PrimaryKeyColumn(Name = "PK_umbracoAccess")] - public int Id { get; set; } + [PrimaryKeyColumn(Name = "PK_umbracoAccess", AutoIncrement = false)] + public Guid Id { get; set; } [Column("nodeId")] - [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_id")] - public int NodeId { get; set; } + [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_uniqueID", Column = "uniqueID")] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoAccess_nodeId")] + public Guid NodeId { get; set; } [Column("loginNodeId")] - [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_id1")] - public int LoginNodeId { get; set; } + [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_uniqueID1", Column = "uniqueID")] + public Guid LoginNodeId { get; set; } [Column("noAccessNodeId")] - [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_id2")] - public int AccessDeniedNodeId { get; set; } + [ForeignKey(typeof(NodeDto), Name = "FK_umbracoAccess_umbracoNode_uniqueID2", Column = "uniqueID")] + public Guid AccessDeniedNodeId { get; set; } + + [Column("createDate")] + [Constraint(Default = "getdate()")] + public DateTime CreateDate { get; set; } + + [Column("updateDate")] + [Constraint(Default = "getdate()")] + public DateTime UpdateDate { get; set; } + + [ResultColumn] + public List Rules { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs b/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs index 6b006fabb7..4a8961c9dd 100644 --- a/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/AccessRuleDto.cs @@ -1,25 +1,34 @@ +using System; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.DatabaseAnnotations; namespace Umbraco.Core.Models.Rdbms { [TableName("umbracoAccessRule")] - [PrimaryKey("id")] + [PrimaryKey("id", autoIncrement = false)] [ExplicitColumns] internal class AccessRuleDto { [Column("id")] - [PrimaryKeyColumn(Name = "PK_umbracoAccessRule")] - public int Id { get; set; } + [PrimaryKeyColumn(Name = "PK_umbracoAccessRule", AutoIncrement = false)] + public Guid Id { get; set; } [Column("accessId")] [ForeignKey(typeof(AccessDto), Name = "FK_umbracoAccessRule_umbracoAccess_id")] - public int AccessId { get; set; } + public Guid AccessId { get; set; } [Column("claim")] public string Claim { get; set; } [Column("claimType")] public string ClaimType { get; set; } + + [Column("createDate")] + [Constraint(Default = "getdate()")] + public DateTime CreateDate { get; set; } + + [Column("updateDate")] + [Constraint(Default = "getdate()")] + public DateTime UpdateDate { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs index f9aadf4963..33c1a73059 100644 --- a/src/Umbraco.Core/Models/Rdbms/NodeDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/NodeDto.cs @@ -40,9 +40,9 @@ namespace Umbraco.Core.Models.Rdbms public int SortOrder { get; set; } [Column("uniqueID")] - [NullSetting(NullSetting = NullSettings.Null)] - [Index(IndexTypes.NonClustered, Name = "IX_umbracoNodeUniqueID")] - public Guid? UniqueId { get; set; } + [NullSetting(NullSetting = NullSettings.NotNull)] + [Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoNodeUniqueID")] + public Guid UniqueId { get; set; } [Column("text")] [NullSetting(NullSetting = NullSettings.Null)] diff --git a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs index 0208a7a128..66dc6f64dc 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentFactory.cs @@ -32,10 +32,7 @@ namespace Umbraco.Core.Persistence.Factories var content = new Content(dto.Text, dto.ContentVersionDto.ContentDto.NodeDto.ParentId, _contentType) { Id = _id, - Key = - dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.HasValue - ? dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.Value - : _id.ToGuid(), + Key = dto.ContentVersionDto.ContentDto.NodeDto.UniqueId, Name = dto.Text, NodeName = dto.ContentVersionDto.ContentDto.NodeDto.Text, Path = dto.ContentVersionDto.ContentDto.NodeDto.Path, diff --git a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs index 23c9270906..fdd2759d76 100644 --- a/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/ContentTypeFactory.cs @@ -22,10 +22,7 @@ namespace Umbraco.Core.Persistence.Factories var contentType = new ContentType(dto.ContentTypeDto.NodeDto.ParentId) { Id = dto.ContentTypeDto.NodeDto.NodeId, - Key = - dto.ContentTypeDto.NodeDto.UniqueId.HasValue - ? dto.ContentTypeDto.NodeDto.UniqueId.Value - : dto.ContentTypeDto.NodeDto.NodeId.ToGuid(), + Key = dto.ContentTypeDto.NodeDto.UniqueId, Alias = dto.ContentTypeDto.Alias, Name = dto.ContentTypeDto.NodeDto.Text, Icon = dto.ContentTypeDto.Icon, diff --git a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs index 7b57800277..6fd6500552 100644 --- a/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/DataTypeDefinitionFactory.cs @@ -24,10 +24,7 @@ namespace Umbraco.Core.Persistence.Factories CreateDate = dto.NodeDto.CreateDate, DatabaseType = dto.DbType.EnumParse(true), Id = dto.DataTypeId, - Key = - dto.NodeDto.UniqueId.HasValue - ? dto.NodeDto.UniqueId.Value - : dto.DataTypeId.ToGuid(), + Key = dto.NodeDto.UniqueId, Level = dto.NodeDto.Level, UpdateDate = dto.NodeDto.CreateDate, Name = dto.NodeDto.Text, diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index cf285cbf66..2d8edcac52 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -32,10 +32,7 @@ namespace Umbraco.Core.Persistence.Factories var media = new Models.Media(dto.ContentDto.NodeDto.Text, dto.ContentDto.NodeDto.ParentId, _contentType) { Id = _id, - Key = - dto.ContentDto.NodeDto.UniqueId.HasValue - ? dto.ContentDto.NodeDto.UniqueId.Value - : _id.ToGuid(), + Key = dto.ContentDto.NodeDto.UniqueId, Path = dto.ContentDto.NodeDto.Path, CreatorId = dto.ContentDto.NodeDto.UserId.Value, Level = dto.ContentDto.NodeDto.Level, diff --git a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs index b63512e1b6..98048cd3a7 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaTypeFactory.cs @@ -21,10 +21,7 @@ namespace Umbraco.Core.Persistence.Factories var contentType = new MediaType(dto.NodeDto.ParentId) { Id = dto.NodeDto.NodeId, - Key = - dto.NodeDto.UniqueId.HasValue - ? dto.NodeDto.UniqueId.Value - : dto.NodeDto.NodeId.ToGuid(), + Key = dto.NodeDto.UniqueId, Alias = dto.Alias, Name = dto.NodeDto.Text, Icon = dto.Icon, diff --git a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs index 42e09b2f9c..a35c472f24 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberFactory.cs @@ -35,10 +35,7 @@ namespace Umbraco.Core.Persistence.Factories dto.Email,dto.LoginName,dto.Password, _contentType) { Id = _id, - Key = - dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.HasValue - ? dto.ContentVersionDto.ContentDto.NodeDto.UniqueId.Value - : _id.ToGuid(), + Key = dto.ContentVersionDto.ContentDto.NodeDto.UniqueId, Path = dto.ContentVersionDto.ContentDto.NodeDto.Path, CreatorId = dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value, Level = dto.ContentVersionDto.ContentDto.NodeDto.Level, diff --git a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs index 17dbba3001..9544d170e2 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberGroupFactory.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Factories { CreateDate = dto.CreateDate, Id = dto.NodeId, - Key = dto.UniqueId.Value, + Key = dto.UniqueId, Name = dto.Text }; diff --git a/src/Umbraco.Core/Persistence/Factories/PublicAccessEntryFactory.cs b/src/Umbraco.Core/Persistence/Factories/PublicAccessEntryFactory.cs new file mode 100644 index 0000000000..797914bce8 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Factories/PublicAccessEntryFactory.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Factories +{ + internal class PublicAccessEntryFactory + { + public PublicAccessEntry BuildEntity(AccessDto dto) + { + var entity = new PublicAccessEntry(dto.Id, dto.NodeId, dto.LoginNodeId, dto.AccessDeniedNodeId, + dto.Rules.Select(x => new PublicAccessRule(x.Id, x.AccessId) + { + Claim = x.Claim, + ClaimType = x.ClaimType, + CreateDate = x.CreateDate, + UpdateDate = x.UpdateDate + })) + { + CreateDate = dto.CreateDate, + UpdateDate = dto.UpdateDate + }; + + //on initial construction we don't want to have dirty properties tracked + // http://issues.umbraco.org/issue/U4-1946 + entity.ResetDirtyProperties(false); + return entity; + } + + public AccessDto BuildDto(PublicAccessEntry entity) + { + var dto = new AccessDto + { + Id = entity.Key, + AccessDeniedNodeId = entity.NoAccessNodeId, + LoginNodeId = entity.LoginNodeId, + NodeId = entity.ProtectedNodeId, + CreateDate = entity.CreateDate, + UpdateDate = entity.UpdateDate, + Rules = entity.Rules.Select(x => new AccessRuleDto + { + AccessId = x.AccessEntryId, + Id = x.Key, + Claim = x.Claim, + ClaimType = x.ClaimType, + CreateDate = x.CreateDate, + UpdateDate = x.UpdateDate + }).ToList() + }; + + return dto; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs index 1124d2e9a8..1e59c8e920 100644 --- a/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/TemplateFactory.cs @@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Factories { CreateDate = dto.NodeDto.CreateDate, Id = dto.NodeId, - Key = dto.NodeDto.UniqueId.Value, + Key = dto.NodeDto.UniqueId, Path = dto.NodeDto.Path }; diff --git a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs index 056d554d17..0494a25cfb 100644 --- a/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UmbracoEntityFactory.cs @@ -75,7 +75,7 @@ namespace Umbraco.Core.Persistence.Factories CreateDate = dto.CreateDate, CreatorId = dto.UserId.Value, Id = dto.NodeId, - Key = dto.UniqueId.Value, + Key = dto.UniqueId, Level = dto.Level, Name = dto.Text, NodeObjectTypeId = dto.NodeObjectType.Value, diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddPublicAccessTables.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddPublicAccessTables.cs index e2a5318051..0ab2e683b8 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddPublicAccessTables.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/AddPublicAccessTables.cs @@ -1,9 +1,10 @@ using System.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero { - [Migration("7.3.0", 5, GlobalSettings.UmbracoMigrationName)] + [Migration("7.3.0", 6, GlobalSettings.UmbracoMigrationName)] public class AddPublicAccessTables : MigrationBase { public override void Up() @@ -13,20 +14,31 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe if (tables.InvariantContains("umbracoAccess")) return; Create.Table("umbracoAccess") - .WithColumn("id").AsInt32().NotNullable().Identity().PrimaryKey("PK_umbracoAccess") - .WithColumn("nodeId").AsInt32().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id", "umbracoNode", "id") - .WithColumn("loginNodeId").AsInt32().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id1", "umbracoNode", "id") - .WithColumn("noAccessNodeId").AsInt32().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id2", "umbracoNode", "id"); + .WithColumn("id").AsGuid().NotNullable().PrimaryKey("PK_umbracoAccess") + .WithColumn("nodeId").AsGuid().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id", "umbracoNode", "uniqueID") + .WithColumn("loginNodeId").AsGuid().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id1", "umbracoNode", "uniqueID") + .WithColumn("noAccessNodeId").AsGuid().NotNullable().ForeignKey("FK_umbracoAccess_umbracoNode_id2", "umbracoNode", "uniqueID") + .WithColumn("createDate").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime) + .WithColumn("updateDate").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime); + + //unique constraint on node id = 1:1 + Create.Index("IX_umbracoAccess_nodeId").OnTable("umbracoAccess").OnColumn("nodeId").Unique(); Create.Table("umbracoAccessRule") - .WithColumn("id").AsInt32().NotNullable().Identity().PrimaryKey("PK_umbracoAccessRule") - .WithColumn("accessId").AsInt32().NotNullable().ForeignKey("FK_umbracoAccessRule_umbracoAccess_id", "umbracoAccess", "id") + .WithColumn("id").AsGuid().NotNullable().PrimaryKey("PK_umbracoAccessRule") + .WithColumn("accessId").AsGuid().NotNullable().ForeignKey("FK_umbracoAccessRule_umbracoAccess_id", "umbracoAccess", "id") .WithColumn("claim").AsString().NotNullable() - .WithColumn("claimType").AsString().NotNullable(); + .WithColumn("claimType").AsString().NotNullable() + .WithColumn("createDate").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime) + .WithColumn("updateDate").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentDateTime); - //Create.PrimaryKey("PK_cmsContentType2ContentType") - // .OnTable("cmsContentType2ContentType") - // .Columns(new[] { "parentContentTypeId", "childContentTypeId" }); + //unique constraint on node + claim + claim type + Create.Index("IX_umbracoAccessRule").OnTable("umbracoAccessRule") + .OnColumn("accessId").Ascending() + .OnColumn("claim").Ascending() + .OnColumn("claimType").Ascending() + .WithOptions() + .Unique(); } public override void Down() diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs new file mode 100644 index 0000000000..92876bbb4d --- /dev/null +++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSevenThreeZero/UpdateUniqueIdToHaveCorrectIndexType.cs @@ -0,0 +1,22 @@ +using Umbraco.Core.Configuration; + +namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZero +{ + [Migration("7.3.0", 5, GlobalSettings.UmbracoMigrationName)] + public class UpdateUniqueIdToHaveCorrectIndexType : MigrationBase + { + //see: http://issues.umbraco.org/issue/U4-6188, http://issues.umbraco.org/issue/U4-6187 + public override void Up() + { + //must be non-nullable + Alter.Column("uniqueID").OnTable("umbracoNode").AsGuid().NotNullable(); + //must be a uniqe index + Delete.Index("IX_umbracoNodeUniqueID").OnTable("umbracoNode"); + Create.Index("IX_umbracoNode_uniqueID").OnTable("umbracoNode").OnColumn("uniqueID").Unique(); + } + + public override void Down() + { + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs b/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs new file mode 100644 index 0000000000..424c68a863 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Relators/AccessRulesRelator.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using Umbraco.Core.Models.Rdbms; + +namespace Umbraco.Core.Persistence.Relators +{ + internal class AccessRulesRelator + { + internal AccessDto Current; + + internal AccessDto Map(AccessDto a, AccessRuleDto p) + { + // Terminating call. Since we can return null from this function + // we need to be ready for PetaPoco to callback later with null + // parameters + if (a == null) + return Current; + + // Is this the same AccessDto as the current one we're processing + if (Current != null && Current.Id == a.Id) + { + // Yes, just add this AccessRuleDto to the current AccessDto's collection + Current.Rules.Add(p); + + // Return null to indicate we're not done with this AccessDto yet + return null; + } + + // This is a different AccessDto to the current one, or this is the + // first time through and we don't have a Tab yet + + // Save the current AccessDto + var prev = Current; + + // Setup the new current AccessDto + Current = a; + Current.Rules = new List(); + Current.Rules.Add(p); + + // Return the now populated previous AccessDto (or null if first time through) + return prev; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 55ec8b3b25..3ac4f5f942 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -305,6 +305,24 @@ namespace Umbraco.Core.Persistence.Repositories #region Unit of Work Implementation + protected override void PersistDeletedItem(IContent entity) + { + //We need to clear out all access rules but we need to do this in a manual way + var subQuery = new Sql() + .Select("umbracoAccessRule.accessId") + .From(SqlSyntax) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.AccessId, right => right.Id) + .Where(dto => dto.NodeId == entity.Key); + Database.Execute(SqlSyntax.GetDeleteSubquery("umbracoAccessRule", "accessId", subQuery)); + //Now delete everything from umbracoAccess, we are doing this manually because we have joined on GUIDs instead + // of integers since we'll be moving to GUID for v8 for everything + Database.Execute("DELETE FROM umbracoAccess WHERE nodeId = @Key", new {Key = entity.Key}); + + //now let the normal delete clauses take care of everything else + base.PersistDeletedItem(entity); + } + protected override void PersistNewItem(IContent entity) { ((Content)entity).AddingEntity(); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IPublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IPublicAccessRepository.cs new file mode 100644 index 0000000000..9ce00cc13a --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IPublicAccessRepository.cs @@ -0,0 +1,10 @@ +using System; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface IPublicAccessRepository : IRepositoryQueryable + { + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskRepository.cs index d2b4770082..60f17c6de5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskRepository.cs @@ -4,11 +4,6 @@ using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { - public interface ITaskTypeRepository : IRepositoryQueryable - { - - } - public interface ITaskRepository : IRepositoryQueryable { IEnumerable GetTasks(int? itemId = null, int? assignedUser = null, int? ownerUser = null, string taskTypeAlias = null, bool includeClosed = false); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskTypeRepository.cs new file mode 100644 index 0000000000..ed35543ef6 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/ITaskTypeRepository.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Models; + +namespace Umbraco.Core.Persistence.Repositories +{ + public interface ITaskTypeRepository : IRepositoryQueryable + { + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs index 872b7f1d14..fe363fea16 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data.SqlServerCe; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; @@ -72,8 +73,13 @@ namespace Umbraco.Core.Persistence.Repositories var deletes = GetDeleteClauses(); foreach (var delete in deletes) { - Database.Execute(delete, new {Id = entity.Id}); + Database.Execute(delete, new { Id = GetEntityId(entity) }); } } + + protected virtual TId GetEntityId(TEntity entity) + { + return (TId)(object)entity.Id; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs new file mode 100644 index 0000000000..e2c02523d9 --- /dev/null +++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Models.Rdbms; +using Umbraco.Core.Persistence.Factories; +using Umbraco.Core.Persistence.Querying; +using Umbraco.Core.Persistence.Relators; +using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Persistence.Repositories +{ + internal class PublicAccessRepository : PetaPocoRepositoryBase, IPublicAccessRepository + { + public PublicAccessRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + } + + protected override PublicAccessEntry PerformGet(Guid id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), new { Id = id }); + + var taskDto = Database.Fetch(new AccessRulesRelator().Map, sql).FirstOrDefault(); + if (taskDto == null) + return null; + + var factory = new PublicAccessEntryFactory(); + var entity = factory.BuildEntity(taskDto); + return entity; + } + + protected override IEnumerable PerformGetAll(params Guid[] ids) + { + var sql = GetBaseQuery(false); + + if (ids.Any()) + { + sql.Where("umbracoAccess.id IN (@ids)", new { ids = ids }); + } + + var factory = new PublicAccessEntryFactory(); + var dtos = Database.Fetch(new AccessRulesRelator().Map, sql); + return dtos.Select(factory.BuildEntity); + } + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + var sqlClause = GetBaseQuery(false); + var translator = new SqlTranslator(sqlClause, query); + var sql = translator.Translate(); + + var factory = new PublicAccessEntryFactory(); + var dtos = Database.Fetch(new AccessRulesRelator().Map, sql); + return dtos.Select(factory.BuildEntity); + } + + protected override Sql GetBaseQuery(bool isCount) + { + var sql = new Sql(); + sql.Select("*") + .From(SqlSyntax) + .InnerJoin(SqlSyntax) + .On(SqlSyntax, left => left.Id, right => right.AccessId); + + return sql; + } + + protected override string GetBaseWhereClause() + { + return "umbracoAccess.id = @Id"; + } + + protected override IEnumerable GetDeleteClauses() + { + var list = new List + { + "DELETE FROM umbracoAccessRule WHERE accessId = @Id", + "DELETE FROM umbracoAccess WHERE id = @Id" + }; + return list; + } + + protected override Guid NodeObjectTypeId + { + get { throw new NotImplementedException(); } + } + + protected override void PersistNewItem(PublicAccessEntry entity) + { + entity.AddingEntity(); + entity.Rules.ForEach(x => x.AddingEntity()); + + var factory = new PublicAccessEntryFactory(); + var dto = factory.BuildDto(entity); + + Database.Insert(dto); + + foreach (var rule in dto.Rules) + { + rule.AccessId = entity.Key; + Database.Insert(rule); + } + + entity.ResetDirtyProperties(); + } + + protected override void PersistUpdatedItem(PublicAccessEntry entity) + { + entity.UpdatingEntity(); + entity.Rules.Where(x => x.HasIdentity).ForEach(x => x.UpdatingEntity()); + entity.Rules.Where(x => x.HasIdentity == false).ForEach(x => x.AddingEntity()); + + var factory = new PublicAccessEntryFactory(); + var dto = factory.BuildDto(entity); + + Database.Update(dto); + + foreach (var rule in entity.Rules) + { + if (rule.HasIdentity) + { + Database.Update(dto.Rules.Single(x => x.Id == rule.Key)); + } + else + { + Database.Insert(new AccessRuleDto + { + AccessId = dto.NodeId, + Claim = rule.Claim, + ClaimType = rule.ClaimType, + CreateDate = rule.CreateDate, + UpdateDate = rule.UpdateDate + }); + } + } + foreach (var removedRule in entity.RemovedRules) + { + Database.Delete("WHERE id=@Id", new {Id = removedRule}); + } + + entity.ResetDirtyProperties(); + } + + protected override Guid GetEntityId(PublicAccessEntry entity) + { + return entity.Key; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b759c51634..ab9d578fbf 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -320,22 +320,30 @@ + + + + + + + + diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 2a65297864..f943f05de6 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -44,10 +44,10 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { - var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax); - contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, templateRepository); - var repository = new ContentRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository); + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository); return repository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs new file mode 100644 index 0000000000..e42a21a115 --- /dev/null +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Web.UI.WebControls; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.IO; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Repositories; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; +using Content = Umbraco.Core.Models.Content; + +namespace Umbraco.Tests.Persistence.Repositories +{ + [DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)] + [TestFixture] + public class PublicAccessRepositoryTest : BaseDatabaseFactoryTest + { + [Test] + public void Can_Delete() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + + var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry); + unitOfWork.Commit(); + + repo.Delete(entry); + unitOfWork.Commit(); + + entry = repo.Get(entry.Key); + Assert.IsNull(entry); + } + } + + [Test] + public void Can_Add() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry); + unitOfWork.Commit(); + + var found = repo.GetAll().ToArray(); + + Assert.AreEqual(1, found.Count()); + Assert.AreEqual(content[0].Key, found[0].ProtectedNodeId); + Assert.AreEqual(content[1].Key, found[0].LoginNodeId); + Assert.AreEqual(content[2].Key, found[0].NoAccessNodeId); + Assert.IsTrue(found[0].HasIdentity); + Assert.AreNotEqual(default(DateTime), found[0].CreateDate); + Assert.AreNotEqual(default(DateTime), found[0].UpdateDate); + Assert.AreEqual(1, found[0].Rules.Count()); + Assert.AreEqual("test", found[0].Rules.First().Claim); + Assert.AreEqual("RoleName", found[0].Rules.First().ClaimType); + Assert.AreNotEqual(default(DateTime), found[0].Rules.First().CreateDate); + Assert.AreNotEqual(default(DateTime), found[0].Rules.First().UpdateDate); + Assert.IsTrue(found[0].Rules.First().HasIdentity); + } + } + + [Test] + public void Can_Update() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry); + unitOfWork.Commit(); + + //re-get + entry = repo.Get(entry.Key); + + entry.Rules.First().Claim = "blah"; + entry.Rules.First().ClaimType = "asdf"; + repo.AddOrUpdate(entry); + + unitOfWork.Commit(); + + //re-get + entry = repo.Get(entry.Key); + + Assert.AreEqual("blah", entry.Rules.First().Claim); + Assert.AreEqual("asdf", entry.Rules.First().ClaimType); + } + } + + [Test] + public void Get_By_Id() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + var entry = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry); + unitOfWork.Commit(); + + //re-get + entry = repo.Get(entry.Key); + + Assert.IsNotNull(entry); + } + } + + [Test] + public void Get_All() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + var entry1 = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry1); + + var entry2 = new PublicAccessEntry(content[1], content[0], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry2); + + unitOfWork.Commit(); + + var found = repo.GetAll().ToArray(); + Assert.AreEqual(2, found.Count()); + } + } + + + [Test] + public void Get_All_With_Node_Id() + { + var content = CreateTestData(3).ToArray(); + + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax)) + { + var entry1 = new PublicAccessEntry(content[0], content[1], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry1); + + var entry2 = new PublicAccessEntry(content[1], content[0], content[2], new[] + { + new PublicAccessRule + { + Claim = "test", + ClaimType = "RoleName" + }, + }); + repo.AddOrUpdate(entry2); + + unitOfWork.Commit(); + + var found = repo.GetAll(entry1.Key).ToArray(); + Assert.AreEqual(1, found.Count()); + } + } + + private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + { + var templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); + contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository); + var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository); + return repository; + } + + private IEnumerable CreateTestData(int count) + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository ctRepo; + using (var repo = CreateRepository(unitOfWork, out ctRepo)) + { + var ct = MockedContentTypes.CreateBasicContentType("testing"); + ctRepo.AddOrUpdate(ct); + unitOfWork.Commit(); + var result = new List(); + for (int i = 0; i < count; i++) + { + var c = new Content("test" + i, -1, ct); + repo.AddOrUpdate(c); + result.Add(c); + } + unitOfWork.Commit(); + + return result; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs index 1477f62e9f..4a755de581 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TaskRepositoryTest.cs @@ -96,6 +96,10 @@ namespace Umbraco.Tests.Persistence.Repositories task.Comment = "blah"; task.Closed = true; + unitOfWork.Commit(); + //re-get + task = repo.Get(task.Id); + Assert.AreEqual(true, task.Closed); Assert.AreEqual("blah", task.Comment); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 7d4fe26670..0600e0106d 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -176,6 +176,7 @@ + diff --git a/src/Umbraco.Web.UI/config/ClientDependency.config b/src/Umbraco.Web.UI/config/ClientDependency.config index 32b39b9d50..006dea76b0 100644 --- a/src/Umbraco.Web.UI/config/ClientDependency.config +++ b/src/Umbraco.Web.UI/config/ClientDependency.config @@ -10,7 +10,7 @@ NOTES: * Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config * A new version will invalidate both client and server cache and create new persisted files --> - +