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. If it is a POST, they might be trying to
51
# clobber their session with some new credentials. That's their own
52
# business, so we let them do it. Otherwise, we don't bother prompting
53
# and just redirect to the destination.
54
# Note that req.user is None even if we are 'logged in', if the user is
55
# invalid (state != enabled, or expired).
56
if req.method != "POST" and req.user is not None:
57
req.throw_redirect(nexturl)
59
# Don't give any URL if we want /.
63
query_string = '?url=' + urllib.quote(nexturl, safe="/~")
65
ctx['path'] = ivle.util.make_path('+login') + query_string
67
# If this succeeds, the user is invalid.
68
user = ivle.webapp.security.get_user_details(req)
70
if user.state == "no_agreement":
71
# Authenticated, but need to accept the ToS. Send them there.
72
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
73
# if you are not planning to display a ToS page - the ToS
74
# acceptance process actually calls usrmgt to create the user
75
# jails and related stuff.
76
req.throw_redirect(ivle.util.make_path('+tos') + query_string)
77
elif user.state == "pending":
78
# FIXME: this isn't quite the right answer, but it
79
# should be more robust in the short term.
80
session = req.get_session()
83
user.state = u'no_agreement'
85
req.throw_redirect(nexturl)
87
if req.method == "POST":
88
# While req.user is normally set to get_user_details, it won't set
89
# it if the account isn't valid. So we get it ourselves.
90
user = ivle.webapp.security.get_user_details(req)
94
username = fields.getfirst('user')
95
password = fields.getfirst('pass')
96
if username is not None:
97
# From this point onwards, we will be showing an error message
101
badlogin = "No password supplied."
105
user = authenticate.authenticate(req.store,
106
username.value, 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.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'] = ivle.util.make_path('+logout')