1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2009 The University of Melbourne
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.
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.
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
18
# Author: Matt Giuca, Will Grant
21
Database Classes and Utilities for Storm ORM
23
This module provides all of the classes which map to database tables.
24
It also provides miscellaneous utility functions for database interaction.
30
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
31
Reference, ReferenceSet, Bool, Storm, Desc
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)
43
def get_conn_string():
45
Returns the Storm connection string, generated from the conf file.
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,
53
Open a database connection and transaction. Return a storm.store.Store
54
instance connected to the configured IVLE database.
56
return Store(create_database(get_conn_string()))
60
Represents an IVLE user.
62
__storm_table__ = "login"
64
id = Int(primary=True, name="loginid")
73
last_login = DateTime()
81
if self.rolenm is 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)
90
__init__ = _kwarg_init
93
return "<%s '%s'>" % (type(self).__name__, self.login)
95
def authenticate(self, password):
96
"""Validate a given password against this user.
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
102
if self.passhash is None:
104
return self.hash_password(password) == self.passhash
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.
110
return self.role.hasCap(capability)
113
def password_expired(self):
114
fieldval = self.pass_exp
115
return fieldval is not None and datetime.datetime.now() > fieldval
118
def account_expired(self):
119
fieldval = self.acct_exp
120
return fieldval is not None and datetime.datetime.now() > fieldval
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(
130
Desc(Semester.semester),
136
return Store.of(self).find(Subject,
137
Enrolment.user_id == self.id,
138
Enrolment.active == True,
139
Offering.id == Enrolment.offering_id,
140
Subject.id == Offering.subject_id).config(distinct=True)
143
def active_enrolments(self):
144
'''A sanely ordered list of the user's active enrolments.'''
145
return self._get_enrolments(True)
148
def enrolments(self):
149
'''A sanely ordered list of all of the user's enrolments.'''
150
return self._get_enrolments(False)
153
def hash_password(password):
154
return md5.md5(password).hexdigest()
157
def get_by_login(cls, store, login):
159
Get the User from the db associated with a given store and
162
return store.find(cls, cls.login == unicode(login)).one()
164
class Subject(Storm):
165
__storm_table__ = "subject"
167
id = Int(primary=True, name="subjectid")
168
code = Unicode(name="subj_code")
169
name = Unicode(name="subj_name")
170
short_name = Unicode(name="subj_short_name")
173
offerings = ReferenceSet(id, 'Offering.subject_id')
175
__init__ = _kwarg_init
178
return "<%s '%s'>" % (type(self).__name__, self.short_name)
180
class Semester(Storm):
181
__storm_table__ = "semester"
183
id = Int(primary=True, name="semesterid")
188
offerings = ReferenceSet(id, 'Offering.semester_id')
190
__init__ = _kwarg_init
193
return "<%s %s/%s>" % (type(self).__name__, self.year, self.semester)
195
class Offering(Storm):
196
__storm_table__ = "offering"
198
id = Int(primary=True, name="offeringid")
199
subject_id = Int(name="subject")
200
subject = Reference(subject_id, Subject.id)
201
semester_id = Int(name="semesterid")
202
semester = Reference(semester_id, Semester.id)
203
groups_student_permissions = Unicode()
205
enrolments = ReferenceSet(id, 'Enrolment.offering_id')
207
__init__ = _kwarg_init
210
return "<%s %r in %r>" % (type(self).__name__, self.subject,
213
class Enrolment(Storm):
214
__storm_table__ = "enrolment"
215
__storm_primary__ = "user_id", "offering_id"
217
user_id = Int(name="loginid")
218
user = Reference(user_id, User.id)
219
offering_id = Int(name="offeringid")
220
offering = Reference(offering_id, Offering.id)
224
__init__ = _kwarg_init
227
return "<%s %r in %r>" % (type(self).__name__, self.user,