Repository: privacyidea/privacyidea

Issue:
Show disallowed characters in policy name
If you create a policy, privacyIDEA does not check its name. You could enter a name like "foo/bar", but privacyIDEA will say 404, because "/policy/foo/bar" could not be found.

So we should may add a message, which says something like "The character '/' is not allowed here."


Discussion:
Okay in fact this problem is not only in the policies.

If I create a token for example with `token/init user=name genkey=1 serial=foo/bar type=hotp`, I won't be able to remove it again. Because the api request would be `DELETE token/foo/bar` and the response will be `404 - NOT FOUND`

So we should disallow slashes in any api requests. It doesn't matter, if these are endpoints or parameters..
This is a UI topic, since the UI will simply create an call to an endpoint ``POST /policy/foo/bar`` and the server can not catch this anymore.
This is not only a UI problem. If you add a token with a serial which contains a `/`, you cannot delete it via cURL, nor HTTP nor UI. So you have to remove it in the database.
I think there is mixing up some issues here. Policy is a ui issue, serial not.

So here are the todos:

When creating a policy like ``foo/bar`` privacyIDEA responds correctly with a 404, but it looks like the 404 is not displayed.

* [x] step one: display the 404 in the UI
* [ ] step two (optional): check the characters in the UI.
I think, this issue still touches both parts:
- the UI part can be handled quite easily by adding an attribute `pattern="[a-zA-Z0-9_ .-]+"` to the input element. This is plain HTML but if You want fancy pop-ups whenever an invalid character is entered, we need some javascript.
- On the other hand, we have the back-end which can still be reached via API-call. And there we have two different ways to create resources:
  1. Adding the name of the resource to the URL:
     - policies are are added using a POST-request to `/policy/<name>`. If the name contains a leading `/` this will break anyway, the rest is covered by #1815 
     - The same is true for realms, resolver, caconnector and machineresolver. They are covered by [`sanity_name_check()`](https://github.com/privacyidea/privacyidea/blob/edd1aa49d198fc70a402a62aeced193e15b8d5a5/privacyidea/lib/utils/__init__.py#L391)
     - The privacyideaserver, radiusserver and smtpserver APIs need to be checked.
  2. The name of the resource is given via parameter:
     - Events, smsgateway and periodic tasks need a parameter with the name when created. This parameter needs to be checked.

Adding a `user` resource is a special use-case in my opinion.

We should have a common list for allowed characters and it should be checked in the UI as well. It is confusing if the UI accepts an input but the back-end complains that there are forbidden characters in the name.

BTW: we could enable slashes in resource names with the `path`-converter in Flask: https://flask.palletsprojects.com/en/1.1.x/quickstart/#variable-rules
But i think this over-complicates things.
Interesting. But I also think it is more clear, if we disallow slashes.
we will do this by using *allowed patterns* in the input field.

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
@@ -168,7 +168,8 @@ def set_random_pin(request=None, action=None):
 
     if len(pin_pols) == 0:
         # We do this to avoid that an admin sets a random PIN manually!
-        raise TokenAdminError("You need to specify a policy 'otp_pin_set_random' in scope {0!s}.".format(scope))
+        raise TokenAdminError("You need to specify a policy '{0!s}' in scope "
+                              "{1!s}.".format(ACTION.OTPPINSETRANDOM, scope))
     elif len(pin_pols) == 1:
         log.debug("Creating random OTP PIN with length {0!s}".format(list(pin_pols)[0]))
         request.all_data["pin"] = generate_password(size=int(list(pin_pols)[0]))


Test patch: