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

« back to all changes in this revision

Viewing changes to ivle/webapp/admin/user.py

  • Committer: Matt Giuca
  • Date: 2009-02-24 02:02:03 UTC
  • mto: This revision was merged to the branch mainline in revision 1119.
  • Revision ID: matt.giuca@gmail.com-20090224020203-aqdcjnsj6y7wl32o
Added a new look to the IVLE header bar. Mmmm... Web 2.0.
Added top-level directory image-source, containing SVG and script files for
    generating the images.
ivle/webapp/coremedia/images: Added 'chrome' directory containing the rendered
    images.
Modified ivle/webapp/base/ivle-headings.html and
    ivle/webapp/coremedia/ivle.css to support the new images.
    Note that the H1 and H2 at the top of the page are no longer displayed
    (and their custom styles have been removed). There is a heading image
    instead.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
# Author: Matt Giuca, Will Grant
19
19
 
20
 
import formencode
21
 
import formencode.validators
22
 
from genshi.filters import HTMLFormFiller
23
 
 
24
 
from ivle.webapp import ApplicationRoot
25
20
from ivle.webapp.base.rest import JSONRESTView, require_permission
26
21
from ivle.webapp.base.xhtml import XHTMLView
27
22
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
28
 
from ivle.webapp.admin.publishing import root_to_user, user_url
29
 
from ivle.database import User
 
23
from ivle.webapp.errors import NotFound, Unauthorized
30
24
import ivle.database
31
 
import ivle.date
32
25
import ivle.util
33
26
 
34
 
 
35
 
class UsersView(XHTMLView):
36
 
    """A list of all IVLE users."""
37
 
    template = 'templates/users.html'
38
 
 
39
 
    def authorize(self, req):
40
 
        return req.user.admin
41
 
 
42
 
    def populate(self, req, ctx):
43
 
        ctx['req'] = req
44
 
        ctx['users'] = req.store.find(User).order_by(User.login)
45
 
 
46
 
 
47
27
# List of fields returned as part of the user JSON dictionary
48
28
# (as returned by the get_user action)
49
29
user_fields_list = (
50
30
    "login", "state", "unixid", "email", "nick", "fullname",
51
 
    "admin", "studentid", "acct_exp", "pass_exp", "last_login",
 
31
    "rolenm", "studentid", "acct_exp", "pass_exp", "last_login",
52
32
    "svn_pass"
53
33
)
54
34
 
56
36
    """
57
37
    A REST interface to the user object.
58
38
    """
 
39
    def __init__(self, req, login):
 
40
        super(UserRESTView, self).__init__(self, req, login)
 
41
        self.context = ivle.database.User.get_by_login(req.store, login)
 
42
        if self.context is None:
 
43
            raise NotFound()
59
44
 
60
45
    @require_permission('view')
61
46
    def GET(self, req):
69
54
        user['local_password'] = self.context.passhash is not None
70
55
        return user
71
56
 
72
 
class UserEditSchema(formencode.Schema):
73
 
    nick = formencode.validators.UnicodeString(not_empty=True)
74
 
    email = formencode.validators.Email(not_empty=False,
75
 
                                        if_missing=None)
76
 
 
77
 
class UserEditView(XHTMLView):
78
 
    """A form to change a user's details."""
79
 
    template = 'templates/user-edit.html'
80
 
    tab = 'settings'
81
 
    permission = 'edit'
82
 
 
83
 
    def filter(self, stream, ctx):
84
 
        return stream | HTMLFormFiller(data=ctx['data'])
85
 
 
86
 
    def populate(self, req, ctx):
87
 
        if req.method == 'POST':
88
 
            data = dict(req.get_fieldstorage())
89
 
            try:
90
 
                validator = UserEditSchema()
91
 
                data = validator.to_python(data, state=req)
92
 
                self.context.nick = data['nick']
93
 
                self.context.email = unicode(data['email']) if data['email'] \
94
 
                                     else None
95
 
                req.store.commit()
96
 
                req.throw_redirect(req.uri)
97
 
            except formencode.Invalid, e:
98
 
                errors = e.unpack_errors()
99
 
        else:
100
 
            data = {'nick': self.context.nick,
101
 
                    'email': self.context.email
102
 
                   }
103
 
            errors = {}
104
 
 
105
 
        ctx['format_datetime'] = ivle.date.make_date_nice
106
 
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
107
 
 
108
 
        ctx['req'] = req
109
 
        ctx['user'] = self.context
110
 
        ctx['data'] = data
111
 
        ctx['errors'] = errors
112
 
 
113
 
class UserAdminSchema(formencode.Schema):
114
 
    admin = formencode.validators.StringBoolean(if_missing=False)
115
 
    fullname = formencode.validators.UnicodeString(not_empty=True)
116
 
    studentid = formencode.validators.UnicodeString(not_empty=False,
117
 
                                                    if_missing=None
118
 
                                                    )
119
 
 
120
 
class UserAdminView(XHTMLView):
121
 
    """A form for admins to change more of a user's details."""
122
 
    template = 'templates/user-admin.html'
123
 
    tab = 'settings'
124
 
 
125
 
    def authorize(self, req):
126
 
        """Only allow access if the requesting user is an admin."""
127
 
        return req.user.admin
128
 
 
129
 
    def filter(self, stream, ctx):
130
 
        return stream | HTMLFormFiller(data=ctx['data'])
