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.dispatch.login
30
from ivle.auth import authenticate, AuthError
31
from ivle.webapp.base.xhtml import XHTMLView
32
from ivle.webapp.base.plugins import CookiePlugin
33
from ivle.dispatch.login import get_user_details
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
ctx['path'] = ivle.util.make_path('+login') + \
57
'?' + urllib.urlencode([('url', nexturl)])
59
# If this succeeds, the user is invalid.
60
user = get_user_details(req)
62
if user.state == "no_agreement":
63
# Authenticated, but need to accept the ToS. Send them there.
64
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
65
# if you are not planning to display a ToS page - the ToS
66
# acceptance process actually calls usrmgt to create the user
67
# jails and related stuff.
68
req.throw_redirect(ivle.util.make_path('+tos') + \
69
'?' + urllib.urlencode([('url', nexturl)]))
70
elif user.state == "pending":
71
# FIXME: this isn't quite the right answer, but it
72
# should be more robust in the short term.
73
session = req.get_session()
76
user.state = u'no_agreement'
78
req.throw_redirect(nexturl)
80
if req.method == "POST":
81
# While req.user is normally set to get_user_details, it won't set
82
# it if the account isn't valid. So we get it ourselves.
83
user = get_user_details(req)
87
username = fields.getfirst('user')
88
password = fields.getfirst('pass')
89
if username is not None:
90
# From this point onwards, we will be showing an error message
94
badlogin = "No password supplied."
98
user = authenticate.authenticate(req.store,
99
username.value, password.value)
100
except AuthError, msg:
103
# Must have got an error. Do not authenticate.
104
# The except: above will have set a message.
107
# Success - Set the session and redirect to the URL.
108
session = req.get_session()
109
session['login'] = user.login
111
user.last_login = datetime.datetime.now()
114
# Create cookies for plugins that might request them.
115
for plugin in req.config.plugin_index[CookiePlugin]:
116
for cookie in plugin.cookies:
117
# The function can be None if they just need to be
119
if plugin.cookies[cookie] is not None:
120
req.add_cookie(mod_python.Cookie.Cookie(cookie,
121
plugin.cookies[cookie](user), path='/'))
123
req.throw_redirect(nexturl)
126
# Render the login form with the error message.
127
ctx['error'] = badlogin
130
class LogoutView(XHTMLView):
131
'''A view to log the current session out.'''
132
template = 'logout.html'
133
allow_overlays = False
135
def authorize(self, req):
136
# This can be used by any authenticated user, even if they haven't
137
# accepted the ToS yet.
138
return ivle.dispatch.login.get_user_details(req) is not None
140
def populate(self, req, ctx):
141
if req.method == "POST":
144
ctx['path'] = ivle.util.make_path('+logout')