Revision f46c95c4 snf-astakos-app/astakos/im/forms.py
b/snf-astakos-app/astakos/im/forms.py | ||
---|---|---|
49 | 49 |
|
50 | 50 |
from astakos.im.models import (AstakosUser, EmailChange, AstakosGroup, |
51 | 51 |
Invitation, Membership, GroupKind, Resource, |
52 |
get_latest_terms) |
|
52 |
get_latest_terms, RESOURCE_SEPARATOR)
|
|
53 | 53 |
from astakos.im.settings import (INVITATIONS_PER_LEVEL, BASEURL, SITENAME, |
54 | 54 |
RECAPTCHA_PRIVATE_KEY, RECAPTCHA_ENABLED, |
55 | 55 |
DEFAULT_CONTACT_EMAIL, LOGGING_LEVEL, |
56 |
PASSWORD_RESET_EMAIL_SUBJECT)
|
|
57 |
|
|
56 |
PASSWORD_RESET_EMAIL_SUBJECT,
|
|
57 |
NEWPASSWD_INVALIDATE_TOKEN) |
|
58 | 58 |
from astakos.im.widgets import DummyWidget, RecaptchaWidget |
59 | 59 |
from astakos.im.functions import send_change_email |
60 | 60 |
|
... | ... | |
176 | 176 |
ro = ('email', 'username',) |
177 | 177 |
for f in ro: |
178 | 178 |
self.fields[f].widget.attrs['readonly'] = True |
179 |
|
|
179 |
|
|
180 | 180 |
def save(self, commit=True): |
181 | 181 |
user = super(InvitedLocalUserCreationForm, self).save(commit=False) |
182 | 182 |
level = user.invitation.inviter.level + 1 |
... | ... | |
193 | 193 |
model = AstakosUser |
194 | 194 |
fields = ("email", "first_name", "last_name", |
195 | 195 |
"third_party_identifier", "has_signed_terms") |
196 |
|
|
196 |
|
|
197 | 197 |
def __init__(self, *args, **kwargs): |
198 | 198 |
""" |
199 | 199 |
Changes the order of fields, and removes the username field. |
... | ... | |
218 | 218 |
% (reverse('latest_terms'), _("the terms")) |
219 | 219 |
self.fields['has_signed_terms'].label = \ |
220 | 220 |
mark_safe("I agree with %s" % terms_link_html) |
221 |
|
|
221 |
|
|
222 | 222 |
def clean_email(self): |
223 | 223 |
email = self.cleaned_data['email'] |
224 | 224 |
if not email: |
... | ... | |
273 | 273 |
class ShibbolethUserCreationForm(ThirdPartyUserCreationForm): |
274 | 274 |
additional_email = forms.CharField( |
275 | 275 |
widget=forms.HiddenInput(), label='', required=False) |
276 |
|
|
276 |
|
|
277 | 277 |
def __init__(self, *args, **kwargs): |
278 | 278 |
super(ShibbolethUserCreationForm, self).__init__(*args, **kwargs) |
279 | 279 |
self.fields.keyOrder.append('additional_email') |
... | ... | |
282 | 282 |
field = self.fields[name] |
283 | 283 |
self.initial['additional_email'] = self.initial.get(name, |
284 | 284 |
field.initial) |
285 |
|
|
285 |
|
|
286 | 286 |
def clean_email(self): |
287 | 287 |
email = self.cleaned_data['email'] |
288 | 288 |
for user in AstakosUser.objects.filter(email=email): |
... | ... | |
304 | 304 |
recaptcha_challenge_field = forms.CharField(widget=DummyWidget) |
305 | 305 |
recaptcha_response_field = forms.CharField( |
306 | 306 |
widget=RecaptchaWidget, label='') |
307 |
|
|
307 |
|
|
308 | 308 |
def __init__(self, *args, **kwargs): |
309 | 309 |
was_limited = kwargs.get('was_limited', False) |
310 | 310 |
request = kwargs.get('request', None) |
... | ... | |
322 | 322 |
if was_limited and RECAPTCHA_ENABLED: |
323 | 323 |
self.fields.keyOrder.extend(['recaptcha_challenge_field', |
324 | 324 |
'recaptcha_response_field', ]) |
325 |
|
|
325 |
|
|
326 |
def clean_username(self): |
|
327 |
if 'username' in self.cleaned_data: |
|
328 |
return self.cleaned_data['username'].lower() |
|
329 |
|
|
326 | 330 |
def clean_recaptcha_response_field(self): |
327 | 331 |
if 'recaptcha_challenge_field' in self.cleaned_data: |
328 | 332 |
self.validate_captcha() |
... | ... | |
340 | 344 |
if not check.is_valid: |
341 | 345 |
raise forms.ValidationError( |
342 | 346 |
_('You have not entered the correct words')) |
343 |
|
|
347 |
|
|
344 | 348 |
def clean(self): |
345 | 349 |
super(LoginForm, self).clean() |
346 | 350 |
if self.user_cache and self.user_cache.provider not in ('local', ''): |
... | ... | |
515 | 519 |
super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs) |
516 | 520 |
|
517 | 521 |
def save(self, commit=True): |
518 |
user = super(ExtendedPasswordChangeForm, self).save(commit=False) |
|
519 |
if self.cleaned_data.get('renew'): |
|
520 |
user.renew_token() |
|
521 |
if commit: |
|
522 |
user.save() |
|
523 |
return user |
|
522 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
523 |
self.user.renew_token() |
|
524 |
return super(ExtendedPasswordChangeForm, self).save(commit=commit) |
|
524 | 525 |
|
525 | 526 |
|
526 | 527 |
class AstakosGroupCreationForm(forms.ModelForm): |
... | ... | |
532 | 533 |
name = forms.URLField() |
533 | 534 |
moderation_enabled = forms.BooleanField( |
534 | 535 |
help_text="Check if you want to approve members participation manually", |
535 |
required=False |
|
536 |
required=False |
|
537 |
) |
|
538 |
max_participants = forms.IntegerField( |
|
539 |
widget=forms.HiddenInput(), label='', required=False |
|
536 | 540 |
) |
537 |
|
|
541 |
|
|
538 | 542 |
class Meta: |
539 | 543 |
model = AstakosGroup |
540 | 544 |
|
541 | 545 |
def __init__(self, *args, **kwargs): |
542 |
try: |
|
543 |
resources = kwargs.pop('resources') |
|
544 |
except KeyError: |
|
545 |
resources = {} |
|
546 |
#update QueryDict |
|
547 |
args = list(args) |
|
548 |
qd = args.pop(0).copy() |
|
549 |
members_unlimited = qd.pop('members_unlimited', False) |
|
550 |
members_uplimit = qd.pop('members_uplimit', None) |
|
551 |
max_participants = None if members_unlimited else members_uplimit |
|
552 |
qd['max_participants']= max_participants.pop(0) if max_participants else None |
|
553 |
|
|
554 |
#substitue QueryDict |
|
555 |
args.insert(0, qd) |
|
556 |
|
|
546 | 557 |
super(AstakosGroupCreationForm, self).__init__(*args, **kwargs) |
547 |
self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc', 'issue_date',
|
|
548 |
'expiration_date', 'estimated_participants',
|
|
549 |
'moderation_enabled'] |
|
550 |
for id, r in resources.iteritems(): |
|
551 |
self.fields['resource_%s' % id] = forms.IntegerField(
|
|
552 |
label=r,
|
|
558 |
self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc', |
|
559 |
'issue_date', 'expiration_date',
|
|
560 |
'moderation_enabled', 'max_participants']
|
|
561 |
|
|
562 |
def add_field((k, v)):
|
|
563 |
self.fields[k] = forms.IntegerField(
|
|
553 | 564 |
required=False, |
554 |
help_text=_('Leave it blank for no additional quota.')
|
|
565 |
widget=forms.HiddenInput()
|
|
555 | 566 |
) |
567 |
map(add_field, |
|
568 |
((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit')) |
|
569 |
) |
|
570 |
|
|
571 |
def policies(self): |
|
572 |
for name, uplimit in self.cleaned_data.iteritems(): |
|
573 |
subs = name.split('_uplimit') |
|
574 |
if len(subs) == 2: |
|
575 |
prefix, suffix = subs |
|
576 |
# # yield only those having a value |
|
577 |
# if not value: |
|
578 |
# continue |
|
579 |
s, r = prefix.split(RESOURCE_SEPARATOR) |
|
580 |
yield dict(service=s, resource=r, uplimit=uplimit) |
|
556 | 581 |
|
557 |
def resources(self): |
|
558 |
for name, value in self.cleaned_data.items(): |
|
559 |
prefix, delimiter, suffix = name.partition('resource_') |
|
560 |
if suffix: |
|
561 |
# yield only those having a value |
|
562 |
if not value: |
|
563 |
continue |
|
564 |
yield (suffix, value) |
|
565 | 582 |
|
566 | 583 |
class AstakosGroupUpdateForm(forms.ModelForm): |
567 | 584 |
class Meta: |
568 | 585 |
model = AstakosGroup |
569 | 586 |
fields = ('homepage', 'desc') |
570 | 587 |
|
588 |
|
|
571 | 589 |
class AddGroupMembersForm(forms.Form): |
572 |
q = forms.CharField(max_length=800, widget=forms.Textarea, label=_('Search users'), |
|
573 |
help_text=_('Add comma separated user emails'), |
|
574 |
required=True) |
|
575 |
|
|
590 |
q = forms.CharField( |
|
591 |
max_length=800, widget=forms.Textarea, label=_('Search users'), |
|
592 |
help_text=_('Add comma separated user emails'), |
|
593 |
required=True) |
|
594 |
|
|
576 | 595 |
def clean(self): |
577 | 596 |
q = self.cleaned_data.get('q') or '' |
578 | 597 |
users = q.split(',') |
... | ... | |
584 | 603 |
_('Unknown users: %s' % ','.join(unknown))) |
585 | 604 |
self.valid_users = db_entries |
586 | 605 |
return self.cleaned_data |
587 |
|
|
606 |
|
|
588 | 607 |
def get_valid_users(self): |
589 | 608 |
"""Should be called after form cleaning""" |
590 | 609 |
try: |
... | ... | |
596 | 615 |
class AstakosGroupSearchForm(forms.Form): |
597 | 616 |
q = forms.CharField(max_length=200, label='Search group') |
598 | 617 |
|
618 |
|
|
599 | 619 |
class TimelineForm(forms.Form): |
600 | 620 |
# entity = forms.CharField( |
601 | 621 |
# widget=forms.HiddenInput(), label='') |
602 | 622 |
entity = forms.ModelChoiceField( |
603 |
queryset=AstakosUser.objects.filter(is_active = True)
|
|
623 |
queryset=AstakosUser.objects.filter(is_active=True)
|
|
604 | 624 |
) |
605 | 625 |
resource = forms.ModelChoiceField( |
606 | 626 |
queryset=Resource.objects.all() |
... | ... | |
609 | 629 |
end_date = forms.DateTimeField() |
610 | 630 |
details = forms.BooleanField(required=False, label="Detailed Listing") |
611 | 631 |
operation = forms.ChoiceField( |
612 |
label = 'Charge Method', |
|
613 |
choices = ( ('', '-------------'), |
|
614 |
('charge_usage', 'Charge Usage'), |
|
615 |
('charge_traffic', 'Charge Traffic'), ) |
|
616 |
) |
|
632 |
label='Charge Method', |
|
633 |
choices=(('', '-------------'), |
|
634 |
('charge_usage', 'Charge Usage'), |
|
635 |
('charge_traffic', 'Charge Traffic'), ) |
|
636 |
) |
|
637 |
|
|
617 | 638 |
def clean(self): |
618 | 639 |
super(TimelineForm, self).clean() |
619 | 640 |
d = self.cleaned_data |
620 | 641 |
if 'resource' in d: |
621 | 642 |
d['resource'] = str(d['resource']) |
622 | 643 |
if 'start_date' in d: |
623 |
d['start_date'] = d['start_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24] |
|
644 |
d['start_date'] = d['start_date'].strftime( |
|
645 |
"%Y-%m-%dT%H:%M:%S.%f")[:24] |
|
624 | 646 |
if 'end_date' in d: |
625 | 647 |
d['end_date'] = d['end_date'].strftime("%Y-%m-%dT%H:%M:%S.%f")[:24] |
626 |
if 'entity' in d:
|
|
648 |
if 'entity' in d:
|
|
627 | 649 |
d['entity'] = d['entity'].email |
628 | 650 |
return d |
629 | 651 |
|
652 |
|
|
630 | 653 |
class AstakosGroupSortForm(forms.Form): |
631 | 654 |
sort_by = forms.ChoiceField(label='Sort by', |
632 | 655 |
choices=(('groupname', 'Name'), |
633 | 656 |
('kindname', 'Type'), |
634 | 657 |
('issue_date', 'Issue Date'), |
635 |
('expiration_date', 'Expiration Date'), |
|
636 |
('approved_members_num', 'Participants'), |
|
658 |
('expiration_date', |
|
659 |
'Expiration Date'), |
|
660 |
('approved_members_num', |
|
661 |
'Participants'), |
|
637 | 662 |
('is_enabled', 'Status'), |
638 | 663 |
('moderation_enabled', 'Moderation'), |
639 |
('membership_status','Enrollment Status') |
|
664 |
('membership_status', |
|
665 |
'Enrollment Status') |
|
640 | 666 |
), |
641 | 667 |
required=False) |
642 | 668 |
|
669 |
|
|
643 | 670 |
class MembersSortForm(forms.Form): |
644 | 671 |
sort_by = forms.ChoiceField(label='Sort by', |
645 | 672 |
choices=(('person__email', 'User Id'), |
... | ... | |
648 | 675 |
), |
649 | 676 |
required=False) |
650 | 677 |
|
678 |
|
|
651 | 679 |
class PickResourceForm(forms.Form): |
652 | 680 |
resource = forms.ModelChoiceField( |
653 | 681 |
queryset=Resource.objects.select_related().all() |
654 | 682 |
) |
655 |
resource.widget.attrs["onchange"]="this.form.submit()" |
|
683 |
resource.widget.attrs["onchange"] = "this.form.submit()" |
|
684 |
|
|
685 |
|
|
686 |
class ExtendedSetPasswordForm(SetPasswordForm): |
|
687 |
""" |
|
688 |
Extends SetPasswordForm by enabling user |
|
689 |
to optionally renew also the token. |
|
690 |
""" |
|
691 |
if not NEWPASSWD_INVALIDATE_TOKEN: |
|
692 |
renew = forms.BooleanField(label='Renew token', required=False, |
|
693 |
initial=True, |
|
694 |
help_text='Unsetting this may result in security risk.') |
|
695 |
|
|
696 |
def __init__(self, user, *args, **kwargs): |
|
697 |
super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs) |
|
698 |
|
|
699 |
def save(self, commit=True): |
|
700 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
701 |
if isinstance(self.user, AstakosUser): |
|
702 |
self.user.renew_token() |
|
703 |
return super(ExtendedSetPasswordForm, self).save(commit=commit) |
Also available in: Unified diff