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.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. 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
# Don't give any URL if we want /.
59
query_string = '?url=' + urllib.quote(nexturl, safe="/~")
61
ctx['path'] = ivle.util.make_path('+login') + query_string
63
# If this succeeds, the user is invalid.
64
user = ivle.webapp.security.get_user_details(req)
66
if user.state == "no_agreement":
67
# Authenticated, but need to accept the ToS. Send them there.
68
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
69
# if you are not planning to display a ToS page - the ToS
70
# acceptance process actually calls usrmgt to create the user
71
# jails and related stuff.
72
req.throw_redirect(ivle.util.make_path('+tos') + query_string)
73
elif user.state == "pending":
74
# FIXME: this isn't quite the right answer, but it
75
# should be more robust in the short term.
76
session = req.get_session()
79
user.state = u'no_agreement'
81
req.throw_redirect(nexturl)
83
if req.method == "POST":
84
# While req.user is normally set to get_user_details, it won't set
85
# it if the account isn't valid. So we get it ourselves.
86
user = ivle.webapp.security.get_user_details(req)
90
username = fields.getfirst('user')
91
password = fields.getfirst('pass')
92
if username is not None:
93
# From this point onwards, we will be showing an error message
97
badlogin = "No password supplied."
101
user = authenticate.authenticate(req.store,
102
username.value, password.value)
103
except AuthError, msg:
106
# Must have got an error. Do not authenticate.
107
# The except: above will have set a message.
110
# Success - Set the session and redirect to the URL.
111
session = req.get_session()
112
session['login'] = user.login
114
user.last_login = datetime.datetime.now()
117
# Create cookies for plugins that might request them.
118
for plugin in req.config.plugin_index[CookiePlugin]:
119
for cookie in plugin.cookies:
120
# The function can be None if they just need to be
122
if plugin.cookies[cookie] is not None:
123
req.add_cookie(mod_python.Cookie.Cookie(cookie,
124
plugin.cookies[cookie](user), path='/'))
126
req.throw_redirect(nexturl)
129
# Render the login form with the error message.
130
ctx['error'] = badlogin
133
class LogoutView(XHTMLView):
134
'''A view to log the current session out.'''
135
template = 'logout.html'
136
allow_overlays = False
138
def authorize(self, req):
139
# This can be used by any authenticated user, even if they haven't
140
# accepted the ToS yet.
141
return ivle.webapp.security.get_user_details(req) is not None
143
def populate(self, req, ctx):
144
if req.method == "POST":
147
ctx['path'] = ivle.util.make_path('+logout')