Объединение логических выражений при определении приоритетов выражений
Я нахожусь в процессе создания сложного модуля авторизации для системы, который будет основан на шаблоне спецификации. Правила доступа определены следующим образом:
operationName
определяет, к какой операции применяется правило.SubjectSpecification
определяет, должно ли правило применяться к конкретномуSubject
или нет. Например, следующее будет соответствовать любому предмету в подразделении А.subjectSpec = new MyAppSubjectSpecification(division: Division.SOME_DIVISION)
AccessSpecification
определяет фактическое выражение правила.AccessType
определяет, разрешает ли соответствие правило или запрещает доступ.RulePriorityStrategy
это определяет, как правила должны быть унаследованы.
На вопрос, скажем, что наше приложение Subject
имеет следующую структуру {divisionId, sectionId, groupId, userId }
и что RulePriority
утверждает, что чем конкретнее SubjectSpecification
тем выше его приоритет.
Например, правило, ориентированное на конкретный userId
будет иметь приоритет над правилом, ориентированным на division
к которому принадлежит этот пользователь.
Теперь вот настоящая проблема, которую я пока не знаю, как ее решить. Я хочу, чтобы правила наследовались таким образом, чтобы правила с высоким приоритетом наследовались от правил с самым низким приоритетом, а их собственные условия переопределяли части правил с самым низким приоритетом, которые конфликтуют. Также обратите внимание, что операции запрещены по умолчанию, если не существует соответствующего правила предоставления.
Например, со следующими правилами:
- Grant OperationA to all where (A && B) || C
- Grant OperationA to division A where D
- Deny Operation to user xyz where B && E
Здесь я ожидаю, что пользователь xyz (который принадлежит к разделу A) будет разрешен, когда C || D || (A && B && !E)
,
То, как я планировал использовать финал по наследству grant
а также allow
Правила таковы:
canPerformOperation = grantSpec.isSatisfiedBy(...) and not (denySpec.isSatisfiedBy(...))
В этом случае кажется, что комбинирование следующим образом будет работать, но это не во всех сценариях (например, когда allow должен переопределять отказ).
GR = Grant rule
DN = Deny rule
allowed = (GRn || GRn+1 ... || GRn+x)) && !(DRn || DRn+1 ... || DRn+x)
allowed = ((A && B) || C) || D) && !(B && E)
Я провел небольшое исследование, и я уверен, что это стандартное академическое знание логических выражений, но я не смог найти стандартный алгоритм, который каким-то образом решит проблему, и я уверен, что решение придет ко мне достаточно много времени или не будет эффективным.