~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
493 by dcoles
session.php: More interfaceing between IVLE and phpBB. Adds groups, emails and
28
from common import (util, db, caps, forumutil)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
29
from auth import authenticate
30
31
def login(req):
32
    """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
33
    and if not, presents the login page. Returns a User object, or None
124 by mattgiuca
dispatch/request: Added new fields: method and username.
34
    if not logged in.
35
36
    If the user was already logged in, nothing is written to req. Returns
505 by mattgiuca
dispatch.html, consoleservice, userservice, interpret:
37
    the User object for the logged in user.
124 by mattgiuca
dispatch/request: Added new fields: method and username.
38
39
    If the user was not logged in, but manages to authenticate due to
40
    included postdata with a valid username/password, throws a redirect
41
    back to the same page (to avoid leaving POSTDATA in the browser).
42
43
    If the user is not logged in, or fails to authenticate, a full page is
44
    written to req. Returns None. The caller should immediately terminate.
45
    """
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
46
    # Get the user details from the session, if already logged in
47
    # (None means not logged in yet)
48
    login_details = get_user_details(req)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
49
50
    # Check the session to see if someone is logged in. If so, go with it.
51
    # No security is required here. You must have already been authenticated
52
    # 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
53
    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
54
        # 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
55
        return login_details
124 by mattgiuca
dispatch/request: Added new fields: method and username.
56
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
57
    badlogin = None
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
58
    login_details = None    # We'll re-auth you
124 by mattgiuca
dispatch/request: Added new fields: method and username.
59
    # Check if there is any postdata containing login information
60
    if req.method == 'POST':
61
        fields = req.get_fieldstorage()
155 by mattgiuca
login: Fix exception when user or pass is not supplied in a POST request.
62
        username = fields.getfirst('user')
63
        password = fields.getfirst('pass')
124 by mattgiuca
dispatch/request: Added new fields: method and username.
64
        if username is not None:
65
            # From this point onwards, we will be showing an error message
66
            # if unsuccessful.
67
            # Authenticate
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
68
            if password is None:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
69
                badlogin = "No password supplied."
124 by mattgiuca
dispatch/request: Added new fields: method and username.
70
            else:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
71
                try:
72
                    login_details = \
73
                        authenticate.authenticate(username.value, password.value)
74
                except authenticate.AuthError, msg:
75
                    badlogin = msg
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
76
                if login_details is None:
509 by mattgiuca
common.db: Rewrote user_authenticate to return 3 values (True, false, None)
77
                    # Must have got an error. Do not authenticate.
78
                    pass
503 by mattgiuca
user.py: Added acct_expired and pass_expired methods.
79
                elif login_details.pass_expired():
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
80
                    badlogin = "Your password has expired."
503 by mattgiuca
user.py: Added acct_expired and pass_expired methods.
81
                elif login_details.acct_expired():
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
82
                    badlogin = "Your account has expired."
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
83
                else:
84
                    # Success - Set the session and redirect to avoid POSTDATA
500 by mattgiuca
db: get_user and get_users now return User objects instead of dictionaries.
85
                    # TODO: Store the User object in session instead of
86
                    # individual fields
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
87
                    session = req.get_session()
88
                    session['user'] = login_details
376 by mattgiuca
auth/authenticate: Replaced dummy code (which always auths) with a call to the
89
                    session.save()
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
90
                    # XXX time.localtime() (a tuple of ints) is not valid for
91
                    # inserting as a TIMESTAMP in the DB.
92
                    #db.DB().update_user(username.value,
93
                    #                    last_login=time.localtime())
493 by dcoles
session.php: More interfaceing between IVLE and phpBB. Adds groups, emails and
94
                    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
95
                    req.throw_redirect(req.uri)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
96
97
    # Give a 403 Forbidden status, but present a full HTML login page
98
    # instead of the usual 403 error.
99
    req.status = req.HTTP_FORBIDDEN
100
    req.content_type = "text/html"
101
    req.title = "Login"
102
    req.write_html_head_foot = True
103
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
104
    # 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
105
    if login_details is not None:
106
        # Only possible if no errors occured thus far
107
        if login_details.state == "no_agreement":
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
108
            # User has authenticated but has not accepted the TOS.
