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.
28
import ivle.pulldown_subj
29
import ivle.webapp.security
30
from ivle.auth import authenticate, AuthError
31
from ivle.webapp.base.xhtml import XHTMLView
32
from ivle.webapp.base.plugins import CookiePlugin
34
class LoginView(XHTMLView):
35
'''A view to allow a user to log in.'''
36
template = 'login.html'
37
allow_overlays = False
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. If it is a POST, they might be trying to
50
# clobber their session with some new credentials. That's their own
51
# business, so we let them do it. Otherwise, we don't bother prompting
52
# and just redirect to the destination.
53
# Note that req.user is None even if we are 'logged in', if the user is
54
# invalid (state != enabled, or expired).
55
if req.method != "POST" and req.user is not None:
56
req.throw_redirect(nexturl)
58
# Don't give any URL if we want /.
62
query_string = '?url=' + urllib.quote(nexturl, safe="/~")
64
ctx['path'] = req.make_path('+login') + query_string
66
# If this succeeds, the user is invalid.
67
user = ivle.webapp.security.get_user_details(req)
69
if user.state == "no_agreement":
70
# Authenticated, but need to accept the ToS. Send them there.
71
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
72
# if you are not planning to display a ToS page - the ToS
73
# acceptance process actually calls usrmgt to create the user
74
# jails and related stuff.
75
req.throw_redirect(req.make_path('+tos') + query_string)
76
elif user.state == "pending":
77
# FIXME: this isn't quite the right answer, but it
78
# should be more robust in the short term.
79
session = req.get_session()
82
user.state = u'no_agreement'
84
req.throw_redirect(nexturl)
86
if req.method == "POST":
87
# While req.user is normally set to get_user_details, it won't set
88
# it if the account isn't valid. So we get it ourselves.
89
user = ivle.webapp.security.get_user_details(req)
93
username = fields.getfirst('user')
94
password = fields.getfirst('pass')
95
if username is not None:
96
# From this point onwards, we will be showing an error message
100
badlogin = "No password supplied."
104
# Username is case insensitive
105
user = authenticate.authenticate(req.config, req.store,
106
username.value.lower(), password.value)
107
except AuthError, msg:
110
# Must have got an error. Do not authenticate.
111
# The except: above will have set a message.
114
# Success - Set the session and redirect to the URL.
115
session = req.get_session()
116
session['login'] = user.login
119
user.last_login = datetime.datetime.now()
121
# Create cookies for plugins that might request them.
122
for plugin in req.config.plugin_index[CookiePlugin]:
123
for cookie in plugin.cookies:
124
# The function can be None if they just need to be
126
if plugin.cookies[cookie] is not None:
127
req.add_cookie(mod_python.Cookie.Cookie(cookie,
128
plugin.cookies[cookie](user), path='/'))
130
# Add any new enrolments.
131
ivle.pulldown_subj.enrol_user(req.config, req.store, user)
134
req.throw_redirect(nexturl)
137
# Render the login form with the error message.
138
ctx['error'] = badlogin
141
class LogoutView(XHTMLView):
142
'''A view to log the current session out.'''
143
template = 'logout.html'
144
allow_overlays = False
146
def authorize(self, req):
147
# This can be used by any authenticated user, even if they haven't
148
# accepted the ToS yet.
149
return ivle.webapp.security.get_user_details(req) is not None
151
def populate(self, req, ctx):
152
if req.method == "POST":
155
ctx['path'] = req.make_path('+logout')