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'
39
def authorize(self, req):
42
def populate(self, req, ctx):
43
fields = req.get_fieldstorage()
44
nexturl = fields.getfirst('url')
49
# We are already logged in. Don't bother logging in again.
50
# Note that req.user is None even if we are 'logged in', if the user is
52
if req.user is not None:
53
req.throw_redirect(nexturl)
55
ctx['path'] = ivle.util.make_path('+login') + \
56
'?' + urllib.urlencode([('url', nexturl)])
58
# If this succeeds, the user is invalid.
59
user = get_user_details(req)
61
if user.state == "no_agreement":
62
# Authenticated, but need to accept the ToS. Send them there.
63
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
64
# if you are not planning to display a ToS page - the ToS
65
# acceptance process actually calls usrmgt to create the user
66
# jails and related stuff.
67
req.throw_redirect(ivle.util.make_path('+tos') + \
68
'?' + urllib.urlencode([('url', nexturl)]))
69
elif user.state == "pending":
70
# FIXME: this isn't quite the right answer, but it
71
# should be more robust in the short term.
72
session = req.get_session()
75
user.state = u'no_agreement'
77
req.throw_redirect(nexturl)
79
if req.method == "POST":
80
# While req.user is normally set to get_user_details, it won't set
81
# it if the account isn't valid. So we get it ourselves.
82
user = get_user_details(req)
86
username = fields.getfirst('user')
87
password = fields.getfirst('pass')
88
if username is not None:
89
# From this point onwards, we will be showing an error message
93
badlogin = "No password supplied."
97
user = authenticate.authenticate(req.store,
98
username.value, password.value)
99
except AuthError, msg:
102
# Must have got an error. Do not authenticate.
103
# The except: above will have set a message.
106
# Success - Set the session and redirect to the URL.
107
session = req.get_session()
108
session['login'] = user.login
110
user.last_login = datetime.datetime.now()
113
# Create cookies for plugins that might request them.
114
for plugin in req.plugin_index[CookiePlugin]:
115
for cookie in plugin.cookies:
116
# The function can be None if they just need to be
118
if plugin.cookies[cookie] is not None:
119
req.add_cookie(mod_python.Cookie.Cookie(cookie,
120
plugin.cookies[cookie](user), path='/'))
122
req.throw_redirect(nexturl)
125
# Render the login form with the error message.
126
ctx['error'] = badlogin
129
class LogoutView(XHTMLView):
130
'''A view to log the current session out.'''
131
template = 'logout.html'
133
def authorize(self, req):
134
# This can be used by any authenticated user, even if they haven't
135
# accepted the ToS yet.
136
return ivle.dispatch.login.get_user_details(req) is not None
138
def populate(self, req, ctx):
139
if req.method == "POST":
142
ctx['path'] = ivle.util.make_path('+logout')