131
 
 
132
 
    def populate(self, req, ctx):
133
 
        if req.method == 'POST':
134
 
            data = dict(req.get_fieldstorage())
135
 
            try:
136
 
                validator = UserAdminSchema()
137
 
                data = validator.to_python(data, state=req)
138
 
 
139
 
                self.context.admin = data['admin']
140
 
                self.context.fullname = data['fullname'] \
141
 
                                        if data['fullname'] else None
142
 
                self.context.studentid = data['studentid'] \
143
 
                                         if data['studentid'] else None
144
 
                req.store.commit()
145
 
                req.throw_redirect(req.uri)
146
 
            except formencode.Invalid, e:
147
 
                errors = e.unpack_errors()
148
 
        else:
149
 
            data = {'admin': self.context.admin,
150
 
                    'fullname': self.context.fullname,
151
 
                    'studentid': self.context.studentid,
152
 
                   }
153
 
            errors = {}
154
 
 
155
 
        ctx['req'] = req
156
 
        ctx['user'] = self.context
157
 
        ctx['data'] = data
158
 
        ctx['errors'] = errors
159
 
 
160
 
class PasswordChangeView(XHTMLView):
161
 
    """A form to change a user's password, with knowledge of the old one."""
162
 
    template = 'templates/user-password-change.html'
163
 
    tab = 'settings'
164
 
    permission = 'edit'
165
 
 
166
 
    def authorize(self, req):
167
 
        """Only allow access if the requesting user holds the permission,
168
 
           and the target user has a password set. Otherwise we might be
169
 
           clobbering external authn.
170
 
        """
171
 
        return super(PasswordChangeView, self).authorize(req) and \
172
 
               self.context.passhash is not None
173
 
 
174
 
    def populate(self, req, ctx):
175
 
        error = None
176
 
        if req.method == 'POST':
177
 
            data = dict(req.get_fieldstorage())
178
 
            if data.get('old_password') is None or \
179
 
               not self.context.authenticate(data.get('old_password')):
180
 
                error = 'Incorrect password.'
181
 
            elif data.get('new_password') != data.get('new_password_again'):
182
 
                error = 'New passwords do not match.'
183
 
            elif not data.get('new_password'):
184
 
                error = 'New password cannot be empty.'
185
 
            else:
186
 
                self.context.password = data['new_password']
187
 
                req.store.commit()
188
 
                req.throw_redirect(req.uri)
189
 
 
190
 
        ctx['req'] = req
191
 
        ctx['user'] = self.context
192
 
        ctx['error'] = error
193
 
 
194
 
class PasswordResetView(XHTMLView):
195
 
    """A form to reset a user's password, without knowledge of the old one."""
196
 
    template = 'templates/user-password-reset.html'
197
 
    tab = 'settings'
198
 
 
199
 
    def authorize(self, req):
200
 
        """Only allow access if the requesting user is an admin."""
201
 
        return req.user.admin
202
 
 
203
 
    def populate(self, req, ctx):
204
 
        error = None
205
 
        if req.method == 'POST':
206
 
            data = dict(req.get_fieldstorage())
207
 
            if data.get('new_password') != data.get('new_password_again'):
208
 
                error = 'New passwords do not match.'
209
 
            elif not data.get('new_password'):
210
 
                error = 'New password cannot be empty.'
211
 
            else:
212
 
                self.context.password = data['new_password']
213
 
                req.store.commit()
214
 
                req.throw_redirect(req.uri)
215
 
 
216
 
        ctx['user'] = self.context
217
 
        ctx['error'] = error
 
57
class UserSettingsView(XHTMLView):
 
58
    template = 'user-settings.html'
 
59
    appname = 'settings'
 
60
    permission = 'edit'
 
61
 
 
62
    def __init__(self, req, login):
 
63
        self.context = ivle.database.User.get_by_login(req.store, login)
 
64
        if self.context is None:
 
65
            raise NotFound()
 
66
 
 
67
    def populate(self, req, ctx):
 
68
        self.plugin_scripts[Plugin] = ['settings.js']
 
69
        req.scripts_init = ['revert_settings']
 
70
 
 
71
        ctx['login'] = self.context.login
218
72
 
219
73
class Plugin(ViewPlugin, MediaPlugin):
220
74
    """
221
75
    The Plugin class for the user plugin.
222
76
    """
223
 
 
224
 
    forward_routes = (root_to_user,)
225
 
    reverse_routes = (user_url,)
226
 
    views = [(ApplicationRoot, 'users', UsersView),
227
 
             (ivle.database.User, '+index', UserEditView),
228
 
             (ivle.database.User, '+admin', UserAdminView),
229
 
             (ivle.database.User, '+changepassword', PasswordChangeView),
230
 
             (ivle.database.User, '+resetpassword', PasswordResetView),
231
 
             (ivle.database.User, '+index', UserRESTView, 'api'),
232
 
             ]
233
 
 
234
 
    public_forward_routes = forward_routes
235
 
    public_reverse_routes = reverse_routes
 
77
    # Magic attribute: urls
 
78
    # Sequence of pairs/triples of
 
79
    # (regex str, handler class, kwargs dict)
 
80
    # The kwargs dict is passed to the __init__ of the view object
 
81
    urls = [
 
82
        ('~:login/+settings', UserSettingsView),
 
83
        ('api/~:login', UserRESTView),
 
84
    ]
236
85
 
237
86
    media = 'user-media'