~azzar1/unity/add-show-desktop-key

124 by mattgiuca
dispatch/request: Added new fields: method and username.
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2008 The University of Melbourne
3
#
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.
8
#
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.
13
#
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
17
18
# Module: dispatch.login
19
# Author: Matt Giuca
20
# Date: 21/12/2007
21
22
# Provides services for checking logins and presenting the login page.
458 by mattgiuca
Added "tos" as an app. This app simply displays the Terms of Service
23
import os
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
24
import time
458 by mattgiuca
Added "tos" as an app. This app simply displays the Terms of Service
25
26
from mod_python import Session
27
673 by mattgiuca
Rebuilt the way Terms of Service are displayed:
28
import conf
493 by dcoles
session.php: More interfaceing between IVLE and phpBB. Adds groups, emails and
29
from common import (util, db, caps, forumutil)
534 by mattgiuca
login: Catches and nicely reports any login exception, not just AuthError.
30
from auth import authenticate, autherror
124 by mattgiuca
dispatch/request: Added new fields: method and username.
31
32
def login(req):
33
    """Determines whether the user is logged in or not (looking at sessions),
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
34
    and if not, presents the login page. Returns a User object, or None
124 by mattgiuca
dispatch/request: Added new fields: method and username.
35
    if not logged in.
36
37
    If the user was already logged in, nothing is written to req. Returns
505 by mattgiuca
dispatch.html, consoleservice, userservice, interpret:
38
    the User object for the logged in user.
124 by mattgiuca
dispatch/request: Added new fields: method and username.
39
40
    If the user was not logged in, but manages to authenticate due to
41
    included postdata with a valid username/password, throws a redirect
42
    back to the same page (to avoid leaving POSTDATA in the browser).
43
44
    If the user is not logged in, or fails to authenticate, a full page is
45
    written to req. Returns None. The caller should immediately terminate.
46
    """
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
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)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
50
51
    # Check the session to see if someone is logged in. If so, go with it.
52
    # No security is required here. You must have already been authenticated
53
    # in order to get a 'login_name' variable in the session.
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
54
    if login_details is not None and login_details.state == "enabled":
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
55
        # Only allow users to authenticate if their account is ENABLED
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
56
        return login_details
124 by mattgiuca
dispatch/request: Added new fields: method and username.
57
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
58
    badlogin = None
521 by drtomc
login: Fix a carefully documented braino. Phew, users can now get to the clickthrough.
59
124 by mattgiuca
dispatch/request: Added new fields: method and username.
60
    # Check if there is any postdata containing login information
521 by drtomc
login: Fix a carefully documented braino. Phew, users can now get to the clickthrough.
61
    if login_details is None and req.method == 'POST':
124 by mattgiuca
dispatch/request: Added new fields: method and username.
62
        fields = req.get_fieldstorage()
155 by mattgiuca
login: Fix exception when user or pass is not supplied in a POST request.
63
        username = fields.getfirst('user')
64
        password = fields.getfirst('pass')
124 by mattgiuca
dispatch/request: Added new fields: method and username.
65
        if username is not None:
66
            # From this point onwards, we will be showing an error message
67
            # if unsuccessful.
68
            # Authenticate
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
69
            if password is None:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
70
                badlogin = "No password supplied."
124 by mattgiuca
dispatch/request: Added new fields: method and username.
71
            else:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
72
                try:
73
                    login_details = \
74
                        authenticate.authenticate(username.value, password.value)
534 by mattgiuca
login: Catches and nicely reports any login exception, not just AuthError.
75
                # NOTE: Can't catch AuthError, since each module throws a
76
                # different identity of AuthError.
77
                except Exception, msg:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
78
                    badlogin = msg
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
79
                if login_details is None:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
80
                    # Must have got an error. Do not authenticate.
81
                    pass
503 by mattgiuca
user.py: Added acct_expired and pass_expired methods.
82
                elif login_details.pass_expired():
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
83
                    badlogin = "Your password has expired."
503 by mattgiuca
user.py: Added acct_expired and pass_expired methods.
84
                elif login_details.acct_expired():
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
85
                    badlogin = "Your account has expired."
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
86
                else:
87
                    # Success - Set the session and redirect to avoid POSTDATA
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
88
                    session = req.get_session()
