Skip to content

Commit

Permalink
[ODS-6045] Role-named fields in EdOrg Only and People Only authorizat…
Browse files Browse the repository at this point in the history
…ion strategies do not apply appropriate filters
  • Loading branch information
gmcelhanon authored and simpat-adam committed Feb 27, 2024
1 parent f91ddc4 commit bee28cd
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ public string[] GetConcreteNames()
/// <inheritdoc cref="IEducationOrganizationIdNamesProvider.IsEducationOrganizationIdName" />
public bool IsEducationOrganizationIdName(string candidateName)
{
return _sortedEducationOrganizationIdNames.Value.BinarySearch(candidateName) >= 0;
// First look for an exact match (no role name)
if (_sortedEducationOrganizationIdNames.Value.BinarySearch(candidateName) >= 0)
{
return true;
}

// Now check iteratively through known names as a matching suffix on the property name (allowing for a role name)
return _sortedEducationOrganizationIdNames.Value.Any(candidateName.EndsWith);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ public interface IEducationOrganizationIdNamesProvider
string[] GetConcreteNames();

/// <summary>
/// Indicates whether the supplied name is a known education organization id.
/// Indicates whether the supplied name is a known education organization id, allowing for the presence of role names.
/// </summary>
/// <param name="candidateName">The name to be evaluated.</param>
/// <returns><b>true</b> if the name matches a known education organization id; otherwise <b>false</b>.</returns>
/// <returns><b>true</b> if the name matches a known education organization id as a suffix; otherwise <b>false</b>.</returns>
bool IsEducationOrganizationIdName(string candidateName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public static class PersonEntitySpecification
Staff, Student, Parent
};

private static readonly string[] _suffixes = { UniqueIdSpecification.USI, UniqueIdSpecification.UniqueId };

/// <summary>
/// Indicates whether the specified <see cref="Type"/> represents a type of person.
/// </summary>
Expand All @@ -41,40 +43,43 @@ public static bool IsPersonEntity(string typeName)
return ValidPersonTypes.Contains(typeName, StringComparer.CurrentCultureIgnoreCase);
}

/// <summary>
/// Indicates whether the specified property name is an identifier for a person.
/// </summary>
/// <param name="propertyName">The name of the property to be evaluated.</param>
/// <returns><b>true</b> if the property is an identifier for a type of person; otherwise <b>false</b>.</returns>
public static bool IsPersonIdentifier(string propertyName)
{
return IsPersonIdentifier(propertyName, null);
}

/// <summary>
/// Indicates whether the specified property name is an identifier for the specified person type.
/// </summary>
/// <param name="propertyName">The name of the property to be evaluated.</param>
/// <param name="personType">A specific type of person.</param>
/// <param name="personType">A specific type of person; or <b>null</b> for any type.</param>
/// <returns><b>true</b> if the property is an identifier for the specified type of person; otherwise <b>false</b>.</returns>
public static bool IsPersonIdentifier(string propertyName, string personType)
public static bool IsPersonIdentifier(string propertyName, string personType = null)
{
if (personType != null && !ValidPersonTypes.Any(pt => pt.EqualsIgnoreCase(personType)))
{
throw new ArgumentException("'{0}' is not a supported person type.");
}

string entityName;

// TODO: Embedded convention (Person identifiers can end with "USI" or "UniqueId")
if (propertyName.TryTrimSuffix("UniqueId", out entityName)
|| propertyName.TryTrimSuffix("USI", out entityName))
return _suffixes.Any(
s => propertyName.EndsWith(s)
&& ValidPersonTypes.Any(
pt =>
// Person type was either not specified, or current person type matches what was specified
(personType == null || personType == pt)
&& PersonTypeAppearsImmediatelyBeforeSuffix(pt, s)));

bool PersonTypeAppearsImmediatelyBeforeSuffix(string pt, string suffix)
{
return IsPersonEntity(entityName)
&& (personType == null || entityName.EqualsIgnoreCase(personType));
}
int lastIndexOfPersonType = propertyName.LastIndexOf(pt, StringComparison.Ordinal);

if (lastIndexOfPersonType < 0)
{
// Person type is not in the property name
return false;
}

// Identify expected location of the person type in the property name
int expectedLastIndexOfPersonType = propertyName.Length - (pt.Length + suffix.Length);

return false;
return lastIndexOfPersonType == expectedLastIndexOfPersonType;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ namespace EdFi.Ods.Common.Specifications
{
public static class UniqueIdSpecification
{
private const string USI = "USI";
private const string UniqueId = "UniqueId";
public const string USI = "USI";
public const string UniqueId = "UniqueId";

public static string GetUniqueIdPersonType(string propertyName)
{
Expand Down

0 comments on commit bee28cd

Please sign in to comment.