Repository: privacyidea/privacyidea

Issue:
Add multiple choice for realms and resolvers in eventhandler
**Is your feature request related to a problem? Please describe.**

We use multi-choice for the token realm, token resolver and toke type, so we should use this here too. 

**Describe the solution you'd like**

We can change the type from str to multi for realm and resolver in evanthandler/base.py similar to tokenrealm

# Implementation

# TODOs

- [x] change the type of realm and resolver here: https://github.com/privacyidea/privacyidea/blob/0facb209610e6553cc1f420e1d65f454f85e3460/privacyidea/lib/eventhandler/base.py#L149
- [x] we have to change this: https://github.com/privacyidea/privacyidea/blob/0facb209610e6553cc1f420e1d65f454f85e3460/privacyidea/lib/eventhandler/base.py#L416
- [x] Test it
- [x] Check docu: https://github.com/privacyidea/privacyidea/blob/master/doc/eventhandler/index.rst#conditions



Discussion:

Resolving patch:
diff --git a/privacyidea/lib/eventhandler/base.py b/privacyidea/lib/eventhandler/base.py
--- a/privacyidea/lib/eventhandler/base.py
+++ b/privacyidea/lib/eventhandler/base.py
@@ -147,15 +147,15 @@ def conditions(cls):
                 "group": GROUP.TOKEN
             },
             CONDITION.REALM: {
-                "type": "str",
+                "type": "multi",
                 "desc": _("The realm of the user, for which this event should apply."),
-                "value": list(realms),
+                "value": [{"name": r} for r in realms],
                 "group": GROUP.USER
             },
             CONDITION.RESOLVER: {
-                "type": "str",
+                "type": "multi",
                 "desc": _("The resolver of the user, for which this event should apply."),
-                "value": list(resolvers),
+                "value": [{"name": r} for r in resolvers],
                 "group": GROUP.USER
             },
             CONDITION.TOKENREALM: {
@@ -364,7 +364,7 @@ def _get_response_content(response):
     def check_condition(self, options):
         """
         Check if all conditions are met and if the action should be executed.
-        The the conditions are met, we return "True"
+        If the conditions are met, we return "True"
         :return: True
         """
         g = options.get("g")
@@ -414,11 +414,11 @@ def check_condition(self, options):
                     return False
 
         if CONDITION.REALM in conditions:
-            if user.realm != conditions.get(CONDITION.REALM):
+            if user.realm not in conditions.get(CONDITION.REALM).split(","):
                 return False
 
         if CONDITION.RESOLVER in conditions:
-            if user.resolver != conditions.get(CONDITION.RESOLVER):
+            if user.resolver not in conditions.get(CONDITION.RESOLVER).split(","):
                 return False
 
         if "logged_in_user" in conditions:


Test patch:
diff --git a/tests/test_lib_events.py b/tests/test_lib_events.py
--- a/tests/test_lib_events.py
+++ b/tests/test_lib_events.py
@@ -649,6 +649,83 @@ def test_08_counter_condition(self):
         )
         self.assertTrue(r)
 
+    def test_09_check_conditions_realm_and_resolver_value(self):
+        # prepare
+        # setup realms
+        self.setUp_user_realms()
+        self.setUp_user_realm2()
+
+        serial = "pw01"
+        user = User("cornelius", "realm1")
+        remove_token(user=user)
+        tok = init_token({"serial": serial,
+                          "type": "pw", "otppin": "test", "otpkey": "secret"},
+                         user=user)
+        self.assertEqual(tok.type, "pw")
+
+        uhandler = BaseEventHandler()
+
+        # Checking values of the conditions
+        realm_value = uhandler.conditions.get("realm").get("value")
+        resolver_value = uhandler.conditions.get("resolver").get("value")
+        self.assertEqual([{'name': 'realm1'}, {'name': 'realm2'}], realm_value, realm_value)
+        self.assertEqual([{'name': 'resolver1'}], resolver_value, resolver_value)
+
+        builder = EnvironBuilder(method='POST',
+                                 data={'user': "cornelius@realm1",
+                                       "pass": "wrongvalue"},
+                                 headers={})
+        env = builder.get_environ()
+        req = Request(env)
+        # This is a kind of authentication request
+        req.all_data = {"user": "cornelius@realm1",
+                        "pass": "wrongvalue"}
+        req.User = User("cornelius", "realm1")
+        resp = Response()
+        resp.data = """{"result": {"value": false}}"""
+
+        r = uhandler.check_condition(
+            {"g": {},
+             "handler_def": {"conditions": {CONDITION.REALM: "realm1"}},
+             "request": req,
+             "response": resp
+             }
+        )
+        # Works if the realm is correct
+        self.assertEqual(r, True)
+
+        r = uhandler.check_condition(
+            {"g": {},
+             "handler_def": {"conditions": {CONDITION.REALM: "realm3"}},
+             "request": req,
+             "response": resp
+             }
+        )
+        # False if the realm is incorrect
+        self.assertEqual(r, False)
+
+        r = uhandler.check_condition(
+            {"g": {},
+             "handler_def": {"conditions": {CONDITION.RESOLVER: "resolver1"}},
+             "request": req,
+             "response": resp
+             }
+        )
+        # Works if the resolver is correct
+        self.assertEqual(r, True)
+
+        r = uhandler.check_condition(
+            {"g": {},
+             "handler_def": {"conditions": {CONDITION.REALM: "resolver3"}},
+             "request": req,
+             "response": resp
+             }
+        )
+        # False if the resolver is incorrect
+        self.assertEqual(r, False)
+
+        remove_token(serial)
+
 
 class CounterEventTestCase(MyTestCase):
 
@@ -2457,13 +2534,12 @@ def test_14_attach_token(self):
         options = {"g": g,
                    "request": req,
                    "response": resp,
-                   "handler_def":{
+                   "handler_def": {
                        "options": {
-                                   "application": "offline",
-                                   "count": "12"}}
+                           "application": "offline",
+                           "count": "12"}}
                    }
 
-
         t_handler = TokenEventHandler()
         res = t_handler.do("attach application", options=options)
         self.assertTrue(res)