1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from __future__
import unicode_literals
19 from wtforms
.fields
import StringField
, SelectField
, PasswordField
20 from wtforms
.fields
.html5
import EmailField
21 from wtforms
.validators
import DataRequired
, Length
, ValidationError
, Optional
23 from indico
.modules
.auth
import Identity
24 from indico
.modules
.users
import User
25 from indico
.util
.i18n
import _
26 from indico
.web
.forms
.base
import IndicoForm
, SyncedInputsMixin
27 from indico
.web
.forms
.validators
import ConfirmPassword
, used_if_not_synced
28 from indico
.web
.forms
.widgets
import SyncedInputWidget
32 return s
.lower() if s
else s
35 def _check_existing_email(form
, field
):
36 if User
.find_all(~User
.is_deleted
, ~User
.is_pending
, User
.all_emails
.contains(field
.data
)):
37 raise ValidationError(_('This email address is already in use.'))
40 def _check_existing_username(form
, field
):
41 if Identity
.find(provider
='indico', identifier
=field
.data
).count():
42 raise ValidationError(_('This username is already in use.'))
45 class LocalLoginForm(IndicoForm
):
46 identifier
= StringField(_('Username'), [DataRequired()], filters
=[_tolower
])
47 password
= PasswordField(_('Password'), [DataRequired()])
50 class AddLocalIdentityForm(IndicoForm
):
51 username
= StringField(_('Username'), [DataRequired(), _check_existing_username
], filters
=[_tolower
])
52 password
= PasswordField(_('Password'), [DataRequired(), Length(min=5)])
53 confirm_password
= PasswordField(_('Confirm password'), [DataRequired(), ConfirmPassword('password')])
56 class EditLocalIdentityForm(IndicoForm
):
57 username
= StringField(_('Username'), [DataRequired()], filters
=[_tolower
])
58 password
= PasswordField(_('Current password'), [DataRequired()])
59 new_password
= PasswordField(_('New password'), [Optional(), Length(min=5)])
60 confirm_new_password
= PasswordField(_('Confirm password'), [ConfirmPassword('new_password')])
62 def __init__(self
, *args
, **kwargs
):
63 self
.identity
= kwargs
.pop('identity', None)
64 super(EditLocalIdentityForm
, self
).__init
__(*args
, **kwargs
)
66 def validate_password(self
, field
):
67 if field
.data
!= self
.identity
.password
:
68 raise ValidationError(_("Wrong current password"))
70 def validate_username(self
, field
):
71 query
= Identity
.find(Identity
.provider
== 'indico',
72 Identity
.identifier
== field
.data
,
73 Identity
.identifier
!= self
.identity
.identifier
)
75 raise ValidationError(_('This username is already in use.'))
78 class SelectEmailForm(IndicoForm
):
79 email
= SelectField(_('Email address'), [DataRequired()],
80 description
=_('Choose the email address you want to verify.'))
83 class RegistrationEmailForm(IndicoForm
):
84 email
= EmailField(_('Email address'), [DataRequired(), _check_existing_email
], filters
=[_tolower
])
87 class RegistrationForm(IndicoForm
):
88 first_name
= StringField(_('First name'), [DataRequired()])
89 last_name
= StringField(_('Family name'), [DataRequired()])
90 affiliation
= StringField(_('Affiliation'))
93 class MultipassRegistrationForm(SyncedInputsMixin
, IndicoForm
):
94 first_name
= StringField(_('First Name'), [used_if_not_synced
, DataRequired()], widget
=SyncedInputWidget())
95 last_name
= StringField(_('Family name'), [used_if_not_synced
, DataRequired()], widget
=SyncedInputWidget())
96 affiliation
= StringField(_('Affiliation'), widget
=SyncedInputWidget())
97 email
= SelectField(_('Email address'), [DataRequired(), _check_existing_email
])
98 address
= StringField(_('Address'), widget
=SyncedInputWidget(textarea
=True))
99 phone
= StringField(_('Phone number'), widget
=SyncedInputWidget())
102 class LocalRegistrationForm(RegistrationForm
):
103 email
= EmailField(_('Email address'))
104 username
= StringField(_('Username'), [DataRequired(), _check_existing_username
], filters
=[_tolower
])
105 password
= PasswordField(_('Password'), [DataRequired(), Length(min=5)])
106 confirm_password
= PasswordField(_('Confirm password'), [DataRequired(), ConfirmPassword('password')])
109 class ResetPasswordEmailForm(IndicoForm
):
110 email
= EmailField(_('Email address'), [DataRequired()], filters
=[_tolower
])
112 def validate_email(self
, field
):
115 raise ValidationError(_('There is no profile with this email address.'))
116 elif not user
.local_identities
:
117 # XXX: Should we allow creating a new identity instead? Would be user-friendly for sure!
118 raise ValidationError(_('This profile has no local account.'))
122 if not self
.is_submitted() or not self
.email
.data
:
124 return User
.find_first(~User
.is_deleted
, ~User
.is_blocked
, ~User
.is_pending
,
125 User
.all_emails
.contains(self
.email
.data
))
128 class ResetPasswordForm(IndicoForm
):
129 username
= StringField(_('Username'))
130 password
= PasswordField(_('New password'), [DataRequired(), Length(min=5)])
131 confirm_password
= PasswordField(_('Confirm password'), [DataRequired(), ConfirmPassword('password')])