89
                    session['user'] = login_details
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
90
                    session.save()
669 by mattgiuca
Timestamps are now stored within the program as Python "time" module's
91
                    db.DB().update_user(username.value,
92
                                        last_login = time.localtime())
493 by dcoles
session.php: More interfaceing between IVLE and phpBB. Adds groups, emails and
93
                    req.add_cookie(forumutil.make_forum_cookie(login_details))
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
94
                    req.throw_redirect(req.uri)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
95
780 by mattgiuca
dispatch/login.py: When displaying the login page, returns a 200, not a 403
96
    # Present the HTML login page
124 by mattgiuca
dispatch/request: Added new fields: method and username.
97
    req.content_type = "text/html"
98
    req.title = "Login"
99
    req.write_html_head_foot = True
100
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
101
    # User is not logged in or their account is not enabled.
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
102
    if login_details is not None:
103
        # Only possible if no errors occured thus far
104
        if login_details.state == "no_agreement":
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
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
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
109
            req.user = login_details
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
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.
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
114
            present_tos(req, login_details.fullname)
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
115
            return None
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
116
        elif login_details.state == "disabled":
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
117
            # User has authenticated but their account is disabled
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
118
            badlogin = "Your account has been disabled."
522 by drtomc
Add quite a lot of stuff to get usrmgt happening.
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()
123
            session.invalidate()
124
            session.delete()
125
            db.DB().update_user(login_details.login, state='no_agreement')
126
            req.throw_redirect(req.uri)
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
127
124 by mattgiuca
dispatch/request: Added new fields: method and username.
128
    # Write the HTML for the login page
129
    # If badlogin, display an error message indicating a failed login
360 by mattgiuca
Minor HTML touch-up:
130
    req.write("""<div id="ivle_padding">
131
<p>Welcome to the Informatics Virtual Learning Environment.
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
132
   Please log in to access your files and assessment.</p>
133
""")
134
    if badlogin is not None:
135
        req.write("""<p class="error">%s</p>
136
""" % badlogin)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
137
    req.write("""<form action="" method="post">
138
  <table>
139
    <tr><td>Username:</td><td><input name="user" type="text" /></td></tr>
140
    <tr><td>Password:</td><td><input name="pass" type="password" /></td></tr>
141
    <tr><td colspan="2"><input type="submit" value="Login" /></td></tr>
142
  </table>
143
</form>
144
""")
712 by mattgiuca
setup: Added config option "motd_path" to hold the path for message-of-the-day
145
    # Write the "Message of the Day" document, if it exists.
146
    try:
147
        req.sendfile(conf.motd_path)
148
    except IOError:
149
        pass
150
    req.write('</div>\n')
124 by mattgiuca
dispatch/request: Added new fields: method and username.
151
152
    return None
153
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
154
def get_user_details(req):
124 by mattgiuca
dispatch/request: Added new fields: method and username.
155
    """Gets the name of the logged in user, without presenting a login box
156
    or attempting to authenticate.
157
    Returns None if there is no user logged in.
158
    """
159
    session = req.get_session()
160
161
    # Check the session to see if someone is logged in. If so, go with it.
162
    # No security is required here. You must have already been authenticated
163
    # in order to get a 'login_name' variable in the session.
164
    try:
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
165
        return session['user']
124 by mattgiuca
dispatch/request: Added new fields: method and username.
166
    except KeyError:
167
        return None
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
168
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
172
    the system).
173
    """
174
    req.title = "Terms of Service"
175
    # Include the JavaScript for the "makeuser" Ajax stuff
176
    req.scripts = [
177
        "media/common/json2.js",
178
        "media/common/util.js",
179
        "media/common/tos.js",
180
    ]
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"
186
menu.</p>
187
<hr />
188
""" % fullname)
458 by mattgiuca
Added "tos" as an app. This app simply displays the Terms of Service
189
    # Write out the text of the license
673 by mattgiuca
Rebuilt the way Terms of Service are displayed:
190
    util.send_terms_of_service(req)
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
191
    req.write("""<hr />
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>
195
<p>
196
  <input type="button" value="I Accept" onclick="accept_license()" />
197
  <input type="button" value="I Decline" onclick="decline_license()" />
198
</p>
199
</div>
200
""")
201