filter attributes on edit-profile page by scope (fixes #21769)

This commit is contained in:
Benjamin Dauvergne 2018-02-19 21:13:40 +01:00
parent fcc3a92bff
commit ce363ab81d
3 changed files with 62 additions and 6 deletions

View File

@ -43,6 +43,7 @@ def password_change_view(request, *args, **kwargs):
urlpatterns = patterns('authentic2.views',
url(r'^logged-in/$', 'logged_in', name='logged-in'),
url(r'^edit/$', 'edit_profile', name='profile_edit'),
url(r'^edit/(?P<scope>[-\w]+)/$', 'edit_profile', name='profile_edit_with_scope'),
url(r'^change-email/$', 'email_change', name='email-change'),
url(r'^change-email/verify/$', 'email_change_verify',
name='email-change-verify'),

View File

@ -75,7 +75,7 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView):
return bool(fields) and app_settings.A2_PROFILE_CAN_EDIT_PROFILE
@classmethod
def get_fields(cls):
def get_fields(cls, scopes=None):
editable_profile_fields = []
for field in app_settings.A2_PROFILE_FIELDS:
if isinstance(field, (list, tuple)):
@ -89,13 +89,26 @@ class EditProfile(cbv.HookMixin, cbv.TemplateNamesMixin, UpdateView):
else:
if attribute.user_editable:
editable_profile_fields.append(field)
default_fields = list(models.Attribute.objects.filter(user_editable=True).values_list('name', flat=True))
return utils.get_fields_and_labels(
editable_profile_fields,
default_fields)
attributes = models.Attribute.objects.filter(user_editable=True)
if scopes:
scopes = set(scopes)
default_fields = [attribute.name for attribute in attributes if scopes & set(attribute.scopes.split())]
else:
default_fields = list(attributes.values_list('name', flat=True))
fields, labels = utils.get_fields_and_labels(
editable_profile_fields,
default_fields)
if scopes:
# restrict fields to those in the scopes
fields = [field for field in fields if field in default_fields]
return fields, labels
def get_form_class(self):
fields, labels = self.get_fields()
if 'scope' in self.kwargs:
scopes = [self.kwargs['scope']]
else:
scopes = self.request.GET.get('scope', '').split()
fields, labels = self.get_fields(scopes=scopes)
# Email must be edited through the change email view, as it needs validation
fields = [field for field in fields if field != 'email']
return forms.modelform_factory(compat.get_user_model(), fields=fields,

View File

@ -63,3 +63,45 @@ def test_account_edit_next_url(app, simple_user, external_redirect_next_url, ass
resp = resp.form.submit('cancel')
assert_external_redirect(resp, reverse('account_management'))
assert attribute.get_value(simple_user) == '0123456789'
def test_account_edit_scopes(app, simple_user):
utils.login(app, simple_user)
url = reverse('profile_edit')
Attribute.objects.create(name='phone', label='phone',
kind='string', user_visible=True,
user_editable=True, scopes='contact')
Attribute.objects.create(name='mobile', label='mobile phone',
kind='string', user_visible=True,
user_editable=True, scopes='contact')
Attribute.objects.create(name='city', label='city',
kind='string', user_visible=True,
user_editable=True, scopes='address')
Attribute.objects.create(name='zipcode', label='zipcode', kind='string',
user_visible=True, user_editable=True,
scopes='address')
def get_fields(resp):
return set(key.split('edit-profile-')[1]
for key in resp.form.fields.keys() if key and key.startswith('edit-profile-'))
resp = app.get(url, status=200)
assert get_fields(resp) == set(['first_name', 'last_name', 'phone', 'mobile', 'city', 'zipcode', 'next_url'])
resp = app.get(url + '?scope=contact', status=200)
assert get_fields(resp) == set(['phone', 'mobile', 'next_url'])
resp = app.get(url + '?scope=address', status=200)
assert get_fields(resp) == set(['city', 'zipcode', 'next_url'])
resp = app.get(url + '?scope=contact address', status=200)
assert get_fields(resp) == set(['phone', 'mobile', 'city', 'zipcode', 'next_url'])
resp = app.get(reverse('profile_edit_with_scope', kwargs={'scope': 'contact'}),
status=200)
assert get_fields(resp) == set(['phone', 'mobile', 'next_url'])
resp = app.get(reverse('profile_edit_with_scope', kwargs={'scope': 'address'}),
status=200)
assert get_fields(resp) == set(['city', 'zipcode', 'next_url'])