1 # -*- coding: utf-8 -*-
3 # portal/models.py: models for the portal application
4 # This file is part of the Manifold project.
7 # Jordan Augé <jordan.auge@lip6.fr>
8 # Copyright 2013, UPMC Sorbonne Universités / LIP6
10 # This program is free software; you can redistribute it and/or modify it under
11 # the terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 3, or (at your option) any later version.
14 # This program is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 # You should have received a copy of the GNU General Public License along with
20 # this program; see the file COPYING. If not, write to the Free Software
21 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 from django.conf import settings
29 from django.core.mail import send_mail
30 from django.db import models
31 from django.db import transaction
32 from django.utils.translation import ugettext_lazy as _
33 from django.template.loader import render_to_string
35 #from django.core.validators import validate_email
38 from django.contrib.auth import get_user_model
39 User = get_user_model()
41 from django.contrib.auth.models import User
44 from django.utils.timezone import now as datetime_now
46 datetime_now = datetime.datetime.now
48 SHA1_RE = re.compile('^[a-f0-9]{40}$')
50 # Create your models here.
52 class Institution(models.Model):
53 name = models.TextField()
54 # list of associated email domains
56 # code borrowed from django-registration
57 # https://bitbucket.org/ubernostrum/django-registration/
60 #class RegistrationManager(models.Manager):
62 # Custom manager for the ``RegistrationProfile`` model.
64 # The methods defined here provide shortcuts for account creation
65 # and activation (including generation and emailing of activation
66 # keys), and for cleaning out expired inactive accounts.
69 # def activate_user(self, activation_key):
71 # Validate an activation key and activate the corresponding
74 # If the key is valid and has not expired, return the ``User``
77 # If the key is not valid or has expired, return ``False``.
79 # If the key is valid but the ``User`` is already active,
82 # To prevent reactivation of an account which has been
83 # deactivated by site administrators, the activation key is
84 # reset to the string constant ``RegistrationProfile.ACTIVATED``
85 # after successful activation.
88 # # Make sure the key we're trying conforms to the pattern of a
89 # # SHA1 hash; if it doesn't, no point trying to look it up in
91 # if SHA1_RE.search(activation_key):
93 # profile = self.get(activation_key=activation_key)
94 # except self.model.DoesNotExist:
96 # if not profile.activation_key_expired():
98 # user.is_active = True
100 # profile.activation_key = self.model.ACTIVATED
105 # def create_user(self, first_name, last_name, email, password):
106 # pending_user = self.create(first_name=first_name, last_name=last_name, email=email, password=password)
107 # return pending_user
109 # def create_inactive_user(self, first_name, last_name, email, password, site,
112 # Create a new, inactive ``User``, generate a
113 # ``RegistrationProfile`` and email its activation key to the
114 # ``User``, returning the new ``User``.
116 # By default, an activation email will be sent to the new
117 # user. To disable this, pass ``send_email=False``.
120 # salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
121 # if isinstance(email, unicode):
122 # email = email.encode('utf-8')
123 # activation_key = hashlib.sha1(salt+email).hexdigest()
125 # new_user = PendingUser.objects.create_user(first_name, last_name, email, password)
126 # new_user.is_active = False
127 # new_user.activation_key=activation_key
130 # # We might not need this
131 # #registration_profile = self.create_profile(new_user)
134 # new_user.send_activation_email(site)
135 # #registration_profile.send_activation_email(site)
138 # create_inactive_user = transaction.commit_on_success(create_inactive_user)
140 # def create_profile(self, user):
142 # Create a ``RegistrationProfile`` for a given
143 # ``User``, and return the ``RegistrationProfile``.
145 # The activation key for the ``RegistrationProfile`` will be a
146 # SHA1 hash, generated from a combination of the ``User``'s
147 # username and a random salt.
150 # salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
151 # username = user.username
152 # if isinstance(username, unicode):
153 # username = username.encode('utf-8')
154 # activation_key = hashlib.sha1(salt+username).hexdigest()
155 # return self.create(user=user,
156 # activation_key=activation_key)
158 # def delete_expired_users(self):
160 # Remove expired instances of ``RegistrationProfile`` and their
161 # associated ``User``s.
163 # Accounts to be deleted are identified by searching for
164 # instances of ``RegistrationProfile`` with expired activation
165 # keys, and then checking to see if their associated ``User``
166 # instances have the field ``is_active`` set to ``False``; any
167 # ``User`` who is both inactive and has an expired activation
168 # key will be deleted.
170 # It is recommended that this method be executed regularly as
171 # part of your routine site maintenance; this application
172 # provides a custom management command which will call this
173 # method, accessible as ``manage.py cleanupregistration``.
175 # Regularly clearing out accounts which have never been
176 # activated serves two useful purposes:
178 # 1. It alleviates the ocasional need to reset a
179 # ``RegistrationProfile`` and/or re-send an activation email
180 # when a user does not receive or does not act upon the
181 # initial activation email; since the account will be
182 # deleted, the user will be able to simply re-register and
183 # receive a new activation key.
185 # 2. It prevents the possibility of a malicious user registering
186 # one or more accounts and never activating them (thus
187 # denying the use of those usernames to anyone else); since
188 # those accounts will be deleted, the usernames will become
189 # available for use again.
191 # If you have a troublesome ``User`` and wish to disable their
192 # account while keeping it in the database, simply delete the
193 # associated ``RegistrationProfile``; an inactive ``User`` which
194 # does not have an associated ``RegistrationProfile`` will not
198 # for profile in self.all():
200 # if profile.activation_key_expired():
201 # user = profile.user
202 # if not user.is_active:
205 # except User.DoesNotExist:
209 class PendingUser(models.Model):
210 # NOTE We might consider migrating the fields to CharField, which would
211 # simplify form creation in forms.py
212 first_name = models.TextField()
213 last_name = models.TextField()
214 # affiliation = models.TextField()
215 email = models.EmailField() #validators=[validate_email])
216 password = models.TextField()
217 keypair = models.TextField()
219 authority_hrn = models.TextField()
220 # models.ForeignKey(Institution)
222 # objects = RegistrationManager()
225 # verbose_name = _('registration profile')
226 # verbose_name_plural = _('registration profiles')
228 # def __unicode__(self):
229 # return u"Registration information for %s" % self.email
231 # def activation_key_expired(self):
233 # Determine whether this ``RegistrationProfile``'s activation
234 # key has expired, returning a boolean -- ``True`` if the key
237 # Key expiration is determined by a two-step process:
239 # 1. If the user has already activated, the key will have been
240 # reset to the string constant ``ACTIVATED``. Re-activating
241 # is not permitted, and so this method returns ``True`` in
244 # 2. Otherwise, the date the user signed up is incremented by
245 # the number of days specified in the setting
246 # ``ACCOUNT_ACTIVATION_DAYS`` (which should be the number of
247 # days after signup during which a user is allowed to
248 # activate their account); if the result is less than or
249 # equal to the current date, the key has expired and this
250 # method returns ``True``.
253 # expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
254 # return self.activation_key == self.ACTIVATED or \
255 # (self.user.date_joined + expiration_date <= datetime_now())
256 # activation_key_expired.boolean = True
258 # def send_activation_email(self, site):
260 # Send an activation email to the user associated with this
261 # ``RegistrationProfile``.
263 # The activation email will make use of two templates:
265 # ``user_register_email_subject.txt``
266 # This template will be used for the subject line of the
267 # email. Because it is used as the subject line of an email,
268 # this template's output **must** be only a single line of
269 # text; output longer than one line will be forcibly joined
270 # into only a single line.
272 # ``user_register_email.txt``
273 # This template will be used for the body of the email.
275 # These templates will each receive the following context
279 # The activation key for the new account.
281 # ``expiration_days``
282 # The number of days remaining during which the account may
286 # An object representing the site on which the user
287 # registered; depending on whether ``django.contrib.sites``
288 # is installed, this may be an instance of either
289 # ``django.contrib.sites.models.Site`` (if the sites
290 # application is installed) or
291 # ``django.contrib.sites.models.RequestSite`` (if
292 # not). Consult the documentation for the Django sites
293 # framework for details regarding these objects' interfaces.
296 # ctx_dict = {'activation_key': self.activation_key,
297 # 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
299 # subject = render_to_string('user_register_email_subject.txt',
301 # # Email subject *must not* contain newlines
302 # subject = ''.join(subject.splitlines())
304 # message = render_to_string('user_register_email.txt',
307 # send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [self.email])
312 class PendingSlice(models.Model):
313 slice_name = models.TextField()
314 authority_hrn = models.TextField(null=True)
315 number_of_nodes = models.TextField(default=0)
316 type_of_nodes = models.TextField(default='NA')
317 purpose = models.TextField(default='NA')