cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
user.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 ##
21 # @package src.wi.forms.user
22 #
23 # @author Krzysztof Danielowski
24 # @date 31.01.2014
25 #
26 import hashlib
27 
28 from django import forms
29 from django.utils.translation import ugettext_lazy as _
30 
31 from common.states import user_active_states
32 from wi import settings
33 from wi.recaptcha_django import ReCaptchaField
34 from wi.utils import parsing
35 from wi.utils.auth import authenticate, cm_authenticate
36 from wi.utils.forms import PasswordForm, attrs_dict
37 from wi.utils.regexp import regexp, regexp_text
38 from wi.utils.views import make_request
39 from wi.utils.widgets import SelectWithDisabled
40 
41 
42 ##
43 #
44 # Class for <b>login</b> form.
45 #
46 class AuthenticationForm(forms.Form):
47  username = forms.CharField(max_length=63,
48  label=_('Username'),
49  widget=forms.TextInput(attrs={'tabindex': '1', 'class': 'required'}))
50  password = forms.RegexField(regex=regexp['password'],
51  max_length=255,
52  label=_('Password'),
53  widget=forms.PasswordInput(attrs={'tabindex': '2', 'class': 'required'}),
54  error_messages={'invalid': regexp_text['password']})
55 
56  ##
57  #
58  # If request is passed in, the form will validate that cookies are
59  # enabled.
60  #
61  # @note
62  # Note that the \c request (a HttpRequest object) must have set
63  # a cookie with the key \c TEST_COOKIE_NAME and value \c TEST_COOKIE_VALUE
64  # before running this validation.
65  #
66  def __init__(self, request=None, *args, **kwargs):
67  self.request = request
68  self.user_cache = None
69  super(AuthenticationForm, self).__init__(*args, **kwargs)
70 
71  ##
72  #
73  # Validates the password.
74  #
75  def clean(self):
76  if not self.cleaned_data.get('password') or not self.cleaned_data.get('username'):
77  return None
78  self.cleaned_data['password'] = hashlib.sha1(self.cleaned_data['password']).hexdigest()
79 
80  username = self.cleaned_data['username']
81  password = self.cleaned_data['password']
82 
83  self.user_cache = authenticate(username, password)
84 
85  if self.user_cache is None:
86  raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
87  elif self.user_cache.is_active == user_active_states['inactive']:
88  raise forms.ValidationError(_("Account has not been activated yet. Please, click on the activation link in the email sent to you after the registration step."))
89  elif self.user_cache.is_active == user_active_states['email_confirmed']:
90  raise forms.ValidationError(_("This account is inactive. Please wait for system operator to activate your account."))
91 
92  if self.request and not self.request.session.test_cookie_worked():
93  raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
94 
95  return self.cleaned_data
96 
97  ##
98  #
99  # Returns cached user object instance.
100  #
101  def get_user(self):
102  return self.user_cache
103 
104 
105 ##
106 #
107 # Class of the <b>password's reset</b> form.
108 #
109 class PasswordResetForm(forms.Form):
110  email = forms.EmailField(label=_("E-mail"), max_length=255)
111 
112  ##
113  #
114  # Validates that a user exists with the given e-mail address.
115  #
116  def clean_email(self):
117  email = self.cleaned_data['email']
118 
119  rest_data = make_request('guest/user/email_exists/', {'email': email})
120  if rest_data['status'] == 'ok' and rest_data['data'] == False:
121  raise forms.ValidationError(_('Incorrect email address.'))
122 
123  return email
124 
125 
126 ##
127 #
128 # Class of the <b>password edition (doesnt's require giving the previous one)</b> form.
129 #
130 class SetPasswordForm(forms.Form):
131  new_password1 = forms.RegexField(regex=regexp['password'],
132  max_length=255,
133  widget=forms.PasswordInput(attrs=dict(attrs_dict)),
134  label=_("New password"),
135  error_messages={'invalid': regexp_text['password']})
136 
137  new_password2 = forms.RegexField(regex=regexp['password'],
138  max_length=255,
139  widget=forms.PasswordInput(attrs=dict(attrs_dict)),
140  label=_("New password confirmation"),
141  error_messages={'invalid': regexp_text['password']})
142 
143  ##
144  #
145  #
146  def clean(self):
147  if 'new_password1' in self.cleaned_data and 'new_password2' in self.cleaned_data:
148  if self.cleaned_data['new_password1'] != self.cleaned_data['new_password2']:
149  raise forms.ValidationError(_("The two password fields didn't match."))
150 
151  self.cleaned_data['new_password1'] = hashlib.sha1(self.cleaned_data['new_password1']).hexdigest()
152  del self.cleaned_data['new_password2']
153  return self.cleaned_data
154 
155 
156 ##
157 #
158 # Form for <b>registering a new user account</b>.
159 #
160 # Validates that the requested username is not already in use, and
161 # requires the password to be entered twice to catch typos.
162 #
163 class RegistrationForm(PasswordForm):
164  login = forms.RegexField(regex=regexp['login'],
165  max_length=63,
166  widget=forms.TextInput(attrs=attrs_dict),
167  label=_('Username'),
168  error_messages={'invalid': regexp_text['login']})
169  first = forms.CharField(max_length=63,
170  widget=forms.TextInput(attrs=attrs_dict),
171  label=_('First name'))
172  last = forms.CharField(max_length=63,
173  widget=forms.TextInput(attrs=attrs_dict),
174  label=_('Last name'))
175  organization = forms.CharField(max_length=63,
176  widget=forms.TextInput(attrs=attrs_dict),
177  label=_('Organization'))
178  email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=255)),
179  label=_('Email address'))
180 
181  def __init__(self, *args, **kwargs):
182  super(RegistrationForm, self).__init__(*args, **kwargs)
183 
184  self.fields.keyOrder = ['login', 'first', 'last', 'organization', 'email', 'new_password', 'password2']
185 
186  if settings.CAPTCHA:
187  self.fields['recaptcha'] = ReCaptchaField()
188 
189  ##
190  #
191  # Validate that the login is alphanumeric and is not already in use.
192  #
193  def clean_login(self):
194  response = make_request('guest/user/exists/', {'login': self.cleaned_data['login']})
195 
196  if response['data'] == False:
197  return self.cleaned_data['login']
198  else:
199  raise forms.ValidationError(_("A user with that login already exists."))
200 
201  ##
202  #
203  # Validate that the supplied email address is unique for the site.
204  #
205  def clean_email(self):
206  response = make_request('guest/user/email_exists/', {'email': self.cleaned_data['email']})
207 
208  if response['data'] == False:
209  return self.cleaned_data['email']
210  else:
211  raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
212 
213 
214 ##
215 #
216 # Class of the <b>user data edition</b> form.
217 #
218 class AccountDataEdit(forms.Form):
219  email = forms.EmailField(widget=forms.TextInput(attrs=dict(maxlength=255)),
220  label=_('Email address'))
221 
222  def __init__(self, *args, **kwargs):
223  rest_data = kwargs.pop('rest_data')
224  try:
225  self.old_email = args[0]['email']
226  except Exception:
227  self.old_email = kwargs['data']['email']
228  super(AccountDataEdit, self).__init__(*args, **kwargs)
229 
230  self.fields['default_cluster_id'] = forms.ChoiceField(choices=parsing.parse_cm_list(rest_data), label=_('Default CM'))
231  self.fields['default_cluster_id'].widget.attrs['class'] = 'medium'
232 
233  ##
234  #
235  # Validate that the supplied email address is unique for the site.
236  #
237  def clean_email(self):
238  # if same email as current
239  if self.old_email == self.cleaned_data['email']:
240  return self.cleaned_data['email']
241 
242  rest_data = make_request('guest/user/email_exists/', {'email': self.cleaned_data['email']})
243 
244  if rest_data['data']:
245  raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
246  else:
247  return self.cleaned_data['email']
248 
249  ##
250  #
251  # Cast 'default_cluster_id' to int.
252  #
254  return int(self.cleaned_data['default_cluster_id'])
255 
256 
257 ##
258 #
259 # Class of the <b>password edition (requires giving the previous one)</b>
260 # form.
261 #
263  old_password = forms.RegexField(regex=regexp['password'],
264  max_length=255,
265  widget=forms.PasswordInput,
266  label=_("Old password"),
267  error_messages={'invalid': regexp_text['password']})
268 
269  def __init__(self, user, *args, **kwargs):
270  self.user = user
271  super(PasswordChangeForm, self).__init__(*args, **kwargs)
272 
273  self.fields.keyOrder = ['old_password', 'new_password1', 'new_password2']
274 
275  ##
276  #
277  # Validates that the old_password field is correct.
278  #
280  self.cleaned_data['old_password'] = hashlib.sha1(self.cleaned_data['old_password']).hexdigest()
281  old_password = self.cleaned_data["old_password"]
282 
283  rest_data = make_request('guest/user/check_password/', {'login': self.user.username, 'password': old_password})
284  if rest_data['status'] == 'ok' and rest_data['data'] == False:
285  raise forms.ValidationError(_("Your old password was entered incorrectly. Please enter it again."))
286  return old_password
287 
288 
289 ##
290 #
291 # Form for <b>sending error information/help</b>.
292 #
293 class HelpForm(forms.Form):
294  topic = forms.CharField(widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=255)),
295  label=_('Topic'))
296 
297  firstlast = forms.CharField(max_length=127,
298  widget=forms.TextInput(attrs=attrs_dict),
299  label=_('First and last name'))
300 
301  email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=255)),
302  label=_('Your email address'))
303 
304  issue = forms.CharField(widget=forms.Textarea(attrs=dict(attrs_dict, rows=5, maxlength=2048)),
305  label=_('Describe your issue'))
306 
307  def __init__(self, *args, **kwargs):
308  super(HelpForm, self).__init__(*args, **kwargs)
309 
310 
311 ##
312 #
313 # Class for <b>user data edition</b> form.
314 #
315 class AccountDataEditAdminCLM(forms.Form):
316  first = forms.CharField(max_length=63,
317  widget=forms.TextInput(),
318  label=_("First name"),
319  required=False)
320  last = forms.CharField(max_length=63,
321  widget=forms.TextInput(),
322  label=_("Last name"),
323  required=False)
324  email = forms.EmailField(widget=forms.TextInput(attrs=dict(maxlength=255)),
325  label=_("Email address"))
326  organization = forms.CharField(max_length=63,
327  widget=forms.TextInput(),
328  label=_("Organization"))
329 
330  def __init__(self, *args, **kwargs):
331  try:
332  self.old_email = args[0]['email']
333  except Exception:
334  self.old_email = kwargs['data']['email']
335  super(AccountDataEditAdminCLM, self).__init__(*args, **kwargs)
336 
337 
338 ##
339 #
340 # Class for <b>login to CM admin's panel</b> form.
341 #
342 class CMAuthenticationForm(forms.Form):
343  password = forms.RegexField(regex=regexp['password'],
344  max_length=255,
345  label=_("Password"),
346  widget=forms.PasswordInput(attrs={'tabindex': '1', 'class': 'required'}),
347  error_messages={'invalid': regexp_text['password']})
348 
349  def __init__(self, request=None, *args, **kwargs):
350  self.request = request
351  rest_data = kwargs.pop('rest_data')
352  super(CMAuthenticationForm, self).__init__(*args, **kwargs)
353 
354  self.fields['cm'] = forms.ChoiceField(choices=parsing.parse_cm_list(rest_data),
355  initial=request.session['user'].default_cluster_id,
356  widget=SelectWithDisabled(attrs=dict({'class': 'small'})),
357  label=_("Cluster Manager"))
358  self.fields.keyOrder = ['cm', 'password']
359 
360  ##
361  #
362  # Cast 'cm' to int.
363  #
364  def clean_cm(self):
365  return int(self.cleaned_data['cm'])
366 
367  ##
368  #
369  # Checks cm password.
370  #
371  def clean(self):
372  self.cleaned_data['password'] = hashlib.sha1(self.cleaned_data['password']).hexdigest()
373 
374  password = self.cleaned_data['password']
375  cm = self.cleaned_data['cm']
376 
377  if password and not cm_authenticate(self.request.session['user'], password, cm):
378  raise forms.ValidationError(_('Please enter a correct password. Note that password field is case-sensitive.'))
379 
380  return self.cleaned_data
381 
382 
383 ##
384 #
385 # Class for <b>quota's change</b> form.
386 #
387 class ChangeQuotaForm(forms.Form):
388  cpu = forms.IntegerField(label=_("Cpu Total"))
389  memory = forms.IntegerField(label=_("Memory Total [MB]"))
390  storage = forms.IntegerField(label=_("Storage Total [MB]"))
391  public_ip = forms.IntegerField(min_value=0, label=_("Public IPs Total"))
392  points = forms.IntegerField(min_value=0, label=_("Points"))
393 
394 
395 ##
396 #
397 # Class for <b>quota's change</b> form.
398 #
399 class MultipleChangeQuotaForm(forms.Form):
400  cpu = forms.IntegerField(label=_("Cpu Total"), required=False)
401  memory = forms.IntegerField(label=_("Memory Total [MB]"), required=False)
402  storage = forms.IntegerField(label=_("Storage Total [MB]"), required=False)
403  public_ip = forms.IntegerField(min_value=0, label=_("Public IPs Total"), required=False)
404  points = forms.IntegerField(min_value=0, label=_("Points"), required=False)
405 
406 
407 ##
408 #
409 # Class for <b>moving image</b> form.
410 #
411 class CopyToUserForm(forms.Form):
412  def __init__(self, *args, **kwargs):
413  rest_data = kwargs.pop('rest_data')
414  super(CopyToUserForm, self).__init__(*args, **kwargs)
415  self.fields['dest_user_id'] = forms.ChoiceField(choices=parsing.parse_cm_users(rest_data),
416  initial=0,
417  label=_("User"))
418