~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: me at id
  • Date: 2009-01-15 05:45:05 UTC
  • mto: This revision was merged to the branch mainline in revision 1090.
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:branches%2Fstorm:1160
ivle.database.User: Order 'enrolments' the same way as 'active_enrolments'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
# Author: Matt Giuca, Will Grant
 
19
 
 
20
"""
 
21
Database Classes and Utilities for Storm ORM
 
22
 
 
23
This module provides all of the classes which map to database tables.
 
24
It also provides miscellaneous utility functions for database interaction.
 
25
"""
 
26
 
 
27
import md5
 
28
import datetime
 
29
 
 
30
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
 
31
                         Reference, ReferenceSet, Bool, Storm, Desc
 
32
 
 
33
import ivle.conf
 
34
import ivle.caps
 
35
 
 
36
def _kwarg_init(self, **kwargs):
 
37
    for k,v in kwargs.items():
 
38
        if k.startswith('_') or not hasattr(self, k):
 
39
            raise TypeError("%s got an unexpected keyword argument '%s'"
 
40
                % self.__class__.__name__, k)
 
41
        setattr(self, k, v)
 
42
 
 
43
def get_conn_string():
 
44
    """
 
45
    Returns the Storm connection string, generated from the conf file.
 
46
    """
 
47
    return "postgres://%s:%s@%s:%d/%s" % (ivle.conf.db_user,
 
48
        ivle.conf.db_password, ivle.conf.db_host, ivle.conf.db_port,
 
49
        ivle.conf.db_dbname)
 
50
 
 
51
def get_store():
 
52
    """
 
53
    Open a database connection and transaction. Return a storm.store.Store
 
54
    instance connected to the configured IVLE database.
 
55
    """
 
56
    return Store(create_database(get_conn_string()))
 
57
 
 
58
class User(Storm):
 
59
    """
 
60
    Represents an IVLE user.
 
61
    """
 
62
    __storm_table__ = "login"
 
63
 
 
64
    id = Int(primary=True, name="loginid")
 
65
    login = Unicode()
 
66
    passhash = Unicode()
 
67
    state = Unicode()
 
68
    rolenm = Unicode()
 
69
    unixid = Int()
 
70
    nick = Unicode()
 
71
    pass_exp = DateTime()
 
72
    acct_exp = DateTime()
 
73
    last_login = DateTime()
 
74
    svn_pass = Unicode()
 
75
    email = Unicode()
 
76
    fullname = Unicode()
 
77
    studentid = Unicode()
 
78
    settings = Unicode()
 
79
 
 
80
    def _get_role(self):
 
81
        if self.rolenm is None:
 
82
            return None
 
83
        return ivle.caps.Role(self.rolenm)
 
84
    def _set_role(self, value):
 
85
        if not isinstance(value, ivle.caps.Role):
 
86
            raise TypeError("role must be an ivle.caps.Role")
 
87
        self.rolenm = unicode(value)
 
88
    role = property(_get_role, _set_role)
 
89
 
 
90
    __init__ = _kwarg_init
 
91
 
 
92
    def __repr__(self):
 
93
        return "<%s '%s'>" % (type(self).__name__, self.login)
 
94
 
 
95
    def authenticate(self, password):
 
96
        """Validate a given password against this user.
 
97
 
 
98
        Returns True if the given password matches the password hash for this
 
99
        User, False if it doesn't match, and None if there is no hash for the
 
100
        user.
 
101
        """
 
102
        if self.passhash is None:
 
103
            return None
 
104
        return self.hash_password(password) == self.passhash
 
105
 
 
106
    def hasCap(self, capability):
 
107
        """Given a capability (which is a Role object), returns True if this
 
108
        User has that capability, False otherwise.
 
109
        """
 
110
        return self.role.hasCap(capability)
 
111
 
 
112
    @property
 
113
    def password_expired(self):
 
114
        fieldval = self.pass_exp
 
115
        return fieldval is not None and datetime.datetime.now() > fieldval
 
116
 
 
117
    @property
 
118
    def account_expired(self):
 
119
        fieldval = self.acct_exp
 
