manager: implement csv import of role emails and emails_to_members (#72462)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Benjamin Dauvergne 2024-02-26 14:55:49 +01:00
parent 7d6601c870
commit 88c1106777
2 changed files with 47 additions and 4 deletions

View File

@ -859,13 +859,12 @@ class RolesCsvImportForm(LimitQuerysetFormMixin, forms.Form):
roles_by_names[role.ou][role.name] = role
self.roles = []
errors = []
for i, csvline in enumerate(csv.reader(StringIO(content), dialect=dialect, delimiter=',')):
if not csvline:
continue
if i == 0:
if csvline != ['name', 'slug', 'ou'][: len(csvline)]:
if csvline != ['name', 'slug', 'ou', 'emails', 'emails_to_members'][: len(csvline)]:
header = ','.join(csvline)
raise ValidationError(_('Invalid file header "%s", expected "name,slug,ou".') % header)
continue
@ -892,6 +891,27 @@ class RolesCsvImportForm(LimitQuerysetFormMixin, forms.Form):
self.add_line_error(_('Organizational Unit %s does not exist.') % csvline[2], i)
continue
emails = []
if len(csvline) > 3:
for email in csvline[3].split():
email = email.strip()
try:
EmailValidator()(email)
except ValidationError as e:
self.add_line_error(
_('Invalid email "%(email)s": %(error)s') % {'email': email, 'error': e},
i,
)
else:
emails.append(email)
emails_to_members = None
if len(csvline) > 4:
if csvline[4].strip().lower() in ('yes', 'true', '1', 'on'):
emails_to_members = True
if csvline[4].strip().lower() in ('no', 'false', '0', 'off'):
emails_to_members = False
if name in roles_by_names.get(ou, {}):
role = roles_by_names[ou][name]
role.slug = slug or role.slug
@ -904,13 +924,17 @@ class RolesCsvImportForm(LimitQuerysetFormMixin, forms.Form):
if not role.slug:
role.slug = generate_slug(role.name, seen_slugs=roles_by_slugs[ou])
if emails:
role.emails = emails
if emails_to_members is not None:
role.emails_to_members = emails_to_members
roles_by_slugs[ou][role.slug] = role
roles_by_names[ou][role.name] = role
role.ou = ou
self.roles.append(role)
if errors:
raise ValidationError(errors)
def add_line_error(self, error, line):
error = _('%(error)s (line %(number)d)') % {'error': error, 'number': line + 1}

View File

@ -379,6 +379,25 @@ def test_manager_role_csv_import(app, admin, ou1, ou2):
resp = resp.form.submit()
assert 'Invalid slug "invalid slug". (line 2)' in resp.pyquery('.error').text()
csv_header = b'name,slug,ou,emails,emails_to_members\n'
csv_content = f'''Role Name,role_slug,{ou1.slug},foo@example.net bar@example.net,false
Other role,other,{ou1.slug},foo@example.net bar@example.net,yes'''
resp.form['import_file'] = Upload('t.csv', csv_header + csv_content.encode(), 'text/csv')
resp.form.submit(status=302)
assert set(Role.objects.get(name='Role Name', slug='role_slug', ou=ou1).emails) == {
'foo@example.net',
'bar@example.net',
}
assert not Role.objects.get(name='Role Name', slug='role_slug', ou=ou1).emails_to_members
assert set(Role.objects.get(name='Other role').emails) == {'foo@example.net', 'bar@example.net'}
assert Role.objects.get(slug='other').emails_to_members
csv_header = b'name,slug,ou,emails,emails_to_members\n'
csv_content = f'''Role Name,role_slug,{ou1.slug},foo#@example.net xyz'''
resp.form['import_file'] = Upload('t.csv', csv_header + csv_content.encode(), 'text/csv')
resp = resp.form.submit()
assert str(resp).count('Invalid email') == 2
resp = app.get('/manage/roles/csv-import/')
resp = resp.click('Download sample')
assert 'name,slug,ou' in resp.text