models.py:Affiliation field removed. NOTE: DB MIGRATION or FLUSH needed
[myslice.git] / portal / models.py
1 # -*- coding: utf-8 -*-
2 #
3 # portal/models.py: models for the portal application
4 # This file is part of the Manifold project.
5 #
6 # Authors:
7 #   Jordan AugĂ© <jordan.auge@lip6.fr>
8 # Copyright 2013, UPMC Sorbonne UniversitĂ©s / LIP6
9 #
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.
13
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
17 # details.
18
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.
22
23 import datetime
24 import hashlib
25 import random
26 import re
27
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
34
35 #from django.core.validators import validate_email
36
37 try:
38     from django.contrib.auth import get_user_model
39     User = get_user_model()
40 except ImportError:
41     from django.contrib.auth.models import User
42
43 try:
44     from django.utils.timezone import now as datetime_now
45 except ImportError:
46     datetime_now = datetime.datetime.now
47
48 SHA1_RE = re.compile('^[a-f0-9]{40}$')
49
50 # Create your models here.
51
52 class Institution(models.Model):
53     name = models.TextField()
54     # list of associated email domains 
55
56 # code borrowed from django-registration
57 # https://bitbucket.org/ubernostrum/django-registration/
58
59 #DEPRECATED
60 #class RegistrationManager(models.Manager):
61 #    """
62 #    Custom manager for the ``RegistrationProfile`` model.
63 #    
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.
67 #    
68 #    """
69 #    def activate_user(self, activation_key):
70 #        """
71 #        Validate an activation key and activate the corresponding
72 #        ``User`` if valid.
73 #        
74 #        If the key is valid and has not expired, return the ``User``
75 #        after activating.
76 #        
77 #        If the key is not valid or has expired, return ``False``.
78 #        
79 #        If the key is valid but the ``User`` is already active,
80 #        return ``False``.
81 #        
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.
86 #
87 #        """
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
90 #        # the database.
91 #        if SHA1_RE.search(activation_key):
92 #            try:
93 #                profile = self.get(activation_key=activation_key)
94 #            except self.model.DoesNotExist:
95 #                return False
96 #            if not profile.activation_key_expired():
97 #                user = profile.user
98 #                user.is_active = True
99 #                user.save()
100 #                profile.activation_key = self.model.ACTIVATED
101 #                profile.save()
102 #                return user
103 #        return False
104 #    
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
108 #
109 #    def create_inactive_user(self, first_name, last_name, email, password, site,
110 #                             send_email=True):
111 #        """
112 #        Create a new, inactive ``User``, generate a
113 #        ``RegistrationProfile`` and email its activation key to the
114 #        ``User``, returning the new ``User``.
115 #
116 #        By default, an activation email will be sent to the new
117 #        user. To disable this, pass ``send_email=False``.
118 #        
119 #        """
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()
124 #
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
128 #        new_user.save()
129 #
130 #        # We might not need this
131 #        #registration_profile = self.create_profile(new_user)
132 #
133 #        if send_email:
134 #            new_user.send_activation_email(site)
135 #            #registration_profile.send_activation_email(site)
136 #
137 #        return new_user
138 #    create_inactive_user = transaction.commit_on_success(create_inactive_user)
139 #
140 #    def create_profile(self, user):
141 #        """
142 #        Create a ``RegistrationProfile`` for a given
143 #        ``User``, and return the ``RegistrationProfile``.
144 #        
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.
148 #        
149 #        """
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)
157 #        
158 #    def delete_expired_users(self):
159 #        """
160 #        Remove expired instances of ``RegistrationProfile`` and their
161 #        associated ``User``s.
162 #        
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.
169 #        
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``.
174 #        
175 #        Regularly clearing out accounts which have never been
176 #        activated serves two useful purposes:
177 #        
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.
184 #        
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.
190 #        
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
195 #        be deleted.
196 #        
197 #        """
198 #        for profile in self.all():
199 #            try:
200 #                if profile.activation_key_expired():
201 #                    user = profile.user
202 #                    if not user.is_active:
203 #                        user.delete()
204 #                        profile.delete()
205 #            except User.DoesNotExist:
206 #                profile.delete()
207 #DEPRECATED
208
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()
218     # institution
219     authority_hrn = models.TextField()
220     # models.ForeignKey(Institution)
221 #DEPRECATED
222 #    objects = RegistrationManager()
223 #
224 #    class Meta:
225 #        verbose_name = _('registration profile')
226 #        verbose_name_plural = _('registration profiles')
227 #    
228 #    def __unicode__(self):
229 #        return u"Registration information for %s" % self.email
230 #
231 #    def activation_key_expired(self):
232 #        """
233 #        Determine whether this ``RegistrationProfile``'s activation
234 #        key has expired, returning a boolean -- ``True`` if the key
235 #        has expired.
236 #        
237 #        Key expiration is determined by a two-step process:
238 #        
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
242 #           this case.
243 #
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``.
251 #        
252 #        """
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
257 #
258 #    def send_activation_email(self, site):
259 #        """
260 #        Send an activation email to the user associated with this
261 #        ``RegistrationProfile``.
262 #        
263 #        The activation email will make use of two templates:
264 #
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.
271 #
272 #        ``user_register_email.txt``
273 #            This template will be used for the body of the email.
274 #
275 #        These templates will each receive the following context
276 #        variables:
277 #
278 #        ``activation_key``
279 #            The activation key for the new account.
280 #
281 #        ``expiration_days``
282 #            The number of days remaining during which the account may
283 #            be activated.
284 #
285 #        ``site``
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.
294 #
295 #        """
296 #        ctx_dict = {'activation_key': self.activation_key,
297 #                    'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
298 #                    'site': site}
299 #        subject = render_to_string('user_register_email_subject.txt',
300 #                                   ctx_dict)
301 #        # Email subject *must not* contain newlines
302 #        subject = ''.join(subject.splitlines())
303 #
304 #        message = render_to_string('user_register_email.txt',
305 #                                   ctx_dict)
306 #
307 #        send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [self.email])
308 #DEPRECATED
309
310
311
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')