From 15024fa5f81b7e627b564ee229edb19990411e1a Mon Sep 17 00:00:00 2001 From: Jafar Mirzaie Date: Fri, 22 Jul 2022 18:32:14 +0200 Subject: [PATCH] finish TypeConditions intersection --- .../Authorization/TypeAuthCache.cs | 20 ++++++----- .../Authorization/TypeAuthLogic.cs | 19 +++++++++-- .../Authorization/TypeConditionAlgebra.cs | 33 +++++++++++++++---- .../Authorization/ServicesData.cs | 14 ++++++-- .../Authorization/Admin/AuthAdmin.css | 4 +++ .../Admin/TypeRulePackControl.tsx | 4 +-- 6 files changed, 73 insertions(+), 21 deletions(-) diff --git a/Signum.Engine.Extensions/Authorization/TypeAuthCache.cs b/Signum.Engine.Extensions/Authorization/TypeAuthCache.cs index 344d23369b..b4ec1287b0 100644 --- a/Signum.Engine.Extensions/Authorization/TypeAuthCache.cs +++ b/Signum.Engine.Extensions/Authorization/TypeAuthCache.cs @@ -76,9 +76,13 @@ public TypeAuthCache(SchemaBuilder sb, IMerger m { TypeConditionSymbol condition = (TypeConditionSymbol)arg; - var command = Administrator.UnsafeDeletePreCommandMList((RuleTypeEntity rt)=>rt.Conditions, Database.MListQuery((RuleTypeEntity rt) => rt.Conditions).Where(mle => mle.Element.Conditions.Contains(condition))); + if (!Database.MListQuery((RuleTypeConditionEntity rt) => rt.Conditions).Any(mle => mle.Element.Is(condition))) + return null; - return command; + var mlist = Administrator.UnsafeDeletePreCommandMList((RuleTypeConditionEntity rt)=>rt.Conditions, Database.MListQuery((RuleTypeConditionEntity rt) => rt.Conditions).Where(mle => mle.Element.Is(condition))); + var emptyRules = Administrator.UnsafeDeletePreCommand(Database.Query().Where(rt => rt.Conditions.Count == 0), force: true, avoidMList: true); + + return SqlPreCommand.Combine(Spacing.Simple, mlist, emptyRules); } TypeAllowedAndConditions IManualAuth.GetAllowed(Lite role, Type key) @@ -327,7 +331,7 @@ orderby resource new XAttribute("Allowed", allowed.Fallback.ToString()!), from c in allowed.ConditionRules select new XElement("Condition", - new XAttribute("Name", c.ToString()), + new XAttribute("Name", c.TypeConditions.ToString(", ")), new XAttribute("Allowed", c.Allowed.ToString())) ) ) @@ -351,7 +355,7 @@ from c in allowed.ConditionRules TypeLogic.NameToType.Where(a => !a.Value.IsEnumEntity()).Select(a => a.Key).ToHashSet(), typeReplacementKey); replacements.AskForReplacements( - xRoles.SelectMany(x => x.Elements("Type")).SelectMany(t => t.Elements("Condition")).SelectMany(x => x.Attribute("Name")!.Value.Split(" & ").ToList()).ToHashSet(), + xRoles.SelectMany(x => x.Elements("Type")).SelectMany(t => t.Elements("Condition")).SelectMany(x => x.Attribute("Name")!.Value.SplitNoEmpty(",").Select(a=>a.Trim()).ToList()).ToHashSet(), SymbolLogic.AllUniqueKeys(), typeConditionReplacementKey); @@ -366,7 +370,7 @@ from c in allowed.ConditionRules }; - return Synchronizer.SynchronizeScript(Spacing.Double, should, current, + return Synchronizer.SynchronizeScript(Spacing.Triple, should, current, createNew: (role, x) => { var dic = (from xr in x.Elements("Type") @@ -397,7 +401,7 @@ from c in allowed.ConditionRules select KeyValuePair.Create(t, xr)).ToDictionaryEx("Type rules for {0}".FormatWith(role)); SqlPreCommand? restSql = Synchronizer.SynchronizeScript( - Spacing.Simple, + Spacing.Triple, dic, list.Where(a => a.Resource != null).ToDictionary(a => a.Resource), createNew: (r, xr) => @@ -432,8 +436,8 @@ private static MList Conditions(XElement xr, Replacemen var conditions = (from xc in xr.Elements("Condition") select new RuleTypeConditionEntity { - Conditions = xc.Attribute("Name")!.Value.Split(" & ") - .Select(s => SymbolLogic.TryToSymbol(replacements.Apply(typeConditionReplacementKey, s))).NotNull().ToMList(), + Conditions = xc.Attribute("Name")!.Value.SplitNoEmpty(",") + .Select(s => SymbolLogic.TryToSymbol(replacements.Apply(typeConditionReplacementKey, s.Trim()))).NotNull().ToMList(), Allowed = xc.Attribute("Allowed")!.Value.ToEnum() }).ToMList(); return conditions; diff --git a/Signum.Engine.Extensions/Authorization/TypeAuthLogic.cs b/Signum.Engine.Extensions/Authorization/TypeAuthLogic.cs index 91fa1ffb66..a8d0f6290b 100644 --- a/Signum.Engine.Extensions/Authorization/TypeAuthLogic.cs +++ b/Signum.Engine.Extensions/Authorization/TypeAuthLogic.cs @@ -277,6 +277,21 @@ public static TypeAllowedAndConditions MergeBase(IEnumerable conditionDictionary) + { + return conditionDictionary.ToString(kvp => ((kvp.Value & cell) == kvp.Value ? " " : "!") + kvp.Key.ToString().After("."), " & "); + } + + static string Debug(TypeAllowed[] matrix, Dictionary conditionDictionary) + { + return matrix.Select((ta, i) => Debug(i, conditionDictionary) + " => " + ta).ToString("\n"); + } + + static string Debug(TypeAllowed?[] matrix, Dictionary conditionDictionary) + { + return matrix.Select((ta, i) => Debug(i, conditionDictionary) + " => " + ta).ToString("\n"); + } + static TypeAllowed[] GetMatrix(TypeAllowedAndConditions tac, int numCells, Dictionary conditionDictionary) { var matrix = 0.To(numCells).Select(a => tac.Fallback).ToArray(); @@ -335,7 +350,7 @@ static TypeAllowedAndConditions GetRules(TypeAllowed[] matrix, int numCells, Dic } //>= 2 Conditions - for (int numConditions = 2; numConditions < availableTypeConditions.Count; numConditions++) + for (int numConditions = 2; numConditions <= availableTypeConditions.Count; numConditions++) { foreach (var mask in GetMasksOf(numConditions, availableTypeConditions)) { @@ -343,7 +358,7 @@ static TypeAllowedAndConditions GetRules(TypeAllowed[] matrix, int numCells, Dic if (ta.HasValue) { - conditionRules.Add(new TypeConditionRuleModel(availableTypeConditions.Where(tc => (conditionDictionary[tc] & mask) == mask).ToArray(), ta.Value)); + conditionRules.Add(new TypeConditionRuleModel(availableTypeConditions.Where(tc => (conditionDictionary[tc] & mask) == conditionDictionary[tc]).ToArray(), ta.Value)); ClearArray(mask); diff --git a/Signum.Engine.Extensions/Authorization/TypeConditionAlgebra.cs b/Signum.Engine.Extensions/Authorization/TypeConditionAlgebra.cs index c07ac1eec0..ae2de3043b 100644 --- a/Signum.Engine.Extensions/Authorization/TypeConditionAlgebra.cs +++ b/Signum.Engine.Extensions/Authorization/TypeConditionAlgebra.cs @@ -42,9 +42,20 @@ public override bool IsMoreSimpleAndGeneralThan(TypeConditionNode og) return false; } - public override string ToString() => Nodes.Count == 0 ? "TRUE" : $"AND({Nodes.ToString(", ")})"; + public override string ToString() => Nodes.Count == 0 ? "TRUE" : + Nodes.All(a => a is SymbolNode) ? $"AND({Nodes.ToString(", ")})" : + $"AND(\n{Nodes.ToString(",\n").Indent(3)}\n)"; - public override int GetHashCode() => Nodes.Sum(a => a.GetHashCode()) + 5; + public override int GetHashCode() { + + var hs = new HashCode(); + hs.Add(100); + foreach (var item in Nodes) + { + hs.Add(item); + } + return hs.ToHashCode(); + } public override bool Equals(object? obj) => obj is AndNode other && other.Nodes.ToHashSet().SetEquals(other.Nodes); @@ -63,10 +74,18 @@ public OrNode(IEnumerable nodes) public override bool IsMoreSimpleAndGeneralThan(TypeConditionNode og) => false; - public override string ToString() => Nodes.Count == 0 ? "FALSE" : $"OR({Nodes.ToString(a => " " + a + " ", ", ")})"; - - public override int GetHashCode() => Nodes.Sum(a => a.GetHashCode()); + public override string ToString() => Nodes.Count == 0 ? "FALSE" : $"OR(\n{Nodes.ToString(",\n").Indent(2)}\n)"; + public override int GetHashCode() + { + var hs = new HashCode(); + hs.Add(10); + foreach (var item in Nodes) + { + hs.Add(item); + } + return hs.ToHashCode(); + } public override bool Equals(object? obj) => obj is OrNode other && other.Nodes.ToHashSet().SetEquals(other.Nodes); } @@ -99,7 +118,7 @@ public SymbolNode(TypeConditionSymbol symbol) public override bool? ConstantValue => null; - public override bool IsMoreSimpleAndGeneralThan(TypeConditionNode og) => false; + public override bool IsMoreSimpleAndGeneralThan(TypeConditionNode og) => og is AndNode an && an.Nodes.Contains(this); public override string ToString() => Symbol.ToString(); @@ -187,7 +206,7 @@ public static Expression ToExpression(this TypeConditionNode node, Expression en return Expression.Negate(nn.ToExpression(entity)); if (node is AndNode and) - return and.Nodes.Select(n => n.ToExpression(entity)).Aggregate(Expression.Add); + return and.Nodes.Select(n => n.ToExpression(entity)).Aggregate(Expression.And); if (node is OrNode or) return or.Nodes.Select(n => n.ToExpression(entity)).Aggregate(Expression.Or); diff --git a/Signum.Entities.Extensions/Authorization/ServicesData.cs b/Signum.Entities.Extensions/Authorization/ServicesData.cs index 7a2b0c93af..59ee760045 100644 --- a/Signum.Entities.Extensions/Authorization/ServicesData.cs +++ b/Signum.Entities.Extensions/Authorization/ServicesData.cs @@ -265,7 +265,7 @@ internal bool Exactly(TypeAllowed current) public TypeAllowedAndConditions WithoutCondition(TypeConditionSymbol typeCondition) { - return new TypeAllowedAndConditions(this.Fallback, this.ConditionRules.Where(a => !a.TypeConditions.Contains(typeCondition))); + return new TypeAllowedAndConditions(this.Fallback, this.ConditionRules.Select(a => a.WithoutCondition(typeCondition)).NotNull().ToMList()); } } @@ -293,9 +293,19 @@ public bool Equals(TypeConditionRuleModel? other) Allowed.Equals(other.Allowed); } - [AutoExpressionField] public override string ToString() => As.Expression(() => TypeConditions.ToString(" & ") + " => " + Allowed); + + internal TypeConditionRuleModel? WithoutCondition(TypeConditionSymbol typeCondition) + { + if (!TypeConditions.Contains(typeCondition)) + return this; + + if (TypeConditions.Count == 1) + return null; + + return new TypeConditionRuleModel { TypeConditions = TypeConditions.Where(tc => !tc.Is(typeCondition)).ToMList() }; + } } public enum AuthThumbnail diff --git a/Signum.React.Extensions/Authorization/Admin/AuthAdmin.css b/Signum.React.Extensions/Authorization/Admin/AuthAdmin.css index d6d03379ab..f8a49fcb8a 100644 --- a/Signum.React.Extensions/Authorization/Admin/AuthAdmin.css +++ b/Signum.React.Extensions/Authorization/Admin/AuthAdmin.css @@ -53,6 +53,10 @@ color:#bbb } + .sf-auth-rules small.and { + color: #444 + } + a.sf-auth-chooser { text-decoration: none !important; diff --git a/Signum.React.Extensions/Authorization/Admin/TypeRulePackControl.tsx b/Signum.React.Extensions/Authorization/Admin/TypeRulePackControl.tsx index 555ec19011..52146fbd78 100644 --- a/Signum.React.Extensions/Authorization/Admin/TypeRulePackControl.tsx +++ b/Signum.React.Extensions/Authorization/Admin/TypeRulePackControl.tsx @@ -276,8 +276,8 @@ export default React.forwardRef(function TypesRulesPackControl({ ctx }: { ctx: T handleRemoveConditionClick(tctx.value.allowed, cr)}>   {cr.typeConditions.flatMap((tc, j) => [ - {getToString(tc.element)}, - j < cr.typeConditions.length - 1 ? & : null]) + {getToString(tc.element)}, + j < cr.typeConditions.length - 1 ? & : null]) .notNull()}