Repository: privacyidea/privacyidea

Issue:
max_token_per_user does not find the max value
There is a bug with the max_token_per_user policy.

The problem is here:

https://github.com/privacyidea/privacyidea/blob/branch-2.22/privacyidea/api/lib/prepolicy.py#L614

``limit_list`` is a list of the "max_token_per_user" values for the specific request. 
The list is a list of action values, that are strings. So this list could be ``["20", "4"]``.

But:

    max(["20", "4"]) -> "4"

and

    int(max(["20", "4"])) -> 4

The max should be:

     max([int(x) for x in limit_list])

This would result in 20 as expected.

We also need to add a test accordingly!


Discussion:

Resolving patch:
diff --git a/privacyidea/api/lib/prepolicy.py b/privacyidea/api/lib/prepolicy.py
--- a/privacyidea/api/lib/prepolicy.py
+++ b/privacyidea/api/lib/prepolicy.py
@@ -614,6 +614,7 @@ def twostep_enrollment_parameters(request=None, action=None):
             if action_values:
                 request.all_data[parameter] = action_values[0]
 
+
 def check_max_token_user(request=None, action=None):
     """
     Pre Policy
@@ -642,7 +643,7 @@ def check_max_token_user(request=None, action=None):
             # we need to check how many tokens the user already has assigned!
             tokenobject_list = get_tokens(user=user_object)
             already_assigned_tokens = len(tokenobject_list)
-            if already_assigned_tokens >= int(max(limit_list)):
+            if already_assigned_tokens >= max([int(x) for x in limit_list]):
                 raise PolicyError(ERROR)
     return True
 
@@ -679,10 +680,10 @@ def check_max_token_realm(request=None, action=None):
                                                      realm=realm,
                                                      client=g.client_ip)
         if limit_list:
-            # we need to check how many tokens the user already has assigned!
+            # we need to check how many tokens the realm already has assigned!
             tokenobject_list = get_tokens(realm=realm)
             already_assigned_tokens = len(tokenobject_list)
-            if already_assigned_tokens >= int(max(limit_list)):
+            if already_assigned_tokens >= max([int(x) for x in limit_list]):
                 raise PolicyError(ERROR)
     return True
 


Test patch:
diff --git a/tests/test_api_lib_policy.py b/tests/test_api_lib_policy.py
--- a/tests/test_api_lib_policy.py
+++ b/tests/test_api_lib_policy.py
@@ -296,6 +296,17 @@ def test_04_check_max_token_user(self):
         self.assertRaises(PolicyError,
                           check_max_token_user, req)
 
+        # Now we set another policy for the user max_token = 12.
+        # This way, the user should be allowed to enroll tokens again, since there
+        # are two policies matching for the user and the maximum is 12.
+        set_policy(name="pol_max_12",
+                   scope=SCOPE.ENROLL,
+                   action="{0!s}={1!s}".format(ACTION.MAXTOKENUSER, 12))
+        g.policy_object = PolicyClass()
+        # new check_max_token_user should not raise an error!
+        self.assertTrue(check_max_token_user(req))
+        delete_policy("pol_max_12")
+        g.policy_object = PolicyClass()
 
         # The check for a token, that has no username in it, must not
         # succeed. I.e. in the realm new tokens must be enrollable.