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: Will Grant, Nick Chadwick
23
import mod_python.Cookie
25
# This needs to be importable from outside Apache.
29
import ivle.pulldown_subj
30
import ivle.webapp.security
31
from ivle.auth import authenticate, AuthError
32
from ivle.webapp.base.xhtml import XHTMLView
33
from ivle.webapp.base.plugins import CookiePlugin
35
class LoginView(XHTMLView):
36
'''A view to allow a user to log in.'''
37
template = 'login.html'
38
allow_overlays = False
40
def authorize(self, req):
43
def populate(self, req, ctx):
44
fields = req.get_fieldstorage()
45
nexturl = fields.getfirst('url')
50
# We are already logged in. Don't bother logging in again.
51
# Note that req.user is None even if we are 'logged in', if the user is
53
if req.user is not None:
54
req.throw_redirect(nexturl)
56
# Don't give any URL if we want /.
60
query_string = '?url=' + urllib.quote(nexturl, safe="/~")
62
ctx['path'] = ivle.util.make_path('+login') + query_string
64
# If this succeeds, the user is invalid.
65
user = ivle.webapp.security.get_user_details(req)
67
if user.state == "no_agreement":
68
# Authenticated, but need to accept the ToS. Send them there.
69
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
70
# if you are not planning to display a ToS page - the ToS
71
# acceptance process actually calls usrmgt to create the user
72
# jails and related stuff.
73
req.throw_redirect(ivle.util.make_path('+tos') + query_string)
74
elif user.state == "pending":
75
# FIXME: this isn't quite the right answer, but it
76
# should be more robust in the short term.
77
session = req.get_session()
80
user.state = u'no_agreement'
82
req.throw_redirect(nexturl)
84
if req.method == "POST":
85
# While req.user is normally set to get_user_details, it won't set
86
# it if the account isn't valid. So we get it ourselves.
87
user = ivle.webapp.security.get_user_details(req)
91
username = fields.getfirst('user')
92
password = fields.getfirst('pass')
93
if username is not None:
94
# From this point onwards, we will be showing an error message
98
badlogin = "No password supplied."
102
user = authenticate.authenticate(req.store,
103
username.value, password.value)
104
except AuthError, msg:
107
# Must have got an error. Do not authenticate.
108
# The except: above will have set a message.
111
# Success - Set the session and redirect to the URL.
112
session = req.get_session()
113
session['login'] = user.login
116
user.last_login = datetime.datetime.now()
118
# Create cookies for plugins that might request them.
119
for plugin in req.config.plugin_index[CookiePlugin]:
120
for cookie in plugin.cookies:
121
# The function can be None if they just need to be
123
if plugin.cookies[cookie] is not None:
124
req.add_cookie(mod_python.Cookie.Cookie(cookie,
125
plugin.cookies[cookie](user), path='/'))
127
# Add any new enrolments.
128
ivle.pulldown_subj.enrol_user(req.store, user)
131
req.throw_redirect(nexturl)
134
# Render the login form with the error message.
135
ctx['error'] = badlogin
138
class LogoutView(XHTMLView):
139
'''A view to log the current session out.'''
140
template = 'logout.html'
141
allow_overlays = False
143
def authorize(self, req):
144
# This can be used by any authenticated user, even if they haven't
145
# accepted the ToS yet.
146
return ivle.webapp.security.get_user_details(req) is not None
148
def populate(self, req, ctx):
149
if req.method == "POST":
152
ctx['path'] = ivle.util.make_path('+logout')