Modify the GUI of ABAC permissions to handle multivalued attributes

This commit is contained in:
Mikaël Ates 2011-08-25 20:03:01 +02:00
parent 495b3f9873
commit 3fd4f8013f
3 changed files with 486 additions and 146 deletions

View File

@ -254,8 +254,12 @@ class PredicateRequired(Predicate):
single_value = models.BooleanField(default=False)
def __unicode__(self):
if self.single_value:
return "Predicate required: %s - \
The attribute must be single-valued" % str(self.definition)
return "Predicate required: %s" % str(self.definition)
MULTIVALUES_OPTION = (
('NO_MULTIVALUES', _('Only accept single valued attributes')),
('EQUAL_ONE_VALUE', _('At least one value matches')),
@ -290,6 +294,7 @@ class PredicateComparison(Predicate):
choices = MULTIVALUES_OPTION,
verbose_name = 'How to handle multivalued attributes',
default = 'NO_MULTIVALUES')
multivalues_explanation = models.CharField(max_length = 500, blank=True)
def __unicode__(self):
operator = ''
@ -312,8 +317,12 @@ class PredicateComparison(Predicate):
if self.operand2_single_value:
s += 'operand two requires a single-valued attribute - '
if not self.operand1_single_value or not self.operand2_single_value:
s += 'multivalues management is %s - ' \
% self.multivalues
if not self.multivalues_explanation:
s += 'multivalues management is %s' \
% self.multivalues
else:
s += 'The multivalues management is as follows: %s' \
% self.multivalues_explanation
s += ')'
return s
@ -337,7 +346,8 @@ class AbacRule(models.Model):
Solution: make a first substitution with unique identifiers.
'''
for p in Predicate.objects.filter(rule=self):
rdm_str = ''.join(random.choice(string.ascii_uppercase) for x in range(8))
rdm_str = ''.join(\
random.choice(string.ascii_uppercase) for x in range(8))
predicates1[p.id] = rdm_str
predicates2[rdm_str] = str(p.get_predicate_instance())
for key in predicates1.keys():

View File

@ -168,6 +168,8 @@ def add_abac_permission(request):
request.POST['predicate_type']
request.session['working_predicate']['type_friendly'] = \
COMPARISON_TYPE_DIC[(request.POST['predicate_type'])]
request.session['working_predicate']['working_operand'] = {}
request.session['working_predicate']['working_operand']['type'] = 'definition'
return return_add_abac_permission_form(request)
if 'select_attribute_definition' in request.POST \
@ -191,6 +193,8 @@ def add_abac_permission(request):
= request.POST['attribute_definition_id']
working_predicate['definition_name'] \
= ad.attribute_name
if 'singlevalued' in request.POST:
working_predicate['singlevalued'] = 'singlevalued'
request.session['working_predicate'] = working_predicate
except:
messages.add_message(request, messages.ERROR,
@ -214,6 +218,11 @@ def add_abac_permission(request):
s = Source.objects.get(id=request.POST['source_id'])
working_predicate = request.session['working_predicate']
if 'sources_selected' in working_predicate:
if 'singlevalued' in working_predicate:
messages.add_message(request, messages.ERROR,
_('Attribute must be single-valued, a unique source can be provided, source %s has already be given') \
%working_predicate['sources_selected'][0][1])
return return_add_abac_permission_form(request)
if (s.id, s.name) in working_predicate['sources_selected']:
messages.add_message(request, messages.ERROR,
_('Source already added'))
@ -268,6 +277,115 @@ def add_abac_permission(request):
_('Predicate removed'))
return return_add_abac_permission_form(request)
if 'select_multivalue_step_one' in request.POST:
if not 'working_predicate' in request.session:
messages.add_message(request, messages.ERROR,
_('No working predicate'))
elif not 'type' in request.session['working_predicate']:
messages.add_message(request, messages.ERROR,
_('Missing predicate type'))
elif request.session['working_predicate']['type'] == \
PREDICATE_REQUIRED:
messages.add_message(request, messages.ERROR,
_('Working predicate is not a required attribute'))
else:
working_predicate = request.session['working_predicate']
request.session.pop('working_predicate')
working_predicate['multivalues_step_one'] = 'multivalues_step_one'
if 'operandone_singlevalued' in request.POST:
working_predicate['operandone_singlevalued'] = 'singlevalued'
if 'operandtwo_singlevalued' in request.POST:
working_predicate['operandtwo_singlevalued'] = 'singlevalued'
if 'operandone_singlevalued' in request.POST \
and 'operandtwo_singlevalued' in request.POST:
working_predicate['multivalues_step_two'] = 'NO_MULTIVALUES'
if ('operandone_singlevalued' in request.POST \
or 'operandtwo_singlevalued' in request.POST) \
and working_predicate['type'] \
in XACML_COMPARISON_EQUALITY:
working_predicate['multivalues_step_two'] = 'EQUAL_ONE_VALUE'
request.session['working_predicate'] = working_predicate
return return_add_abac_permission_form(request)
if 'select_multivalue_step_two' in request.POST \
and 'multivalues' in request.POST:
if not 'working_predicate' in request.session:
messages.add_message(request, messages.ERROR,
_('No working predicate'))
elif not 'type' in request.session['working_predicate']:
messages.add_message(request, messages.ERROR,
_('Missing predicate type'))
elif request.session['working_predicate']['type'] == \
PREDICATE_REQUIRED:
messages.add_message(request, messages.ERROR,
_('Working predicate is not a required attribute'))
elif not 'multivalues_step_one' in request.session['working_predicate']:
messages.add_message(request, messages.ERROR,
_('the first mutltivalue configuration step has not yet been completed'))
elif not request.POST['multivalues'] in \
('EQUAL_ONE_VALUE', 'EQUAL_OP1_SUBSET_OP2',
'EQUAL_EXACT_MATCH',
'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2',
'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2'):
messages.add_message(request, messages.ERROR,
_('Unknown multivalues treatment option'))
else:
working_predicate = request.session['working_predicate']
request.session.pop('working_predicate')
working_predicate['multivalues_step_two'] = \
request.POST['multivalues']
s = None
if working_predicate['type'] in ACS_XACML_COMPARISON_LT:
s = 'less than'
elif working_predicate['type'] in ACS_XACML_COMPARISON_LT_OE:
s = 'less than or equal to'
elif working_predicate['type'] in ACS_XACML_COMPARISON_GRT:
s = 'greater than'
elif working_predicate['type'] in ACS_XACML_COMPARISON_GRT_OE:
s = 'greater than or equal to'
if working_predicate['multivalues_step_two'] \
== 'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2':
working_predicate['multivalues_explanation'] = \
_('All values of operand one must be %s the highest value of operand two.') %s
elif working_predicate['multivalues_step_two'] \
== 'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2':
working_predicate['multivalues_explanation'] = \
_('All values of operand one must be %s the smallest value of operand two.') %s
elif working_predicate['multivalues_step_two'] \
== 'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2':
working_predicate['multivalues_explanation'] = \
_('At least one value of operand one must be %s the highest value of operand two.') %s
elif working_predicate['multivalues_step_two'] \
== 'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2':
working_predicate['multivalues_explanation'] = \
_('At least one value of operand one must be %s the smallest value of operand two.') %s
elif working_predicate['multivalues_step_two'] \
== 'EQUAL_OP1_SUBSET_OP2':
working_predicate['multivalues_explanation'] = \
_('The first attribute may have multiple values and each must be equal to a value of the second attribute (subset).')
elif working_predicate['multivalues_step_two'] \
== 'EQUAL_EXACT_MATCH':
working_predicate['multivalues_explanation'] = \
_('The first attribute may have multiple values that exactly match the values of the second attribute.')
elif working_predicate['multivalues_step_two'] \
== 'EQUAL_ONE_VALUE':
if 'operandtwo_singlevalued' in working_predicate \
or 'operandtwo_singlevalued' in working_predicate:
working_predicate['multivalues_explanation'] = \
_('One of the two operand might be multivalued, then the comparison will search that at least one value of multi values is equal to the value of the other attribute.')
elif not 'operandtwo_singlevalued' in working_predicate \
and not 'operandtwo_singlevalued' in working_predicate:
working_predicate['multivalues_explanation'] = \
_('The first attribute may have multiple values and at least one must be equal to a value of the second attribute.')
request.session['working_predicate'] = working_predicate
return return_add_abac_permission_form(request)
if 'operand_is_definition' in request.POST \
or 'operand_is_definition_data' in request.POST:
if not 'working_predicate' in request.session:
@ -295,6 +413,9 @@ def add_abac_permission(request):
working_predicate['working_operand']['type'] = 'definition'
else:
working_predicate['working_operand']['type'] = 'value'
# Definition type is the same as operand one
working_predicate['working_operand']['definition_name'] = working_predicate['operand1_defined']['definition_name']
working_predicate['working_operand']['definition_id'] = working_predicate['operand1_defined']['definition_id']
request.session['working_predicate'] = working_predicate
return return_add_abac_permission_form(request)
@ -321,6 +442,10 @@ def add_abac_permission(request):
else:
try:
ad = AttributeDefinition.objects.get(id=request.POST['attribute_definition_id'])
if ad.attribute_type != ACS_COMP_TYPE[request.session['working_predicate']['type']]:
messages.add_message(request, messages.ERROR,
_('The attribute type does not match the comparison type'))
return return_add_abac_permission_form(request)
working_predicate = request.session['working_predicate']
request.session.pop('working_predicate')
working_predicate['working_operand']['definition_id'] \
@ -328,9 +453,9 @@ def add_abac_permission(request):
working_predicate['working_operand']['definition_name'] \
= ad.attribute_name
request.session['working_predicate'] = working_predicate
except:
except Exception, e:
messages.add_message(request, messages.ERROR,
_('Attribute definition not found'))
_('Attribute definition not found (%s)') %str(e))
return return_add_abac_permission_form(request)
if 'select_source_operand' in request.POST \
@ -362,6 +487,16 @@ def add_abac_permission(request):
s = Source.objects.get(id=request.POST['source_operand_id'])
working_predicate = request.session['working_predicate']
if 'sources_selected' in working_predicate['working_operand']:
if not 'operand1_defined' in request.session['working_predicate'] and 'operandone_singlevalued' in working_predicate:
messages.add_message(request, messages.ERROR,
_('Operand one is single-valued, a unique source can be provided, source %s has already be given') \
% working_predicate['working_operand']['sources_selected'][0][1])
return return_add_abac_permission_form(request)
if 'operand1_defined' in request.session['working_predicate'] and 'operandtwo_singlevalued' in working_predicate:
messages.add_message(request, messages.ERROR,
_('Operand two is single-valued, a unique source can be provided, source %s has already be given') \
% working_predicate['working_operand']['sources_selected'][0][1])
return return_add_abac_permission_form(request)
if (s.id, s.name) in working_predicate['working_operand']['sources_selected']:
messages.add_message(request, messages.ERROR,
_('Source already added'))
@ -404,6 +539,11 @@ def add_abac_permission(request):
try:
working_predicate = request.session['working_predicate']
if 'values_selected' in working_predicate['working_operand']:
if 'operandtwo_singlevalued' in working_predicate:
messages.add_message(request, messages.ERROR,
_('Operand two is single-valued, value %s has already be given') \
%working_predicate['working_operand']['values_selected'][0])
return return_add_abac_permission_form(request)
if request.POST['value_operand'] in working_predicate['working_operand']['values_selected']:
messages.add_message(request, messages.ERROR,
_('Value already added'))
@ -516,8 +656,9 @@ def add_abac_permission(request):
policy = get_policy_from_session(request)
return HttpResponseRedirect('mod_policy?id=' + str(policy.id))
messages.add_message(request, messages.ERROR,
_('Unknown action'))
messages.add_message(request, messages.ERROR,
_('Unknown action'))
return return_add_abac_permission_form(request)
@ -563,8 +704,29 @@ def check_data_and_create_permission(request, what, how):
AttachedSource(assertion=ad, source=ss).save()
except:
raise Exception('Unable to attach source %s to predicate %s' % (ss, str(p_id)))
pred = PredicateRequired(definition=ad, rule=rule)
single_value = False
if 'singlevalued' in predicate:
single_value = True
pred = PredicateRequired(definition=ad, rule=rule, single_value=single_value)
else:
if not 'multivalues_step_two' in predicate \
or not 'multivalues_explanation' in predicate \
or not predicate['multivalues_step_two'] in \
('NO_MULTIVALUES',
'EQUAL_ONE_VALUE',
'EQUAL_OP1_SUBSET_OP2',
'EQUAL_EXACT_MATCH',
'DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2',
'DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2',
'DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2'):
raise Exception('Missing suitable option for multivalues treatment')
if 'operandone_singlevalued' in predicate \
and 'operandtwo_singlevalued' in predicate \
and predicate['multivalues_step_two'] != 'NO_MULTIVALUES':
raise Exception('Unacceptable option for multivalues treatment')
if not 'operand1_defined' in predicate:
raise Exception('Missing operand1 for predicate %s' %str(p_id))
if not 'type' in predicate['operand1_defined']:
@ -592,8 +754,20 @@ def check_data_and_create_permission(request, what, how):
a1 = handle_operand(predicate, p_id, 'operand1', d1)
a2 = handle_operand(predicate, p_id, 'operand2', d2)
operand1_single_value = False
if 'operandone_singlevalued' in predicate:
operand1_single_value = True
operand2_single_value = False
if 'operandtwo_singlevalued' in predicate:
operand2_single_value = True
pred = PredicateComparison(operand1=a1, operand2=a2,
comparison_type=predicate['type'], rule=rule)
operand1_single_value=operand1_single_value,
operand2_single_value=operand2_single_value,
comparison_type=predicate['type'],
multivalues=predicate['multivalues_step_two'],
multivalues_explanation=predicate['multivalues_explanation'],
rule=rule)
pred.save()
rdm_str = ''.join(random.choice(string.ascii_uppercase) for x in range(8))
@ -739,6 +913,8 @@ def handle_operand(predicate, p_id, name, d):
raise Exception('Unable to create assertion of %s of predicate %s' % (name, str(p_id)))
return a
#Previouslu define choices of multival according to the working pred
@check_policy_in_session
@check_authorized_for_abac
def return_add_abac_permission_form(request, template_name='add_abac_permission.html'):
@ -746,9 +922,46 @@ def return_add_abac_permission_form(request, template_name='add_abac_permission.
policy = get_policy_from_session(request)
tpl_p['multivalues'] = []
if 'working_predicate' in request.session \
and 'type' in request.session['working_predicate']:
if 'multivalues_step_one' in request.session['working_predicate'] \
and request.session['working_predicate']['type'] \
in XACML_COMPARISON_EQUALITY \
and (not 'operandtwo_singlevalued' in request.session['working_predicate'] \
and not 'operandtwo_singlevalued' in request.session['working_predicate']) \
and not 'multivalues_step_two' in request.session['working_predicate']:
tpl_p['multivalues'].append(('EQUAL_ONE_VALUE', _('The first attribute may have multiple values and at least one must be equal to a value of the second attribute')))
tpl_p['multivalues'].append(('EQUAL_OP1_SUBSET_OP2', _('The first attribute may have multiple values and each must be equal to a value of the second attribute (subset)')))
tpl_p['multivalues'].append(('EQUAL_EXACT_MATCH', _('The first attribute may have multiple values that exactly match the values of the second attribute')))
if 'multivalues_step_one' in request.session['working_predicate'] \
and request.session['working_predicate']['type'] \
in ACS_XACML_COMPARISON \
and not 'multivalues_step_two' in request.session['working_predicate']:
s = None
if request.session['working_predicate']['type'] in ACS_XACML_COMPARISON_LT:
s = 'less than'
if request.session['working_predicate']['type'] in ACS_XACML_COMPARISON_LT_OE:
s = 'less than or equal to'
if request.session['working_predicate']['type'] in ACS_XACML_COMPARISON_GRT:
s = 'greater than'
if request.session['working_predicate']['type'] in ACS_XACML_COMPARISON_GRT_OE:
s = 'greater than or equal to'
tpl_p['multivalues'].append(('DIFF_ALL_OP1_WITH_UPPER_LIMIT_OP2', _('All values of operand one must be %s the highest value of operand two') %s))
tpl_p['multivalues'].append(('DIFF_ALL_OP1_WITH_BOTTOM_LIMIT_OP2', _('All values of operand one must be %s the smallest value of operand two') %s))
tpl_p['multivalues'].append(('DIFF_ONE_OP1_WITH_UPPER_LIMIT_OP2', _('At least one value of operand one must be %s the highest value of operand two') %s))
tpl_p['multivalues'].append(('DIFF_ONE_OP1_WITH_BOTTOM_LIMIT_OP2', _('At least one value of operand one must be %s the smallest value of operand two') %s))
if 'working_predicate' in request.session:
tpl_p['working_predicate'] = request.session['working_predicate']
tpl_p['attribute_definitions'] = get_all_attribute_definitions()
if request.session['working_predicate']['type'] == \
PREDICATE_REQUIRED:
tpl_p['attribute_definitions'] = get_all_attribute_definitions()
else:
tpl_p['attribute_definitions'] = \
AttributeDefinition.objects.filter(attribute_type=ACS_COMP_TYPE[request.session['working_predicate']['type']])
tpl_p['sources'] = get_all_sources()
else:

View File

@ -29,13 +29,17 @@
{% if working_predicate.type == "urn:entrouvert:acs:constants:predicate-required" %}
{% if working_predicate.definition_name %}
<p>{% trans "The working predicate is" %} <strong>{{ working_predicate.definition_name }} {% trans "is required" %}</strong>.</p>
<p>
{% trans "The working predicate is" %} <strong>{{ working_predicate.definition_name }} {% trans "is required" %}</strong>.
{% if working_predicate.singlevalued %}{% trans "The attribute must be single-valued." %}{% endif %}
</p>
{% else %}
<p>{% trans "The working predicate is of type" %} <strong>{% trans "predicate required" %}</strong>.</p>
{% endif %}
{% if working_predicate.definition_name %}
{% if working_predicate.singlevalued and not working_predicate.sources_selected or not working_predicate.singlevalued%}
<p>{% trans "Add a source:" %}
<form method="post" action="">
<select name="source_id" id="source">
@ -46,6 +50,7 @@
<input type="submit" name="select_source" value="{% trans "Add" %}"/>
</form>
</p>
{% endif %}
{% if working_predicate.sources_selected %}
<p>{% trans "Source already defined:" %}
@ -64,152 +69,249 @@
{% else %}
<form method="post" action="">
<p>{% trans "Choose an attribute definition:" %}
<form method="post" action="">
<select name="attribute_definition_id" id="attribute_definition">
{% for attr_definition in attribute_definitions %}
<option value="{{ attr_definition.id }}">{{ attr_definition.attribute_name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_attribute_definition" value="{% trans "Ok" %}"/>
</form>
</p>
<p>
{% trans "You can indicate that an attribute might be provided by one source among many, it is a or statement. Then, you can't enforce that an attribute be provided by a unique source among multiple. You can not also enforce singlevalued attributes if you want to let the choice in the source. Then, if you want that an attribute be single-valued, you will only be authorized to select one source. If you want single-valued attribute but let the choice in the source, you have to declare multiple predicate." %}
</p>
<p>
<label>{% trans "Check the following box if you want to require that the attribute provided be single-valued." %}</label>
<input type="checkbox" name="singlevalued" value="singlevalued"/>
</p>
<p>
<input type="submit" name="select_attribute_definition" value="{% trans "Ok" %}"/>
</p>
</form>
{% endif %}
{% else %}
<p>{% trans "The working predicate is of type" %} <strong>{{ working_predicate.type_friendly }}</strong>.</p>
{% if working_predicate.operand1_defined %}
{% if not working_predicate.multivalues_step_one %}
<form method="post" action="">
<p>
{% trans "Operand one is a" %} <strong>{{ working_predicate.operand1_defined.type }}</strong>
{% trans "on attribute" %} <strong>{{ working_predicate.operand1_defined.definition_name }}</strong>
{% if working_predicate.operand1_defined.type == "definition" %}
{% trans "expected from" %}(
{% for s_id, s_name in working_predicate.operand1_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})
{% trans "The predicate have two operands. The first one indicate an attribute expected from a source. The second one might be one or multiple values, or an a different attribute from the same source, or another attribute issued from a different source." %}
</p>
<p>
{% trans "You can indicate that an attribute might be provided by one source among many, it is a or statement. Then, you can't enforce that an attribute be provided by a unique source among multiple. You can not also enforce singlevalued attributes if you want to let the choice in the source. Then, if you want that an attribute be single-valued, you will only be authorized to select one source. If you want single-valued attribute but let the choice in the source, you have to declare multiple predicate." %}
</p>
<p>
{% trans "If you authorize that an attribute be multivalued or you to let the choice in sources, you will be prompt to choose how multivalues must be handled." %}
</p>
<p>
{% trans "By checking the following box you indicate that the operand one must be single-valued." %}
<input type="checkbox" name="operandone_singlevalued" value="singlevalued"/>
</p>
<p>
{% trans "By checking the following box you indicate that the opernad two must be single-valued or that you wish indicate a unique value of comparison." %}
<input type="checkbox" name="operandtwo_singlevalued" value="singlevalued"/>
</p>
<input type="submit" name="select_multivalue_step_one" value="{% trans "Ok" %}"/>
</form>
{% else %}
<p>
{% if working_predicate.operandone_singlevalued %}
{% trans "Operand one must be single-valued." %}
{% else %}
{% trans "with values" %}(
{% for value in working_predicate.operand1_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})
{% trans "Operand one may be multivalued." %}
{% endif %}
{% if working_predicate.operandtwo_singlevalued %}
{% trans "Operand two must be single-valued." %}
{% else %}
{% trans "Operand two may be multivalued." %}
{% endif %}
</p>
{% endif %}
{% if working_predicate.operand2_defined %}
<p>
{% trans "Operand two is a" %} <strong>{{ working_predicate.operand2_defined.type }}</strong>
{% trans "on attribute" %} <strong>{{ working_predicate.operand2_defined.definition_name }}</strong>
{% if working_predicate.operand2_defined.type == "definition" %}
{% trans "expected from" %}(
{% for s_id, s_name in working_predicate.operand2_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})
{% else %}
{% trans "with values" %}(
{% for value in working_predicate.operand2_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})
{% endif %}
</p>
{% endif %}
{% if not working_predicate.operand1_defined or not working_predicate.operand2_defined %}
{% if not working_predicate.working_operand %}
{% if not working_predicate.operand1_defined %}
<p>{% trans "Choose operand 1 type:" %}
{% else %}
<p>{% trans "Choose operand 2 type:" %}
{% endif %}
{% if not working_predicate.multivalues_step_two %}
<p>{% trans "Choose how multivalued attribued are compared:" %}
<form method="post" action="">
<input type="submit" name="operand_is_definition" value="{% trans "Attribute" %}"/>
<input type="submit" name="operand_is_definition_data" value="{% trans "Attribute value" %}"/>
<select name="multivalues" id="multivalues">
{% for multivalue, f_multivalue in multivalues %}
<option value="{{ multivalue }}">{{ f_multivalue }}</option>
{% endfor %}
</select>
<input type="submit" name="select_multivalue_step_two" value="{% trans "Ok" %}"/>
</form>
</p>
</p>
{% else %}
<p>{% trans "The operand definition in progress is a" %} <strong>{{ working_predicate.working_operand.type }}</strong></p>
{% if not working_predicate.working_operand.definition_name %}
<p>{% trans "Choose an attribute definition:" %}
<form method="post" action="">
<select name="attribute_definition_id" id="attribute_definition">
{% for attr_definition in attribute_definitions %}
<option value="{{ attr_definition.id }}">{{ attr_definition.attribute_name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_attribute_definition_operand" value="{% trans "Ok" %}"/>
</form>
</p>
{% else %}
<p>{% trans "On attribute" %} <strong>{{ working_predicate.working_operand.definition_name }}</strong></p>
{% if working_predicate.working_operand.type == "definition" %}
<p>{% trans "Add a source:" %}
<form method="post" action="">
<select name="source_operand_id" id="source">
{% for source in sources %}
<option value="{{ source.id }}">{{ source.name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_source_operand" value="{% trans "Add" %}"/>
</form>
</p>
{% if working_predicate.working_operand.sources_selected %}
<p>{% trans "Source already defined:" %}
<ul>
{% for s_id, s_name in working_predicate.working_operand.sources_selected %}
<li><strong>{{ s_name }}</strong></option>
{% endfor %}
</ul>
</p>
<p>
<form method="post" action="">
<input type="submit" name="close_working_operand" value="{% trans "Finish operand" %}"/>
</form>
</p>
{% endif %}
<p>{{ working_predicate.multivalues_explanation }}</p>
{% if working_predicate.operand1_defined %}
<p>{% trans "Operand one is attribute" %} <strong>{{ working_predicate.operand1_defined.definition_name }}</strong>
{% if working_predicate.operand1_defined.type == "definition" %}
{% trans " from" %}(
{% for s_id, s_name in working_predicate.operand1_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})<p/>
{% else %}
<p>{% trans "Add a value:" %}
<form method="post" action="">
<input type="text" name="value_operand" label="{% trans "Give a value to test" %}"/>
<input type="submit" name="value_operand_submitted" value="{% trans "Add" %}"/>
</form>
</p>
{% if working_predicate.working_operand.values_selected %}
<p>{% trans "Values already given:" %}
<ul>
{% for v_value in working_predicate.working_operand.values_selected %}
<li><strong>{{ v_value }}</strong></option>
{% endfor %}
</ul>
</p>
<p>
<form method="post" action="">
<input type="submit" name="close_working_operand" value="{% trans "Finish operand" %}"/>
</form>
</p>
{% endif %}
{% trans "of values" %}(
{% for value in working_predicate.operand1_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})<p/>
{% endif %}
{% endif %}
<p>
<br style="clear: both;"/>
<form method="post" action="">
<input type="submit" name="delete_working_operand" value="{% trans "Cancel operand" %}"/>
</form>
<p>
{% if working_predicate.operand2_defined %}
{% if working_predicate.operand2_defined.type == "definition" %}
<p>{% trans "Operand two is attribute" %} <strong>{{ working_predicate.operand2_defined.definition_name }}</strong>
{% trans " from" %}(
{% for s_id, s_name in working_predicate.operand2_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})<p/>
{% else %}
<p>{% trans "Compared with values" %}(
{% for value in working_predicate.operand2_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})<p/>
{% endif %}
{% endif %}
{% if not working_predicate.operand1_defined or not working_predicate.operand2_defined %}
{% if not working_predicate.working_operand %}
<form method="post" action="">
<p>{% trans "Compared with" %}:</p>
<ul>
<li>
<p>{% trans "the same attribute from another source or a different attribute" %}</p>
<input type="submit" name="operand_is_definition" value="{% trans "Attribute" %}"/>
</li>
<li>
<p>{% trans "with one or multiple values" %}</p>
<input type="submit" name="operand_is_definition_data" value="{% trans "Value" %}"/>
</li>
</ul>
</form>
</p>
{% else %}
{% if not working_predicate.working_operand.definition_name %}
{% if not working_predicate.operand1_defined %}
<p>{% trans "Choose an attribute as operand one of the comparison:" %}
{% else %}
<p>{% trans "Choose an attribute as operand two of the comparison:" %}
{% endif %}
<form method="post" action="">
<select name="attribute_definition_id" id="attribute_definition">
{% for attr_definition in attribute_definitions %}
<option value="{{ attr_definition.id }}">{{ attr_definition.attribute_name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_attribute_definition_operand" value="{% trans "Ok" %}"/>
</form>
</p>
{% else %}
{% if working_predicate.working_operand.type == "definition" %}
{% if not working_predicate.operand1_defined %}
<p>{% trans "Operand one is the attribute" %} <strong>{{ working_predicate.working_operand.definition_name }}</strong></p>
{% if working_predicate.operandone_singlevalued and not working_predicate.working_operand.sources_selected or not working_predicate.operandone_singlevalued%}
<p>{% trans "From:" %}
<form method="post" action="">
<select name="source_operand_id" id="source">
{% for source in sources %}
<option value="{{ source.id }}">{{ source.name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_source_operand" value="{% trans "Add" %}"/>
</form>
</p>
{% endif %}
{% else %}
<p>{% trans "Operand two is the attribute" %} <strong>{{ working_predicate.working_operand.definition_name }}</strong></p>
{% if working_predicate.operandtwo_singlevalued and not working_predicate.working_operand.sources_selected or not working_predicate.operandtwo_singlevalued%}
<p>{% trans "From:" %}
<form method="post" action="">
<select name="source_operand_id" id="source">
{% for source in sources %}
<option value="{{ source.id }}">{{ source.name }}</option>
{% endfor %}
</select>
<input type="submit" name="select_source_operand" value="{% trans "Add" %}"/>
</form>
</p>
{% endif %}
{% endif %}
{% if working_predicate.working_operand.sources_selected %}
<p>{% trans "Sources already defined:" %}
<ul>
{% for s_id, s_name in working_predicate.working_operand.sources_selected %}
<li><strong>{{ s_name }}</strong></option>
{% endfor %}
</ul>
</p>
<p>
<form method="post" action="">
<input type="submit" name="close_working_operand" value="{% trans "Finish operand" %}"/>
</form>
</p>
{% endif %}
{% else %}
<p>{% trans "Compared with..." %}</p>
{% if not working_predicate.operand1_defined %}
{% if working_predicate.operandone_singlevalued and not working_predicate.working_operand.values_selected or not working_predicate.operandone_singlevalued%}
<p>{% trans "Add a value:" %}
<form method="post" action="">
<input type="text" name="value_operand" label="{% trans "Give a value to test" %}"/>
<input type="submit" name="value_operand_submitted" value="{% trans "Add" %}"/>
</form>
</p>
{% endif %}
{% else %}
{% if working_predicate.operandtwo_singlevalued and not working_predicate.working_operand.values_selected or not working_predicate.operandtwo_singlevalued%}
<p>{% trans "Add a value:" %}
<form method="post" action="">
<input type="text" name="value_operand" label="{% trans "Give a value to test" %}"/>
<input type="submit" name="value_operand_submitted" value="{% trans "Add" %}"/>
</form>
</p>
{% endif %}
{% endif %}
{% if working_predicate.working_operand.values_selected %}
<p>{% trans "Values already defined:" %}
<ul>
{% for v_value in working_predicate.working_operand.values_selected %}
<li><strong>{{ v_value }}</strong></option>
{% endfor %}
</ul>
</p>
<p>
<form method="post" action="">
<input type="submit" name="close_working_operand" value="{% trans "Finish operand" %}"/>
</form>
</p>
{% endif %}
{% endif %}
{% endif %}
<!--<p>
<br style="clear: both;"/>
<form method="post" action="">
<input type="submit" name="delete_working_operand" value="{% trans "Cancel operand" %}"/>
</form>
<p>-->
{% endif %}
{% else %}
<p>
<form method="post" action="">
<input type="submit" name="close_working_predicate" value="{% trans "Finish predicate" %}"/>
</form>
</p>
{% endif %}
{% endif %}
{% else %}
<p>
<form method="post" action="">
<input type="submit" name="close_working_predicate" value="{% trans "Finish predicate" %}"/>
</form>
</p>
{% endif %}
{% endif %}
@ -231,38 +333,53 @@
<li>{% trans "Predicate identifier:" %} <strong>{{ p_id }}</strong></li>
<li>
{% if predicate.type == "urn:entrouvert:acs:constants:predicate-required" %}
{% trans "The predicate is " %} <strong>{% trans "attribute" %} {{ predicate.definition_name }} {% trans "is required" %}</strong>
{% trans "and is expected from" %}(
{% trans "The predicate is " %} <strong>{% trans "attribute" %} {{ predicate.definition_name }} {% trans "is required." %}</strong>
{% if predicate.singlevalued %}{% trans "The attribute must be single-valued." %}{% endif %}
{% trans "It is expected from" %}(
{% for s_id, s_name in predicate.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})
{% else %}
{% trans "The predicate is of type" %} <strong>{{ predicate.type_friendly }}</strong>
{% trans "Operand one is a" %} <strong>{{ predicate.operand1_defined.type }}</strong>
{% trans "on attribute" %} <strong>{{ predicate.operand1_defined.definition_name }}</strong>
<p><strong>{{ predicate.type_friendly }}</strong><p/>
<p>
{% if predicate.operandone_singlevalued %}
{% trans "Operand one must be single-valued." %}
{% else %}
{% trans "Operand one may be multivalued." %}
{% endif %}
{% if predicate.operandtwo_singlevalued %}
{% trans "Operand two must be single-valued." %}
{% else %}
{% trans "Operand two may be multivalued." %}
{% endif %}
</p>
<p>{{ predicate.multivalues_explanation }}</p>
<p>{% trans "Operand one is attribute" %} <strong>{{ predicate.operand1_defined.definition_name }}</strong>
{% if predicate.operand1_defined.type == "definition" %}
{% trans "expected from" %}(
{% trans " from" %}(
{% for s_id, s_name in predicate.operand1_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})
{% endfor %})<p/>
{% else %}
{% trans "with values" %}(
{% trans "of values" %}(
{% for value in predicate.operand1_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})
{% endfor %})<p/>
{% endif %}
{% trans "Operand two is a" %} <strong>{{ predicate.operand2_defined.type }}</strong>
{% trans "on attribute" %} <strong>{{ predicate.operand2_defined.definition_name }}</strong>
{% if predicate.operand2_defined.type == "definition" %}
{% trans "expected from" %}(
<p>{% trans "Operand two is attribute" %} <strong>{{ predicate.operand2_defined.definition_name }}</strong>
{% trans " from" %}(
{% for s_id, s_name in predicate.operand2_defined.sources_selected %}
<strong>{{ s_name }}</strong>,
{% endfor %})
{% endfor %})<p/>
{% else %}
{% trans "with values" %}(
<p>{% trans "Compared with values" %}(
{% for value in predicate.operand2_defined.values_selected %}
<strong>{{ value }}</strong>,
{% endfor %})
{% endfor %})<p/>
{% endif %}
{% endif %}
</li>
@ -348,7 +465,7 @@
<br style="clear: both;"/>
<form method="post" action="">
<input type="submit" name="cancel_all" value="{% trans "Cancel" %}"/>
<input type="submit" name="cancel_all" value="{% trans "Cancel Rule" %}"/>
</form>
</div>