22
22
# Provides services for checking logins and presenting the login page.
26
from mod_python import Session
29
from common import (util, db, caps, forumutil)
30
from auth import authenticate, autherror
24
from mod_python import (util, Session)
26
from auth import authenticate
33
29
"""Determines whether the user is logged in or not (looking at sessions),
34
and if not, presents the login page. Returns a User object, or None
30
and if not, presents the login page. Returns a String username, or None
37
33
If the user was already logged in, nothing is written to req. Returns
38
the User object for the logged in user.
34
a string of the username.
40
36
If the user was not logged in, but manages to authenticate due to
41
37
included postdata with a valid username/password, throws a redirect
44
40
If the user is not logged in, or fails to authenticate, a full page is
45
41
written to req. Returns None. The caller should immediately terminate.
47
# Get the user details from the session, if already logged in
48
# (None means not logged in yet)
49
login_details = get_user_details(req)
43
session = req.get_session()
51
45
# Check the session to see if someone is logged in. If so, go with it.
52
46
# No security is required here. You must have already been authenticated
53
47
# in order to get a 'login_name' variable in the session.
54
if login_details is not None and login_details.state == "enabled":
55
# Only allow users to authenticate if their account is ENABLED
49
return session['login_name']
60
54
# Check if there is any postdata containing login information
61
if login_details is None and req.method == 'POST':
55
if req.method == 'POST':
62
56
fields = req.get_fieldstorage()
63
username = fields.getfirst('user')
64
password = fields.getfirst('pass')
57
username = fields.getfirst('user').value
58
password = fields.getfirst('pass').value
65
59
if username is not None:
66
60
# From this point onwards, we will be showing an error message
70
badlogin = "No password supplied."
63
if (password is not None and
64
authenticate.authenticate(username, password)):
65
# Success - Set the session and redirect to avoid POSTDATA
66
session['login_name'] = username
68
req.throw_redirect(req.uri)
74
authenticate.authenticate(username.value, password.value)
75
# NOTE: Can't catch AuthError, since each module throws a
76
# different identity of AuthError.
77
except Exception, msg:
79
if login_details is None:
80
# Must have got an error. Do not authenticate.
82
elif login_details.pass_expired():
83
badlogin = "Your password has expired."
84
elif login_details.acct_expired():
85
badlogin = "Your account has expired."
87
# Success - Set the session and redirect to avoid POSTDATA
88
session = req.get_session()
89
session['user'] = login_details
91
db.DB().update_user(username.value,
92
last_login = time.localtime())
93
req.add_cookie(forumutil.make_forum_cookie(login_details))
94
req.throw_redirect(req.uri)
96
# Present the HTML login page
72
# User is not logged in. Present the login box.
73
# Give a 403 Forbidden status, but present a full HTML login page
74
# instead of the usual 403 error.
75
req.status = req.HTTP_FORBIDDEN
97
76
req.content_type = "text/html"
98
77
req.title = "Login"
99
78
req.write_html_head_foot = True
101
# User is not logged in or their account is not enabled.
102
if login_details is not None:
103
# Only possible if no errors occured thus far
104
if login_details.state == "no_agreement":
105
# User has authenticated but has not accepted the TOS.
106
# Present them with the TOS page.
107
# First set their username for display at the top, but make sure
108
# the apps tabs are not displayed
109
req.user = login_details
110
# IMPORTANT NOTE FOR HACKERS: You can't simply disable this check
111
# if you are not planning to display a TOS page - the TOS
112
# acceptance process actually calls usermgt to create the user
113
# jails and related stuff.
114
present_tos(req, login_details.fullname)
116
elif login_details.state == "disabled":
117
# User has authenticated but their account is disabled
118
badlogin = "Your account has been disabled."
119
elif login_details.state == "pending":
120
# FIXME: this isn't quite the right answer, but it
121
# should be more robust in the short term.
122
session = req.get_session()
125
db.DB().update_user(login_details.login, state='no_agreement')
126
req.throw_redirect(req.uri)
128
80
# Write the HTML for the login page
129
81
# If badlogin, display an error message indicating a failed login
130
req.write("""<div id="ivle_padding">
131
<p>Welcome to the Informatics Virtual Learning Environment.
132
Please log in to access your files and assessment.</p>
134
if badlogin is not None:
135
req.write("""<p class="error">%s</p>
83
req.write("""<p class="error">Invalid username or password.</p>""")
137
84
req.write("""<form action="" method="post">
139
86
<tr><td>Username:</td><td><input name="user" type="text" /></td></tr>
162
103
# No security is required here. You must have already been authenticated
163
104
# in order to get a 'login_name' variable in the session.
165
return session['user']
106
return session['login_name']
169
def present_tos(req, fullname):
170
"""Present the Terms of Service screen to the user (who has just logged in
171
for the first time and needs to accept these before being admitted into
174
req.title = "Terms of Service"
175
# Include the JavaScript for the "makeuser" Ajax stuff
177
"media/common/json2.js",
178
"media/common/util.js",
179
"media/common/tos.js",
181
req.write("""<div id="ivle_padding">
182
<p>Welcome, <b>%s</b>.</p>
183
<p>As this is the first time you have logged into IVLE, you are required to
184
accept these Terms of Service before using the system.</p>
185
<p>You will be allowed to re-read these terms at any time from the "Help"
189
# Write out the text of the license
190
util.send_terms_of_service(req)
192
<div id="tos_acceptbuttons">
193
<p>Please click "I Accept" to indicate that you have read and understand these
194
terms, or click "I Decline" to log out of IVLE.</p>
196
<input type="button" value="I Accept" onclick="accept_license()" />
197
<input type="button" value="I Decline" onclick="decline_license()" />