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.clm.views.guest.user
22 # @author Gaetano
23 # @date May 14, 2013
24 # @alldecoratedby{src.clm.utils.decorators.guest_log}
25 #
26 
27 from datetime import datetime
28 import random
29 from smtplib import SMTPRecipientsRefused
30 import string
31 
32 from django.conf import settings
33 from django.utils.http import int_to_base36
34 
35 from clm.models.cluster import Cluster
36 from clm.models.user import User
37 from clm.utils import mail
38 from clm.utils.cm import CM
39 from clm.utils.decorators import guest_log
40 from clm.utils.exception import CLMException
41 from clm.utils.tokens import default_token_generator as token_generator
42 from common.signature import Signature
43 from common.states import user_active_states, registration_states, \
44  cluster_states
45 
46 
47 @guest_log(log=False)
48 ##
49 #
50 # Checks User password's correctness.
51 #
52 # @clmview_guest
53 # @param_post{login} user's login
54 # @param_post{password} password to check
55 #
56 # @response{bool} False if password isn't correct
57 # @response{dict} User.dict() property if password is correct
58 #
59 def check_password(login, password):
60  try:
61  user = User.objects.get(login=login)
62  except User.DoesNotExist:
63  raise CLMException('user_get')
64 
65  if user.is_active == user_active_states['ok']:
66  try:
67  user.last_login_date = datetime.now()
68  user.save()
69  except:
70  raise CLMException('user_edit')
71  else:
72  return False
73 
74  if user.password == password:
75  return user.dict
76  else:
77  return False
78 
79 
80 @guest_log(log=True)
81 ##
82 #
83 # Authenticate S3 request by checking parameters passed by EC2
84 #
85 # @clmview_guest
86 # @param_post{parameters} dict with all S3 request headers
87 #
88 def check_signature(parameters):
89 
90  try:
91  auth_header = parameters['authorization']
92  space = auth_header.index(' ')
93  auth_header = auth_header[space + 1:]
94  login_and_signature = auth_header.split(':')
95 
96  login = login_and_signature[0]
97  user_signature = login_and_signature[1]
98 
99  user = User.objects.get(login=login)
100  except User.DoesNotExist, error:
101  print 'ERROR', error
102  raise CLMException('user_get')
103  except KeyError:
104  raise CLMException('user_parameter')
105 
106  if not Signature.checkSignature(user.password, user_signature, parameters):
107  raise CLMException('user_get')
108  return True
109 
110 
111 @guest_log(log=True)
112 ##
113 #
114 # Registers new user.
115 #
116 # @clmview_guest
117 # @param_post{first,string} firstname to set
118 # @param_post{last,string} lastname to set
119 # @param_post{login,string} login to set
120 # @param_post{email,string} email to set
121 # @param_post{new_password,string} password to set
122 # @param_post{organization,string} organization to set
123 # @param_post{wi_data,dict} data for sending mail
124 #
125 # @response{dict}
126 # @dictkey{user,dict} user's data (User.dict() property)
127 # @dictkey{registration_state,int} state of reqistration @seealso{common.states.registration_state}
128 #
129 def register(first, last, login, email, new_password, organization, wi_data):
130 
131  user = User()
132  user.first = first
133  user.last = last
134  try:
135  default_cluster_id = Cluster.objects.filter(state=cluster_states['ok'])[0].id
136  except:
137  default_cluster_id = None
138 
139  user.default_cluster_id = default_cluster_id
140  user.login = login
141  user.email = email
142  user.password = new_password
143  user.organization = organization
144  user.act_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for n in range(40))
145  user.is_active = user_active_states['inactive']
146 
147  try:
148  user.save()
149  except:
150  raise CLMException('user_register')
151 
152  reg_state = -1
153  if settings.MAILER_ACTIVE:
154  try:
155  # mail the user
156  mail.send_activation_email(user.act_key, user, wi_data)
157  except SMTPRecipientsRefused:
158  reg_state = registration_states['error']
159  reg_state = registration_states['mail_confirmation']
160  else:
161  if settings.AUTOACTIVATION:
162  # add user to all unlocked CMs while activating
163  for cluster in Cluster.objects.filter(state__exact=0):
164  # TODO: func user/user is not in cm! so i use guest/user
165  resp = CM(cluster.id).send_request("guest/user/add/", new_user_id=user.id)
166  if resp['status'] != 'ok':
167  raise CLMException('cm_get')
168 
169  user.is_active = user_active_states['ok']
170  user.activation_date = datetime.now()
171  user.act_key = ''
172 
173  reg_state = registration_states['completed']
174  else:
175  user.is_active = user_active_states['email_confirmed']
176 
177  reg_state = registration_states['admin_confirmation']
178 
179  try:
180  user.save()
181  except:
182  raise CLMException('user_activate')
183 
184  return {'user': user.dict, 'registration_state': reg_state}
185 
186 
187 @guest_log(log=False)
188 ##
189 #
190 # Method check, whether specified @prm{login} already exists.
191 #
192 # @clmview_guest
193 # @param_post{login,string}
194 #
195 # @response{bool) True if @prm{login} is registered
196 # @response{bool) False if @prm{login} isn't registered
197 #
198 def exists(login):
199  return User.objects.filter(login=login).exists()
200 
201 
202 @guest_log(log=False)
203 ##
204 #
205 # Method checks, whether user with specified @prm{email} already exists.
206 #
207 # @clmview_guest
208 # @param_post{email,string}
209 #
210 # @response{bool) True if @prm{email} is registered
211 # @response{bool) False if @prm{email} isn't registered
212 #
213 def email_exists(email):
214  return User.objects.filter(email__exact=email).exists()
215 
216 
217 @guest_log(log=True)
218 ##
219 #
220 # Method activates User with activation key @prm{act_key}.
221 #
222 # @clmview_guest
223 # @param_post{act_key,string}
224 # @param_post{wi_data,string} data for email
225 #
226 # @response{dict} user's data, fields:
227 # @dictkey{user,dict}
228 # @dictkey{registration_state,dict}
229 #
230 def activate(act_key, wi_data):
231  try:
232  user = User.objects.get(act_key=act_key)
233  except:
234  raise CLMException('user_get')
235  user.is_active = user_active_states['email_confirmed']
236  reg_state = registration_states['admin_confirmation']
237  if settings.AUTOACTIVATION:
238  # add user to all unlocked CMs while activating
239  for cluster in Cluster.objects.filter(state__exact=0):
240  # TODO: func user/user is not in cm! so i use guest/user
241  resp = CM(cluster.id).send_request("guest/user/add/", new_user_id=user.id)
242  if resp['status'] != 'ok':
243  raise CLMException('cm_get')
244 
245  user.is_active = user_active_states['ok']
246  reg_state = registration_states['completed']
247 
248  user.activation_date = datetime.now()
249  user.act_key = ''
250  try:
251  user.save()
252  except:
253  raise CLMException('user_activate')
254 
255  if settings.MAILER_ACTIVE and reg_state == registration_states['admin_confirmation']:
256  try:
257  mail.send_admin_registration_notification(user, wi_data)
258  except SMTPRecipientsRefused:
259  pass
260 
261  return {'user': user.dict, 'registration_state': reg_state}
262 
263 
264 @guest_log(log=True)
265 ##
266 #
267 # Info, whether mailer is active
268 #
269 # @clmview_guest
270 # @response{dict} fiedls:
271 # @dictkey{mailer_active}
272 # @dictkey{contact_email}
273 #
274 def is_mailer_active():
275  return {'mailer_active': settings.MAILER_ACTIVE, 'contact_email': settings.CONTACT_EMAIL}
276 
277 
278 @guest_log(log=True)
279 ##
280 #
281 # Sends mail for reseting password
282 #
283 # @clmview_guest
284 # @param_post{email,string} whom send "reset password" mail to
285 # @param_post{wi_data,dict} fields:
286 # @dictkey{site_domain}
287 # @dictkey{site_name}
288 #
289 def reset_password_mail(email, wi_data):
290  if settings.MAILER_ACTIVE:
291  user = User.objects.get(email=email)
292  token = token_generator.make_token(user)
293  try:
294  mail.send_reset_password_mail(user, token, wi_data)
295  return
296  except SMTPRecipientsRefused:
297  raise CLMException('reset_password_smtp_error')
298  raise CLMException('reset_password_error')
299 
300 
301 @guest_log(log=True)
302 ##
303 #
304 # Check password-reset token correctness for User.
305 #
306 # @clmview_guest
307 # @param_post{user_id} User whose token should be checked
308 # @param_post{token} token to check
309 #
310 # @response None
311 #
312 def check_token(user_id, token):
313  try:
314  user = User.objects.get(id=user_id)
315  except Exception:
316  raise CLMException('user_get')
317 
318  if token_generator.check_token(user, int_to_base36(user_id) + u'-' + token):
319  return
320  raise CLMException('user_bad_token')
321 
322 
323 @guest_log(log=True)
324 ##
325 #
326 # Sets new password provided reset-password token is correct.
327 #
328 # @clmview_guest
329 # @param_post{user_id} id of the User whose password should be set
330 # @param_post{token} token to set password
331 # @param_post{new_password,string} new password
332 #
333 # @response{dict} User's new data (if succeeded)
334 #
335 def set_password_token(user_id, token, new_password):
336  try:
337  user = User.objects.get(id=user_id)
338  except Exception:
339  raise CLMException('user_get')
340 
341  if token_generator.check_token(user, int_to_base36(user_id) + u'-' + token):
342  user.password = new_password
343  try:
344  user.save()
345  except Exception:
346  raise CLMException('user_set_password')
347  else:
348  raise CLMException('user_bad_token')
349  return user.dict
350