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

« back to all changes in this revision

Viewing changes to ivle/dispatch/login.py

Dispatch now generates an index for each plugin type, allowing plugins to
be written which are aware of other plugins, and other plugin types.

All view plugins now subclass from ivle.webapp.base.plugins.ViewPlugin,
as opposed to subclassing BasePlugin directly. This will allow us to
easily re-write console as an OverlayPlugin, and allow future new
plugins types to be created.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
23
import os
 
24
import datetime
 
25
 
 
26
import ivle.conf
 
27
from ivle import (util, caps, forumutil)
 
28
from ivle.auth import authenticate, AuthError
 
29
import ivle.database
 
30
 
 
31
def login(req):
 
32
    """Determines whether the user is logged in or not (looking at sessions),
 
33
    and if not, presents the login page. Returns a User object, or None
 
34
    if not logged in.
 
35
 
 
36
    If the user was already logged in, nothing is written to req. Returns
 
37
    the User object for the logged in user.
 
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
    """
 
46
    # Get the user details from the session, if already logged in
 
47
    # (None means not logged in yet)
 
48
    user = get_user_details(req)
 
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.
 
53
    if user is not None and user.state == "enabled":
 
54
        # Only allow users to authenticate if their account is ENABLED
 
55
        return user
 
56
 
 
57
    badlogin = None
 
58
 
 
59
    # Check if there is any postdata containing login information
 
60
    if user is None and req.method == 'POST':
 
61
        fields = req.get_fieldstorage()
 
62
        username = fields.getfirst('user')
 
63
        password = fields.getfirst('pass')
 
64
        if username is not None:
 
65
            # From this point onwards, we will be showing an error message
 
66
            # if unsuccessful.
 
67
            # Authenticate
 
68
            if password is None:
 
69
                badlogin = "No password supplied."
 
70
            else:
 
71
                try:
 
72
                    user = authenticate.authenticate(req.store,
 
73
                                username.value, password.value)
 
74
                except AuthError, msg:
 
75
                    badlogin = msg
 
76
                if user is None:
 
77
                    # Must have got an error. Do not authenticate.
 
78
                    pass
 
79
                elif user.password_expired:
 
80
                    badlogin = "Your password has expired."
 
81
                elif user.account_expired:
 
82
                    badlogin = "Your account has expired."
 
83
                else:
 
84
                    # Success - Set the session and redirect to avoid POSTDATA
 
85
                    session = req.get_session()
 
86
                    session['login'] = user.login
 
87
                    session.save()
 
88
                    user.last_login = datetime.datetime.now()
 
89
                    req.store.commit()
 
90
                    req.add_cookie(forumutil.make_forum_cookie(user))
 
91
                    req.throw_redirect(req.uri)
 
92
 
 
93
    # Present the HTML login page
 
94
    req.content_type = "text/html"
 
95
    req.title = "Login"
 
96
    req.write_html_head_foot = True
 
97
 
 
98
    # User is not logged in or their account is not enabled.
 
99
    if user is not None:
 
100
        # Only possible if no errors occured thus far
 
101
        if user.state == "no_agreement":
 
102
            # User has authenticated but has not accepted the TOS.
 
103
            # Present them with the TOS page.
 
104
            # First set their username for display at the top, but make sure
 
105
            # the apps tabs are not displayed
 
106
            req.user = user
 
107
            # IMPORTANT NOTE FOR HACKERS: You can't simply disable this check
 
108
            # if you are not planning to display a TOS page - the TOS
 
109
            # acceptance process actually calls usermgt to create the user
 
110
            # jails and related stuff.
 
111
            present_tos(req, user.fullname)
 
112
            return None
 
113
        elif user.state == "disabled":
 
114
            # User has authenticated but their account is disabled
 
115
            badlogin = "Your account has been disabled."
 
116
        elif user.state == "pending":
 
117
            # FIXME: this isn't quite the right answer, but it
 
118
            # should be more robust in the short term.
 
119
            session = req.get_session()
 
120
            session.invalidate()
 
121
            session.delete()
 
122
            user.state = u'no_agreement'
 
123
            req.store.commit()
 
124
            req.throw_redirect(req.uri)
 
125
 
 
126
    # Write the HTML for the login page
 
127
    # If badlogin, display an error message indicating a failed login
 
128
    req.write("""<div id="ivle_padding">
 
129
<p>Welcome to the Informatics Virtual Learning Environment.
 
130
   Please log in to access your files and assessment.</p>
 
131
""")
 
132
    if badlogin is not None:
 
133
        req.write("""<p class="error">%s</p>
 
134
""" % badlogin)
 
135
    req.write("""<form action="" method="post">
 
136
  <table>
 
137
    <tr><td>Username:</td><td><input name="user" type="text" /></td></tr>
 
138
    <tr><td>Password:</td><td><input name="pass" type="password" /></td></tr>
 
139
    <tr><td colspan="2"><input type="submit" value="Login" /></td></tr>
 
140
  </table>
 
141
</form>
 
142
""")
 
143
    # Write the "Message of the Day" document, if it exists.
 
144
    try:
 
145
        req.sendfile(ivle.conf.motd_path)
 
146
    except IOError:
 
147
        pass
 
148
    req.write('</div>\n')
 
149
 
 
150
    return None
 
151
 
 
152
def get_user_details(req):
 
153
    """Gets the name of the logged in user, without presenting a login box
 
154
    or attempting to authenticate.
 
155
    Returns None if there is no user logged in.
 
156
    """
 
157
    session = req.get_session()
 
158
 
 
159
    # Check the session to see if someone is logged in. If so, go with it.
 
160
    try:
 
161
        login = session['login']
 
162
    except KeyError:
 
163
        return None
 
164
 
 
165
    # Get the full User object from the db associated with this login
 
166
    return ivle.database.User.get_by_login(req.store, login)
 
167
 
 
168
def present_tos(req, fullname):
 
169
    """Present the Terms of Service screen to the user (who has just logged in
 
170
    for the first time and needs to accept these before being admitted into
 
171
    the system).
 
172
    """
 
173
    req.title = "Terms of Service"
 
174
    # Include the JavaScript for the "makeuser" Ajax stuff
 
175
    req.scripts = [
 
176
        "media/common/json2.js",
 
177
        "media/common/util.js",
 
178
        "media/common/tos.js",
 
179
    ]
 
180
    req.write("""<div id="ivle_padding">
 
181
<p>Welcome, <b>%s</b>.</p>
 
182
<p>As this is the first time you have logged into IVLE, you are required to
 
183
accept these Terms of Service before using the system.</p>
 
184
<p>You will be allowed to re-read these terms at any time from the "Help"
 
185
menu.</p>
 
186
<hr />
 
187
""" % fullname)
 
188
    # Write out the text of the license
 
189
    util.send_terms_of_service(req)
 
190
    req.write("""<hr />
 
191
<div id="tos_acceptbuttons">
 
192
<p>Please click "I Accept" to indicate that you have read and understand these
 
193
terms, or click "I Decline" to log out of IVLE.</p>
 
194
<p>
 
195
  <input type="button" value="I Accept" onclick="accept_license()" />
 
196
  <input type="button" value="I Decline" onclick="decline_license()" />
 
197
</p>
 
198
</div>
 
199
""")
 
200