120
        return fieldval is not None and datetime.datetime.now() > fieldval
 
121
 
 
122
    def _get_enrolments(self, justactive):
 
123
        return Store.of(self).find(Enrolment,
 
124
            Enrolment.user_id == self.id,
 
125
            (Enrolment.active == True) if justactive else True,
 
126
            Enrolment.offering_id == Offering.id,
 
127
            Offering.semester_id == Semester.id,
 
128
            Offering.subject_id == Subject.id).order_by(
 
129
                Desc(Semester.year),
 
130
                Desc(Semester.semester),
 
131
                Desc(Subject.code)
 
132
            )
 
133
 
 
134
    @property
 
135
    def active_enrolments(self):
 
136
        '''A sanely ordered list of the user's active enrolments.'''
 
137
        return self._get_enrolments(True)
 
138
 
 
139
    @property
 
140
    def enrolments(self):
 
141
        '''A sanely ordered list of all of the user's enrolments.'''
 
142
        return self._get_enrolments(False) 
 
143
 
 
144
    @staticmethod
 
145
    def hash_password(password):
 
146
        return md5.md5(password).hexdigest()
 
147
 
 
148
    @classmethod
 
149
    def get_by_login(cls, store, login):
 
150
        """
 
151
        Get the User from the db associated with a given store and
 
152
        login.
 
153
        """
 
154
        return store.find(cls, cls.login == unicode(login)).one()
 
155
 
 
156
class Subject(Storm):
 
157
    __storm_table__ = "subject"
 
158
 
 
159
    id = Int(primary=True, name="subjectid")
 
160
    code = Unicode(name="subj_code")
 
161
    name = Unicode(name="subj_name")
 
162
    short_name = Unicode(name="subj_short_name")
 
163
    url = Unicode()
 
164
 
 
165
    offerings = ReferenceSet(id, 'Offering.subject_id')
 
166
 
 
167
    __init__ = _kwarg_init
 
168
 
 
169
    def __repr__(self):
 
170
        return "<%s '%s'>" % (type(self).__name__, self.short_name)
 
171
 
 
172
class Semester(Storm):
 
173
    __storm_table__ = "semester"
 
174
 
 
175
    id = Int(primary=True, name="semesterid")
 
176
    year = Unicode()
 
177
    semester = Unicode()
 
178
    active = Bool()
 
179
 
 
180
    offerings = ReferenceSet(id, 'Offering.semester_id')
 
181
 
 
182
    __init__ = _kwarg_init
 
183
 
 
184
    def __repr__(self):
 
185
        return "<%s %s/%s>" % (type(self).__name__, self.year, self.semester)
 
186
 
 
187
class Offering(Storm):
 
188
    __storm_table__ = "offering"
 
189
 
 
190
    id = Int(primary=True, name="offeringid")
 
191
    subject_id = Int(name="subject")
 
192
    subject = Reference(subject_id, Subject.id)
 
193
    semester_id = Int(name="semesterid")
 
194
    semester = Reference(semester_id, Semester.id)
 
195
    groups_student_permissions = Unicode()
 
196
 
 
197
    enrolments = ReferenceSet(id, 'Enrolment.offering_id')
 
198
 
 
199
    __init__ = _kwarg_init
 
200
 
 
201
    def __repr__(self):
 
202
        return "<%s %r in %r>" % (type(self).__name__, self.subject,
 
203
                                  self.semester)
 
204
 
 
205
class Enrolment(Storm):
 
206
    __storm_table__ = "enrolment"
 
207
    __storm_primary__ = "user_id", "offering_id"
 
208
 
 
209
    user_id = Int(name="loginid")
 
210
    user = Reference(user_id, User.id)
 
211
    offering_id = Int(name="offeringid")
 
212
    offering = Reference(offering_id, Offering.id)
 
213
    notes = Unicode()
 
214
    active = Bool()
 
215
 
 
216
    __init__ = _kwarg_init
 
217
 
 
218
    def __repr__(self):
 
219
        return "<%s %r in %r>" % (type(self).__name__, self.user,
 
220
                                  self.offering)