109
            # Present them with the TOS page.
110
            # First set their username for display at the top, but make sure
111
            # the apps tabs are not displayed
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
112
            req.user = login_details
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
113
            # IMPORTANT NOTE FOR HACKERS: You can't simply disable this check
114
            # if you are not planning to display a TOS page - the TOS
115
            # acceptance process actually calls usermgt to create the user
116
            # jails and related stuff.
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
117
            present_tos(req, login_details.fullname)
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
118
            return None
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
119
        elif login_details.state == "disabled":
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
120
            # User has authenticated but their account is disabled
475 by mattgiuca
Commited some earlier changes to users.sql (not committed earlier due to
121
            badlogin = "Your account has been disabled."
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
122
    # Else, just fall through (failed to authenticate)
123
124 by mattgiuca
dispatch/request: Added new fields: method and username.
124
    # Write the HTML for the login page
125
    # If badlogin, display an error message indicating a failed login
360 by mattgiuca
Minor HTML touch-up:
126
    req.write("""<div id="ivle_padding">
127
<p>Welcome to the Informatics Virtual Learning Environment.
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
128
   Please log in to access your files and assessment.</p>
129
""")
130
    if badlogin is not None:
131
        req.write("""<p class="error">%s</p>
132
""" % badlogin)
124 by mattgiuca
dispatch/request: Added new fields: method and username.
133
    req.write("""<form action="" method="post">
134
  <table>
135
    <tr><td>Username:</td><td><input name="user" type="text" /></td></tr>
136
    <tr><td>Password:</td><td><input name="pass" type="password" /></td></tr>
137
    <tr><td colspan="2"><input type="submit" value="Login" /></td></tr>
138
  </table>
139
</form>
360 by mattgiuca
Minor HTML touch-up:
140
</div>
124 by mattgiuca
dispatch/request: Added new fields: method and username.
141
""")
142
143
    return None
144
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
145
def get_user_details(req):
124 by mattgiuca
dispatch/request: Added new fields: method and username.
146
    """Gets the name of the logged in user, without presenting a login box
147
    or attempting to authenticate.
148
    Returns None if there is no user logged in.
149
    """
150
    session = req.get_session()
151
152
    # Check the session to see if someone is logged in. If so, go with it.
153
    # No security is required here. You must have already been authenticated
154
    # in order to get a 'login_name' variable in the session.
155
    try:
504 by mattgiuca
Warning: Broken build, but rather unavoidable or this commit will spiral out
156
        return session['user']
124 by mattgiuca
dispatch/request: Added new fields: method and username.
157
    except KeyError:
158
        return None
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
159
160
def present_tos(req, fullname):
161
    """Present the Terms of Service screen to the user (who has just logged in
162
    for the first time and needs to accept these before being admitted into
163
    the system).
164
    """
165
    req.title = "Terms of Service"
166
    # Include the JavaScript for the "makeuser" Ajax stuff
167
    req.scripts = [
168
        "media/common/json2.js",
169
        "media/common/util.js",
170
        "media/common/tos.js",
171
    ]
172
    req.write("""<div id="ivle_padding">
173
<p>Welcome, <b>%s</b>.</p>
174
<p>As this is the first time you have logged into IVLE, you are required to
175
accept these Terms of Service before using the system.</p>
176
<p>You will be allowed to re-read these terms at any time from the "Help"
177
menu.</p>
178
<hr />
179
""" % fullname)
458 by mattgiuca
Added "tos" as an app. This app simply displays the Terms of Service
180
    # Write out the text of the license
181
    license_file = os.path.join(util.make_local_path("apps"),
182
                        "tos", "license.html")
183
    req.sendfile(license_file)
455 by mattgiuca
Login now handles the 3 login states: no_agreement, enabled and disabled.
184
    req.write("""<hr />
185
<div id="tos_acceptbuttons">
186
<p>Please click "I Accept" to indicate that you have read and understand these
187
terms, or click "I Decline" to log out of IVLE.</p>
188
<p>
189
  <input type="button" value="I Accept" onclick="accept_license()" />
190
  <input type="button" value="I Decline" onclick="decline_license()" />
191
</p>
192
</div>
193
""")
194