Statistics
| Branch: | Tag: | Revision:

root / astakos / im / models.py @ ca96a346

History | View | Annotate | Download (5.9 kB)

1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
# 
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
# 
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
# 
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
# 
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import hashlib
35
import uuid
36

    
37
from time import asctime
38
from datetime import datetime, timedelta
39
from base64 import b64encode
40

    
41
from django.db import models
42
from django.contrib.auth.models import User, UserManager
43

    
44
from astakos.im.interface import get_quota, set_quota
45
from astakos.im.settings import DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL, AUTH_TOKEN_DURATION
46

    
47
class AstakosUser(User):
48
    """
49
    Extends ``django.contrib.auth.models.User`` by defining additional fields.
50
    """
51
    # Use UserManager to get the create_user method, etc.
52
    objects = UserManager()
53
    
54
    affiliation = models.CharField('Affiliation', max_length=255, blank=True)
55
    provider = models.CharField('Provider', max_length=255, blank=True)
56
    
57
    #for invitations
58
    user_level = DEFAULT_USER_LEVEL
59
    level = models.IntegerField('Inviter level', default=user_level)
60
    invitations = models.IntegerField('Invitations left', default=INVITATIONS_PER_LEVEL[user_level])
61
    
62
    auth_token = models.CharField('Authentication Token', max_length=32,
63
                                  null=True, blank=True)
64
    auth_token_created = models.DateTimeField('Token creation date', null=True)
65
    auth_token_expires = models.DateTimeField('Token expiration date', null=True)
66
    
67
    updated = models.DateTimeField('Update date')
68
    is_verified = models.BooleanField('Is verified?', default=False)
69
    
70
    # ex. screen_name for twitter, eppn for shibboleth
71
    third_party_identifier = models.CharField('Third-party identifier', max_length=255, null=True, blank=True)
72
    
73
    @property
74
    def realname(self):
75
        return '%s %s' %(self.first_name, self.last_name)
76
    
77
    @realname.setter
78
    def realname(self, value):
79
        parts = value.split(' ')
80
        if len(parts) == 2:
81
            self.first_name = parts[0]
82
            self.last_name = parts[1]
83
        else:
84
            self.last_name = parts[0]
85
    
86
    @property
87
    def quota(self):
88
        return get_quota(self.username)
89

    
90
    @quota.setter
91
    def quota(self, value):
92
        set_quota(self.username, value)
93
    
94
    @property
95
    def invitation(self):
96
        try:
97
            return Invitation.objects.get(username=self.email)
98
        except Invitation.DoesNotExist:
99
            return None
100
    
101
    def save(self, update_timestamps=True, **kwargs):
102
        if update_timestamps:
103
            if not self.id:
104
                # set username
105
                while not self.username:
106
                    username =  uuid.uuid4().hex[:30]
107
                    try:
108
                        AstakosUser.objects.get(username = username)
109
                    except AstakosUser.DoesNotExist, e:
110
                        self.username = username
111
                self.is_active = False
112
                if not self.provider:
113
                    self.provider = 'local'
114
                self.date_joined = datetime.now()
115
            self.updated = datetime.now()
116
        super(AstakosUser, self).save(**kwargs)
117
    
118
    def renew_token(self):
119
        md5 = hashlib.md5()
120
        md5.update(self.username)
121
        md5.update(self.realname.encode('ascii', 'ignore'))
122
        md5.update(asctime())
123
        
124
        self.auth_token = b64encode(md5.digest())
125
        self.auth_token_created = datetime.now()
126
        self.auth_token_expires = self.auth_token_created + \
127
                                  timedelta(hours=AUTH_TOKEN_DURATION)
128
    
129
    def __unicode__(self):
130
        return self.username
131

    
132
class Invitation(models.Model):
133
    """
134
    Model for registring invitations
135
    """
136
    inviter = models.ForeignKey(AstakosUser, related_name='invitations_sent',
137
                                null=True)
138
    realname = models.CharField('Real name', max_length=255)
139
    username = models.CharField('Unique ID', max_length=255)
140
    code = models.BigIntegerField('Invitation code', db_index=True)
141
    #obsolete: we keep it just for transfering the data
142
    is_accepted = models.BooleanField('Accepted?', default=False)
143
    is_consumed = models.BooleanField('Consumed?', default=False)
144
    created = models.DateTimeField('Creation date', auto_now_add=True)
145
    #obsolete: we keep it just for transfering the data
146
    accepted = models.DateTimeField('Acceptance date', null=True, blank=True)
147
    consumed = models.DateTimeField('Consumption date', null=True, blank=True)
148
    
149
    def consume(self):
150
        self.is_consumed = True
151
        self.consumed = datetime.now()
152
        self.save()
153
        
154
    def __unicode__(self):
155
        return '%s -> %s [%d]' % (self.inviter, self.username, self.code)