Skip to content

Commit

Permalink
Implement Relationship DataSources respect draft permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
iJungleboy committed Jul 4, 2024
1 parent 41457b7 commit 121faaf
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 43 deletions.
5 changes: 3 additions & 2 deletions ToSic.Eav.DataSources/DataSources/Relationships/Children.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ToSic.Eav.DataSources.Internal;
using ToSic.Eav.Context;
using ToSic.Eav.DataSources.Internal;
using static ToSic.Eav.DataSource.Internal.DataSourceConstants;

namespace ToSic.Eav.DataSources;
Expand All @@ -22,7 +23,7 @@ namespace ToSic.Eav.DataSources;
HelpLink = "https://go.2sxc.org/DsChildren")]
[InternalApi_DoNotUse_MayChangeWithoutNotice("WIP")]

public class Children(DataSourceBase.MyServices services) : RelationshipDataSourceBase(services, $"{LogPrefix}.Child")
public class Children(DataSourceBase.MyServices services, IContextResolverUserPermissions userPermissions) : RelationshipDataSourceBase(services, userPermissions, $"{LogPrefix}.Child")
{
/// <summary>
/// Name of the field pointing to the children.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
namespace ToSic.Eav.DataSources.Internal;
using ToSic.Eav.Context;

namespace ToSic.Eav.DataSources.Internal;

/// <summary>
/// Base class for Children and Parents - since they share a lot of code
/// </summary>
public abstract class RelationshipDataSourceBase : Eav.DataSource.DataSourceBase
public abstract class RelationshipDataSourceBase : DataSourceBase
{
/// <summary>
/// These should be fully implemented in inheriting class, as the docs change from inheritance to inheritance
Expand All @@ -26,36 +28,47 @@ public abstract class RelationshipDataSourceBase : Eav.DataSource.DataSourceBase
/// <summary>
/// Constructor
/// </summary>
protected RelationshipDataSourceBase(MyServices services, string logName): base(services, logName)
protected RelationshipDataSourceBase(MyServices services, IContextResolverUserPermissions userPermissions, string logName): base(services, logName, connect: [userPermissions])
{
_userPermissions = userPermissions;
ProvideOut(GetRelated);
}

private readonly IContextResolverUserPermissions _userPermissions;

private IImmutableList<IEntity> GetRelated()
{
var l = Log.Fn<IImmutableList<IEntity>>();
Configuration.Parse();

// Make sure we have an In - otherwise error
var source = TryGetIn();
if (source is null) return l.ReturnAsError(Error.TryGetInFailed());
if (source is null)
return l.ReturnAsError(Error.TryGetInFailed());

var fieldName = FieldName;
if (string.IsNullOrWhiteSpace(fieldName)) fieldName = null;
Log.A($"Field Name: {fieldName}");
l.A($"Field Name: {fieldName}");

var typeName = ContentTypeName;
if (string.IsNullOrWhiteSpace(typeName)) typeName = null;
Log.A($"Content Type Name: {typeName}");
l.A($"Content Type Name: {typeName}");

var find = InnerGet(fieldName, typeName);

var relationships = source
.SelectMany(o => find(o));
.SelectMany(o => find(o))
.ToList();

// In case the current user should not see draft data,
// we must ensure that we didn't accidentally include any.
// Because it could be that the original data was public, but a related item was not.
if (!(_userPermissions.UserPermissions()?.ShowDraftData ?? false))
relationships = relationships.Where(e => e.IsPublished).ToList();

// ReSharper disable PossibleMultipleEnumeration
var result = (FilterDuplicates)
l.A($"{nameof(FilterDuplicates)}: {FilterDuplicates}");
var result = FilterDuplicates
? relationships.Distinct()
: relationships;

Expand Down
5 changes: 3 additions & 2 deletions ToSic.Eav.DataSources/DataSources/Relationships/Parents.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ToSic.Eav.DataSources.Internal;
using ToSic.Eav.Context;
using ToSic.Eav.DataSources.Internal;
using static ToSic.Eav.DataSource.Internal.DataSourceConstants;

namespace ToSic.Eav.DataSources;
Expand All @@ -21,7 +22,7 @@ namespace ToSic.Eav.DataSources;
ConfigurationType = "a72cb2f4-52bb-41e6-9281-10e69aeb0310",
HelpLink = "https://go.2sxc.org/DsParents")]
[InternalApi_DoNotUse_MayChangeWithoutNotice("WIP")]
public class Parents(DataSourceBase.MyServices services) : RelationshipDataSourceBase(services, $"{LogPrefix}.Parent")
public class Parents(DataSourceBase.MyServices services, IContextResolverUserPermissions userPermissions) : RelationshipDataSourceBase(services, userPermissions, $"{LogPrefix}.Parent")
{
/// <summary>
/// Name of the field (in the parent) pointing to the child.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using ToSic.Eav.DataSource.Internal.Errors;
using ToSic.Eav.DataSource.Streams;
using ToSic.Eav.DataSource.Streams.Internal;
using static ToSic.Eav.DataSource.Internal.DataSourceConstants;
using IEntity = ToSic.Eav.Data.IEntity;
Expand Down Expand Up @@ -260,56 +259,62 @@ private IImmutableList<IEntity> GetEntities()
/// <param name="internalCompare">internal compare method</param>
/// <param name="valuesToFind">value-list to compare to</param>
/// <returns></returns>
private ResultOrError<Func<IEntity, bool>> PickMode(string modeToPick, string relationship,
Func<IEntity, string, bool> internalCompare, string[] valuesToFind) => Log.Func(l =>
private ResultOrError<Func<IEntity, bool>> PickMode(string modeToPick, string relationship, Func<IEntity, string, bool> internalCompare, string[] valuesToFind)
{
var l = Log.Fn<ResultOrError<Func<IEntity, bool>>>();
switch (modeToPick)
{
case CompareModeContains:
if (valuesToFind.Length > 1)
return (new(true,
entity =>
return l.Return(new(true, entity =>
{
var rels = entity.Relationships.Children[relationship];
return valuesToFind.All(v => rels.Any(r => internalCompare(r, v)));
}), "contains all");
return (new(true,
entity => entity.Relationships.Children[relationship]
.Any(r => internalCompare(r, valuesToFind.FirstOrDefault() ?? ""))
), "contains one");
}),
"contains all");
return l.Return(new(true, entity => entity.Relationships.Children[relationship]
.Any(r => internalCompare(r, valuesToFind.FirstOrDefault() ?? ""))
),
"contains one");

case CompareModeContainsAny:
// Condition that of the needed relationships, at least one must exist
return (new(true, entity =>
{
var rels = entity.Relationships.Children[relationship];
return valuesToFind.Any(v => rels.Any(r => internalCompare(r, v)));
}), "will use contains any");
return l.Return(new(true, entity =>
{
var rels = entity.Relationships.Children[relationship];
return valuesToFind.Any(v => rels.Any(r => internalCompare(r, v)));
}),
"will use contains any");

case CompareModeAny:
return (new(true,
entity => entity.Relationships.Children[relationship].Any()), "will use any");
return l.Return(new(true,
entity => entity.Relationships.Children[relationship].Any()),
"will use any");

case CompareModeFirst:
// Condition that of the needed relationships, the first must be what we want
return (new(true, entity =>
{
var first = entity.Relationships.Children[relationship].FirstOrDefault();
return first != null && valuesToFind.Any(v => internalCompare(first, v));
}), "will use first is");
return l.Return(new(true, entity =>
{
var first = entity.Relationships.Children[relationship].FirstOrDefault();
return first != null && valuesToFind.Any(v => internalCompare(first, v));
}),
"will use first is");

case CompareModeCount:
// Count relationships
if (int.TryParse(valuesToFind.FirstOrDefault() ?? "0", out var count))
return (new(true,
entity => entity.Relationships.Children[relationship].Count() == count), "count");
return l.Return(new(true,
entity => entity.Relationships.Children[relationship].Count() == count),
"count");

return (new(true, _ => false), "count");
return l.Return(new(true, _ => false), "count");

default:
return (
new ResultOrError<Func<IEntity, bool>>(false, null,
Error.Create(source: this, title: "Mode unknown", message: $"The mode '{modeToPick}' is invalid")), "error, unknown compare mode");
//SetError("Mode unknown", $"The mode '{modeToPick}' is invalid");
//return (null, "error, unknown compare mode");
return l.Return(new(false, null, Error.Create(source: this, title: "Mode unknown",
message: $"The mode '{modeToPick}' is invalid")),
"error, unknown compare mode");
}
});
}



Expand Down

0 comments on commit 121faaf

Please sign in to comment.