18
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
20
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')
46
# XXX Warning that Internet Explorer is unsupported
47
# Test if the user is in Internet Explorer
49
useragent = req.headers_in['User-Agent']
50
# A bit of very basic UA string detection
51
ctx['msie'] = ('MSIE' in useragent
52
and 'AppleWebKit' not in useragent
53
and 'Gecko' not in useragent
54
and 'Opera' not in useragent)
61
# We are already logged in. If it is a POST, they might be trying to
62
# clobber their session with some new credentials. That's their own
63
# business, so we let them do it. Otherwise, we don't bother prompting
64
# and just redirect to the destination.
65
# Note that req.user is None even if we are 'logged in', if the user is
66
# invalid (state != enabled, or expired).
67
if req.method != "POST" and req.user is not None:
68
req.throw_redirect(nexturl)
70
# Don't give any URL if we want /.
74
query_string = '?url=' + urllib.quote(nexturl, safe="/~")
76
ctx['path'] = req.make_path('+login') + query_string
78
# If this succeeds, the user is invalid.
79
user = ivle.webapp.security.get_user_details(req)
81
if user.state == "no_agreement":
82
# Authenticated, but need to accept the ToS. Send them there.
83
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this
84
# if you are not planning to display a ToS page - the ToS
85
# acceptance process actually calls usrmgt to create the user
86
# jails and related stuff.
87
req.throw_redirect(req.make_path('+tos') + query_string)
88
elif user.state == "pending":
89
# FIXME: this isn't quite the right answer, but it
90
# should be more robust in the short term.
91
session = req.get_session()
94
user.state = u'no_agreement'
96
req.throw_redirect(nexturl)
98
if req.method == "POST":
99
# While req.user is normally set to get_user_details, it won't set
100
# it if the account isn't valid. So we get it ourselves.
101
user = ivle.webapp.security.get_user_details(req)
105
username = fields.getfirst('user')
106
password = fields.getfirst('pass')
107
if username is not None:
108
# From this point onwards, we will be showing an error message
112
badlogin = "No password supplied."
116
# Username is case insensitive
117
user = authenticate.authenticate(req.config, req.store,
118
username.value.lower(), password.value)
119
except AuthError, msg:
122
# Must have got an error. Do not authenticate.
123
# The except: above will have set a message.
126
# Success - Set the session and redirect to the URL.
127
session = req.get_session()
128
session['login'] = user.login
131
user.last_login = datetime.datetime.now()
133
# Create cookies for plugins that might request them.
134
for plugin in req.config.plugin_index[CookiePlugin]:
135
for cookie in plugin.cookies:
136
# The function can be None if they just need to be
138
if plugin.cookies[cookie] is not None:
139
req.add_cookie(mod_python.Cookie.Cookie(cookie,
140
plugin.cookies[cookie](user), path='/'))
142
# Add any new enrolments.
143
ivle.pulldown_subj.enrol_user(req.config, req.store, user)
146
req.throw_redirect(nexturl)
149
# Render the login form with the error message.
150
ctx['error'] = badlogin
153
23
class LogoutView(XHTMLView):
154
24
'''A view to log the current session out.'''
155
25
template = 'logout.html'
156
allow_overlays = False
158
def authorize(self, req):
159
# This can be used by any authenticated user, even if they haven't
160
# accepted the ToS yet.
161
return ivle.webapp.security.get_user_details(req) is not None
163
27
def populate(self, req, ctx):
164
28
if req.method == "POST":
167
ctx['path'] = req.make_path('+logout')
31
ctx['path'] = ivle.util.make_path('logout')