provisionning: add hex digest to truncated role's name (#56295)

Max length of role's name is also augmented to 150 starting with Django
2.2.
This commit is contained in:
Benjamin Dauvergne 2021-08-22 15:10:41 +02:00
parent 49a95cbc4b
commit 739bffb78b
2 changed files with 38 additions and 3 deletions

View File

@ -14,9 +14,11 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import hashlib
import logging
import random
from django.contrib.auth.models import Group
from django.db import IntegrityError
from django.db.transaction import atomic
@ -105,6 +107,19 @@ class NotificationProcessing:
for user in User.objects.filter(saml_identifiers__name_id__in=uuids):
user.delete()
group_name_max_length = Group._meta.get_field('name').max_length
@classmethod
def truncate_role_name(cls, name):
"""Truncate name to 150 characters by adding a 4-chars partial-MD5 hex
digest for disambiguation."""
if len(name) <= cls.group_name_max_length: # Group.name has max_length=150 since Django 2.2
return name
else:
return (
name[: cls.group_name_max_length - 7] + ' (%4s)' % hashlib.md5(name.encode()).hexdigest()[:4]
)
@classmethod
def provision_role(cls, issuer, action, data, full=False):
logger = logging.getLogger(__name__)
@ -114,9 +129,7 @@ class NotificationProcessing:
uuids.add(o['uuid'])
if action == 'provision':
assert cls.check_valid_role(o)
role_name = o['name']
if len(role_name) > 70:
role_name = role_name[:70] + '(...)'
role_name = cls.truncate_role_name(o['name'])
try:
role = Role.objects.get(uuid=o['uuid'])
created = False

View File

@ -0,0 +1,22 @@
from hobo.provisionning.utils import NotificationProcessing
def test_truncate_role_name():
seen = set()
max_length = NotificationProcessing.group_name_max_length
assert max_length == 150 # value on Django 2.2
for length in range(max_length - 10, max_length):
name = 'a' * length
truncated = NotificationProcessing.truncate_role_name(name)
assert len(truncated) == length
assert truncated not in seen
seen.add(truncated)
for length in range(max_length + 1, max_length + 10):
name = 'a' * length
truncated = NotificationProcessing.truncate_role_name(name)
assert len(truncated) == max_length
assert truncated not in seen
seen.add(truncated)