private string GenerateOwnershipExpression(string currentUserIdentifier) { var sb = new StringBuilder(); if (HasCreatedByField || HasModifiedByField) { GetDirectOwnershipExpression(currentUserIdentifier, sb, null); } else { var related = LinkToOwershipType; if (related != null && related.Any()) { var aliases = new FieldEntityAliasDictionary(); sb.AppendLine("EXISTS"); sb.AppendLine("("); sb.AppendLine("\tSELECT TRUE"); sb.AppendLine($"\tFROM"); GenerateOwnershipJoinExpression(related, sb, aliases); sb.AppendLine("\tWHERE"); var lastLinkToOwnershipType = related.Last(); var relatedIdentity = lastLinkToOwnershipType.Type.Fields.Where(f => f.IsTrackingUser); GetRelatedOwnershipExpression(currentUserIdentifier, relatedIdentity, sb, (f) => aliases.GetAliasForLinkingField(lastLinkToOwnershipType)); sb.AppendLine("\tAND"); var linkOnCurrentType = related.First(); sb.AppendLine( $"\t{aliases.GetAliasForLinkingField(related.Skip(1).Take(1).Single())}.{Util.EscapeSqlReservedWord(linkOnCurrentType.ReferencesTypeField.Name)} = {Util.EscapeSqlReservedWord(linkOnCurrentType.Type.Name)}.{Util.EscapeSqlReservedWord(linkOnCurrentType.Name)}"); sb.AppendLine(")"); } else { sb.AppendLine("TODO"); // unknown relationship type } } return(sb.ToString()); }
protected void GenerateOwnershipJoinExpression(List <Field> related, StringBuilder sb, FieldEntityAliasDictionary aliases) { Field previous = null; string prevAlias = null; foreach (var field in related) { var alias = aliases.CreateAliasForTypeByField(field); if (previous == null) { sb.AppendLine($"\t{field.Type.Name} as {alias}"); } else { sb.AppendLine($"\tINNER JOIN {field.Type.Name} as {alias} on {prevAlias}.{previous.Name} = {alias}.{previous.ReferencesTypeField.Name}"); } prevAlias = alias; previous = field; } }
protected void GenerateOwnershipJoinExpression(List <Field> related, StringBuilder sb, FieldEntityAliasDictionary aliases) { Field previous = null; string prevAlias = null; // skip the first item when building the join expression for the security policy because the type we are building the policy for // will be automatically included as a set of items to filter, and explicitly including it in the policy causes an indefinitely recursive // security policy to be created (which doesn't work) foreach (var field in related.Skip(1)) { var alias = aliases.CreateAliasForTypeByField(field); if (previous == null) { sb.AppendLine($"\t{field.Type.Name} as {alias}"); } else { sb.AppendLine($"\tINNER JOIN {field.Type.Name} as {alias} on {prevAlias}.{previous.Name} = {alias}.{previous.ReferencesTypeField.Name}"); } prevAlias = alias; previous = field; } }