|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
from __future__ import unicode_literals |
|
3
|
|
|
""" |
|
4
|
|
|
Default registration backend class |
|
5
|
|
|
|
|
6
|
|
|
This is a modification of django-registration_ ``admin.py`` |
|
7
|
|
|
The original code is written by James Bennett |
|
8
|
|
|
|
|
9
|
|
|
.. _django-registration: https://bitbucket.org/ubernostrum/django-registration |
|
10
|
|
|
|
|
11
|
|
|
Original License:: |
|
12
|
|
|
|
|
13
|
|
|
Copyright (c) 2007-2011, James Bennett |
|
14
|
|
|
All rights reserved. |
|
15
|
|
|
|
|
16
|
|
|
Redistribution and use in source and binary forms, with or without |
|
17
|
|
|
modification, are permitted provided that the following conditions are |
|
18
|
|
|
met: |
|
19
|
|
|
|
|
20
|
|
|
* Redistributions of source code must retain the above copyright |
|
21
|
|
|
notice, this list of conditions and the following disclaimer. |
|
22
|
|
|
* Redistributions in binary form must reproduce the above |
|
23
|
|
|
copyright notice, this list of conditions and the following |
|
24
|
|
|
disclaimer in the documentation and/or other materials provided |
|
25
|
|
|
with the distribution. |
|
26
|
|
|
* Neither the name of the author nor the names of other |
|
27
|
|
|
contributors may be used to endorse or promote products derived |
|
28
|
|
|
from this software without specific prior written permission. |
|
29
|
|
|
|
|
30
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
31
|
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
32
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
33
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
34
|
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
35
|
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
36
|
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
37
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
38
|
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
39
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
40
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
41
|
|
|
|
|
42
|
|
|
""" |
|
43
|
|
|
__author__ = 'Alisue <[email protected]>' |
|
44
|
|
|
import sys |
|
45
|
|
|
from django.core.urlresolvers import reverse |
|
46
|
|
|
|
|
47
|
|
|
from registration import signals |
|
48
|
|
|
from registration.conf import settings |
|
49
|
|
|
from registration.backends.base import RegistrationBackendBase |
|
50
|
|
|
from registration.models import RegistrationProfile |
|
51
|
|
|
from registration.forms import ActivationForm |
|
52
|
|
|
from registration.forms import RegistrationForm |
|
53
|
|
|
from registration.supplements import get_supplement_class |
|
54
|
|
|
|
|
55
|
|
|
|
|
56
|
|
|
class DefaultRegistrationBackend(RegistrationBackendBase): |
|
57
|
|
|
|
|
58
|
|
|
"""Default registration backend class |
|
59
|
|
|
|
|
60
|
|
|
A registration backend which floows a simple workflow: |
|
61
|
|
|
|
|
62
|
|
|
1. User sigs up, inactive account with unusable password is created. |
|
63
|
|
|
|
|
64
|
|
|
2. Inspector accept or reject the account registration. |
|
65
|
|
|
|
|
66
|
|
|
3. Email is sent to user with/without activation link (without when |
|
67
|
|
|
rejected) |
|
68
|
|
|
|
|
69
|
|
|
4. User clicks activation link, enter password, account is now active |
|
70
|
|
|
|
|
71
|
|
|
Using this backend requires that |
|
72
|
|
|
|
|
73
|
|
|
* ``registration`` be listed in the ``INSTALLED_APPS`` settings |
|
74
|
|
|
(since this backend makes use of models defined in this application). |
|
75
|
|
|
|
|
76
|
|
|
* ``django.contrib.admin`` be listed in the ``INSTALLED_APPS`` settings |
|
77
|
|
|
|
|
78
|
|
|
* The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying (as an |
|
79
|
|
|
integer) the number of days from acceptance during which a user may |
|
80
|
|
|
activate their account (after that period expires, activation will be |
|
81
|
|
|
disallowed). Default is ``7`` |
|
82
|
|
|
|
|
83
|
|
|
* The creation of the templates |
|
84
|
|
|
|
|
85
|
|
|
- ``registration/registration_email.txt`` |
|
86
|
|
|
- ``registration/registration_email_subject.txt`` |
|
87
|
|
|
- ``registration/acceptance_email.txt`` |
|
88
|
|
|
- ``registration/acceptance_email_subject.txt`` |
|
89
|
|
|
- ``registration/rejection_email.txt`` |
|
90
|
|
|
- ``registration/rejection_email_subject.txt`` |
|
91
|
|
|
- ``registration/activation_email.txt`` |
|
92
|
|
|
- ``registration/activation_email_subject.txt`` |
|
93
|
|
|
|
|
94
|
|
|
Additinally, registration can be temporarily closed by adding the setting |
|
95
|
|
|
``REGISTRATION_OPEN`` and setting it to ``False``. Omitting this setting, |
|
96
|
|
|
or setting it to ``True``, will be imterpreted as meaning that registration |
|
97
|
|
|
is currently open and permitted. |
|
98
|
|
|
|
|
99
|
|
|
Internally, this is accomplished via storing an activation key in an |
|
100
|
|
|
instance of ``registration.models.RegistrationProfile``. See that model and |
|
101
|
|
|
its custom manager for full documentation of its fields and supported |
|
102
|
|
|
operations. |
|
103
|
|
|
|
|
104
|
|
|
""" |
|
105
|
|
|
|
|
106
|
|
|
def register(self, username, email, request, |
|
107
|
|
|
supplement=None, send_email=None): |
|
108
|
|
|
"""register new user with ``username`` and ``email`` |
|
109
|
|
|
|
|
110
|
|
|
Given a username, email address, register a new user account, which |
|
111
|
|
|
will initially be inactive and has unusable password. |
|
112
|
|
|
|
|
113
|
|
|
Along with the new ``User`` object, a new |
|
114
|
|
|
``registration.models.RegistrationProfile`` will be created, tied to |
|
115
|
|
|
that ``User``, containing the inspection status and activation key |
|
116
|
|
|
which will be used for this account (activation key is not generated |
|
117
|
|
|
untill its inspection status is set to ``accepted``) |
|
118
|
|
|
|
|
119
|
|
|
An email will be sent to the supplied email address; The email will be |
|
120
|
|
|
rendered using two templates. See the documentation for |
|
121
|
|
|
``RegistrationProfile.send_registration_email()`` for information about |
|
122
|
|
|
these templates and the contexts provided to them. |
|
123
|
|
|
|
|
124
|
|
|
If ``REGISTRATION_REGISTRATION_EMAIL`` of settings is ``None``, no |
|
125
|
|
|
registration email will be sent. |
|
126
|
|
|
|
|
127
|
|
|
After the ``User`` and ``RegistrationProfile`` are created and the |
|
128
|
|
|
registration email is sent, the signal |
|
129
|
|
|
``registration.signals.user_registered`` will be sent, with the new |
|
130
|
|
|
``User`` as the keyword argument ``user``, the ``RegistrationProfile`` |
|
131
|
|
|
of the new ``User`` as the keyword argument ``profile`` and the class |
|
132
|
|
|
of this backend as the sender. |
|
133
|
|
|
|
|
134
|
|
|
""" |
|
135
|
|
|
if send_email is None: |
|
136
|
|
|
send_email = settings.REGISTRATION_REGISTRATION_EMAIL |
|
137
|
|
|
|
|
138
|
|
|
new_user = RegistrationProfile.objects.register( |
|
139
|
|
|
username, email, self.get_site(request), |
|
140
|
|
|
send_email=send_email, |
|
141
|
|
|
) |
|
142
|
|
|
profile = new_user.registration_profile |
|
143
|
|
|
|
|
144
|
|
|
if supplement: |
|
145
|
|
|
supplement.registration_profile = profile |
|
146
|
|
|
supplement.save() |
|
147
|
|
|
|
|
148
|
|
|
signals.user_registered.send( |
|
149
|
|
|
sender=self.__class__, |
|
150
|
|
|
user=new_user, |
|
151
|
|
|
profile=new_user.registration_profile, |
|
152
|
|
|
request=request, |
|
153
|
|
|
) |
|
154
|
|
|
|
|
155
|
|
|
return new_user |
|
156
|
|
|
|
|
157
|
|
|
def accept(self, profile, request, send_email=None, message=None, |
|
158
|
|
|
force=False): |
|
159
|
|
|
"""accept the account registration of ``profile`` |
|
160
|
|
|
|
|
161
|
|
|
Given a profile, accept account registration, which will |
|
162
|
|
|
set inspection status of ``profile`` to ``accepted`` and generate new |
|
163
|
|
|
activation key of ``profile``. |
|
164
|
|
|
|
|
165
|
|
|
An email will be sent to the supplied email address; The email will be |
|
166
|
|
|
rendered using two templates. See the documentation for |
|
167
|
|
|
``RegistrationProfile.send_acceptance_email()`` for information about |
|
168
|
|
|
these templates and the contexts provided to them. |
|
169
|
|
|
|
|
170
|
|
|
If ``REGISTRATION_acceptance_EMAIL`` of settings is ``None``, no |
|
171
|
|
|
acceptance email will be sent. |
|
172
|
|
|
|
|
173
|
|
|
After successful acceptance, the signal |
|
174
|
|
|
``registration.signals.user_accepted`` will be sent, with the newly |
|
175
|
|
|
accepted ``User`` as the keyword argument ``uesr``, the |
|
176
|
|
|
``RegistrationProfile`` of the ``User`` as the keyword argument |
|
177
|
|
|
``profile`` and the class of this backend as the sender |
|
178
|
|
|
|
|
179
|
|
|
""" |
|
180
|
|
|
if send_email is None: |
|
181
|
|
|
send_email = settings.REGISTRATION_ACCEPTANCE_EMAIL |
|
182
|
|
|
|
|
183
|
|
|
accepted_user = RegistrationProfile.objects.accept_registration( |
|
184
|
|
|
profile, self.get_site(request), |
|
185
|
|
|
send_email=send_email, message=message, |
|
186
|
|
|
force=force, |
|
187
|
|
|
) |
|
188
|
|
|
|
|
189
|
|
|
if accepted_user: |
|
190
|
|
|
signals.user_accepted.send( |
|
191
|
|
|
sender=self.__class__, |
|
192
|
|
|
user=accepted_user, |
|
193
|
|
|
profile=profile, |
|
194
|
|
|
request=request, |
|
195
|
|
|
) |
|
196
|
|
|
|
|
197
|
|
|
return accepted_user |
|
198
|
|
|
|
|
199
|
|
|
def reject(self, profile, request, send_email=None, message=None): |
|
200
|
|
|
"""reject the account registration of ``profile`` |
|
201
|
|
|
|
|
202
|
|
|
Given a profile, reject account registration, which will |
|
203
|
|
|
set inspection status of ``profile`` to ``rejected`` and delete |
|
204
|
|
|
activation key of ``profile`` if exists. |
|
205
|
|
|
|
|
206
|
|
|
An email will be sent to the supplied email address; The email will be |
|
207
|
|
|
rendered using two templates. See the documentation for |
|
208
|
|
|
``RegistrationProfile.send_rejection_email()`` for information about |
|
209
|
|
|
these templates and the contexts provided to them. |
|
210
|
|
|
|
|
211
|
|
|
If ``REGISTRATION_REJECTION_EMAIL`` of settings is ``None``, no |
|
212
|
|
|
rejection email will be sent. |
|
213
|
|
|
|
|
214
|
|
|
After successful rejection, the signal |
|
215
|
|
|
``registration.signals.user_rejected`` will be sent, with the newly |
|
216
|
|
|
rejected ``User`` as the keyword argument ``uesr``, the |
|
217
|
|
|
``RegistrationProfile`` of the ``User`` as the keyword argument |
|
218
|
|
|
``profile`` and the class of this backend as the sender |
|
219
|
|
|
|
|
220
|
|
|
""" |
|
221
|
|
|
if send_email is None: |
|
222
|
|
|
send_email = settings.REGISTRATION_REJECTION_EMAIL |
|
223
|
|
|
|
|
224
|
|
|
rejected_user = RegistrationProfile.objects.reject_registration( |
|
225
|
|
|
profile, self.get_site(request), |
|
226
|
|
|
send_email=send_email, message=message) |
|
227
|
|
|
|
|
228
|
|
|
if rejected_user: |
|
229
|
|
|
signals.user_rejected.send( |
|
230
|
|
|
sender=self.__class__, |
|
231
|
|
|
user=rejected_user, |
|
232
|
|
|
profile=profile, |
|
233
|
|
|
request=request, |
|
234
|
|
|
) |
|
235
|
|
|
|
|
236
|
|
|
return rejected_user |
|
237
|
|
|
|
|
238
|
|
|
def activate(self, activation_key, request, password=None, send_email=None, |
|
239
|
|
|
message=None, no_profile_delete=False): |
|
240
|
|
|
"""activate user with ``activation_key`` and ``password`` |
|
241
|
|
|
|
|
242
|
|
|
Given an activation key, password, look up and activate the user |
|
243
|
|
|
account corresponding to that key (if possible) and set its password. |
|
244
|
|
|
|
|
245
|
|
|
If ``password`` is not given, password will be generated |
|
246
|
|
|
|
|
247
|
|
|
An email will be sent to the supplied email address; The email will be |
|
248
|
|
|
rendered using two templates. See the documentation for |
|
249
|
|
|
``RegistrationProfile.send_activation_email()`` for information about |
|
250
|
|
|
these templates and the contexts provided to them. |
|
251
|
|
|
|
|
252
|
|
|
If ``REGISTRATION_ACTIVATION_EMAIL`` of settings is ``None``, no |
|
253
|
|
|
activation email will be sent. |
|
254
|
|
|
|
|
255
|
|
|
After successful activation, the signal |
|
256
|
|
|
``registration.signals.user_activated`` will be sent, with the newly |
|
257
|
|
|
activated ``User`` as the keyword argument ``uesr``, the password |
|
258
|
|
|
of the ``User`` as the keyword argument ``password``, whether the |
|
259
|
|
|
password has generated or not as the keyword argument ``is_generated`` |
|
260
|
|
|
and the class of this backend as the sender |
|
261
|
|
|
|
|
262
|
|
|
""" |
|
263
|
|
|
if send_email is None: |
|
264
|
|
|
send_email = settings.REGISTRATION_ACTIVATION_EMAIL |
|
265
|
|
|
|
|
266
|
|
|
activated = RegistrationProfile.objects.activate_user( |
|
267
|
|
|
activation_key=activation_key, |
|
268
|
|
|
site=self.get_site(request), |
|
269
|
|
|
password=password, |
|
270
|
|
|
send_email=send_email, |
|
271
|
|
|
message=message, |
|
272
|
|
|
no_profile_delete=no_profile_delete) |
|
273
|
|
|
|
|
274
|
|
|
if activated: |
|
275
|
|
|
user, password, is_generated = activated |
|
276
|
|
|
signals.user_activated.send( |
|
277
|
|
|
sender=self.__class__, |
|
278
|
|
|
user=user, |
|
279
|
|
|
password=password, |
|
280
|
|
|
is_generated=is_generated, |
|
281
|
|
|
request=request, |
|
282
|
|
|
) |
|
283
|
|
|
return user |
|
284
|
|
|
return None |
|
285
|
|
|
|
|
286
|
|
|
def get_supplement_class(self): |
|
287
|
|
|
"""Return the current registration supplement class""" |
|
288
|
|
|
# cache mechanisms will break the test thus disable it in test |
|
289
|
|
|
if not hasattr(self, '_supplement_class_cache') or 'test' in sys.argv: |
|
290
|
|
|
cls = get_supplement_class() |
|
291
|
|
|
setattr(self, '_supplement_class_cache', cls) |
|
292
|
|
|
return getattr(self, '_supplement_class_cache') |
|
293
|
|
|
|
|
294
|
|
|
def get_activation_form_class(self): |
|
295
|
|
|
"""Return the default form class used for user activation""" |
|
296
|
|
|
return ActivationForm |
|
297
|
|
|
|
|
298
|
|
|
def get_registration_form_class(self): |
|
299
|
|
|
"""Return the default form class used for user registration""" |
|
300
|
|
|
return RegistrationForm |
|
301
|
|
|
|
|
302
|
|
|
def get_supplement_form_class(self): |
|
303
|
|
|
""" |
|
304
|
|
|
Return the default form class used for user registration supplement |
|
305
|
|
|
""" |
|
306
|
|
|
supplement_class = self.get_supplement_class() |
|
307
|
|
|
if not supplement_class: |
|
308
|
|
|
return None |
|
309
|
|
|
return supplement_class.get_form_class() |
|
310
|
|
|
|
|
311
|
|
|
def get_activation_complete_url(self, user): |
|
312
|
|
|
"""Return a url to redirect to after successful user activation""" |
|
313
|
|
|
return reverse('registration_activation_complete') |
|
314
|
|
|
|
|
315
|
|
|
def get_registration_complete_url(self, user): |
|
316
|
|
|
"""Return a url to redirect to after successful user registration""" |
|
317
|
|
|
return reverse('registration_complete') |
|
318
|
|
|
|
|
319
|
|
|
def get_registration_closed_url(self): |
|
320
|
|
|
"""Return a url to redirect to if registration is closed""" |
|
321
|
|
|
return reverse('registration_disallowed') |
|
322
|
|
|
|
|
323
|
|
|
def registration_allowed(self): |
|
324
|
|
|
""" |
|
325
|
|
|
Indicate whether account registration is currently permitted, based on |
|
326
|
|
|
the value of the setting ``REGISTRATION_OEPN``. This is determined as |
|
327
|
|
|
follows: |
|
328
|
|
|
|
|
329
|
|
|
* If ``REGISTRATION_OPEN`` is not specified in settings, or is set |
|
330
|
|
|
to ``True``, registration is permitted. |
|
331
|
|
|
|
|
332
|
|
|
* If ``REGISTRATION_OPEN`` is both specified and set to ``False``, |
|
333
|
|
|
registration is not permitted. |
|
334
|
|
|
|
|
335
|
|
|
""" |
|
336
|
|
|
return getattr(settings, 'REGISTRATION_OPEN', True) |
|
337
|
|
|
|