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

« back to all changes in this revision

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

  • Committer: William Grant
  • Date: 2009-05-31 01:30:23 UTC
  • mto: (1281.1.8 aufsless)
  • mto: This revision was merged to the branch mainline in revision 1300.
  • Revision ID: grantw@unimelb.edu.au-20090531013023-8pril9e3e1tol9b2
Don't hide exceptions encountered in ivle-remakeuser.

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
 
from ivle.webapp.base.forms import BaseFormView
 
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
30
 
import ivle.date
31
 
 
32
 
 
33
 
class UsersView(XHTMLView):
34
 
    """A list of all IVLE users."""
35
 
    template = 'templates/users.html'
36
 
    tab = 'users'
37
 
    breadcrumb_text = 'Users'
38
 
 
39
 
    def authorize(self, req):
40
 
        return req.user and 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
 
class UserEditSchema(formencode.Schema):
48
 
    nick = formencode.validators.UnicodeString(not_empty=True)
49
 
    email = formencode.validators.Email(not_empty=False,
50
 
                                        if_missing=None)
51
 
 
52
 
class UserEditView(BaseFormView):
53
 
    """A form to change a user's details."""
54
 
    template = 'templates/user-edit.html'
55
 
    tab = 'users'
56
 
    permission = 'edit'
57
 
 
58
 
    @property
59
 
    def validator(self):
60
 
        return UserEditSchema()
61
 
 
62
 
    def get_default_data(self, req):
63
 
        return {'nick': self.context.nick,
64
 
                'email': self.context.email
65
 
                }
66
 
 
67
 
    def save_object(self, req, data):
68
 
        self.context.nick = data['nick']
69
 
        self.context.email = unicode(data['email']) if data['email'] \
70
 
                             else None
71
 
        return self.context
72
 
 
73
 
    def populate(self, req, ctx):
74
 
        super(UserEditView, self).populate(req, ctx)
75
 
        ctx['format_datetime'] = ivle.date.make_date_nice
76
 
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
77
 
 
78
 
 
79
 
class UserAdminSchema(formencode.Schema):
80
 
    admin = formencode.validators.StringBoolean(if_missing=False)
81
 
    disabled = formencode.validators.StringBoolean(if_missing=False)
82
 
    fullname = formencode.validators.UnicodeString(not_empty=True)
83
 
    studentid = formencode.validators.UnicodeString(not_empty=False,
84
 
                                                    if_missing=None
85
 
                                                    )
86
 
 
87
 
class UserAdminView(BaseFormView):
88
 
    """A form for admins to change more of a user's details."""
89
 
    template = 'templates/user-admin.html'
90
 
    tab = 'users'
91
 
 
92
 
    def authorize(self, req):
93
 
        """Only allow access if the requesting user is an admin."""
94
 
        return req.user and req.user.admin
95
 
 
96
 
    @property
97
 
    def validator(self):
98
 
        return UserAdminSchema()
99
 
 
100
 
    def get_default_data(self, req):
101
 
        return {'admin': self.context.admin,
102
 
                'disabled': self.context.state == u'disabled',
103
 
                'fullname': self.context.fullname,
104
 
                'studentid': self.context.studentid,
105
 
                }
106
 
 
107
 
    def save_object(self, req, data):
108
 
        if self.context is req.user:
109
 
            # Admin checkbox is disabled -- assume unchanged
110
 
            data['admin'] = self.context.admin
111
 
            data['disabled'] = self.context.state == u'disabled'
112
 
        else:
113
 
            self.context.admin = data['admin']
114
 
            if self.context.state in (u'enabled', u'disabled'):
115
 
                self.context.state = (u'disabled' if data['disabled']
116
 
                        else u'enabled')
117
 
        self.context.fullname = data['fullname'] \
118
 
                                if data['fullname'] else None
119
 
        self.context.studentid = data['studentid'] \
120
 
                                 if data['studentid'] else None
121
 
        return self.context
122
 
 
123
 
    def populate(self, req, ctx):
124
 
        super(UserAdminView, self).populate(req, ctx)
125
 
 
126
 
        # Disable the admin checkbox if editing oneself
127
 
        ctx['disable_admin'] = self.context is req.user
128
 
 
129
 
class PasswordChangeView(XHTMLView):
130
 
    """A form to change a user's password, with knowledge of the old one."""
131
 
    template = 'templates/user-password-change.html'
132
 
    tab = 'users'
133
 
    permission = 'edit'
134
 
 
135
 
    def authorize(self, req):
136
 
        """Only allow access if the requesting user holds the permission,
137
 
           and the target user has a password set. Otherwise we might be
138
 
           clobbering external authn.
139
 
        """
140
 
        return super(PasswordChangeView, self).authorize(req) and \
141
 
               self.context.passhash is not None
142
 
 
143
 
    def populate(self, req, ctx):
144
 
        error = None
145
 
        if req.method == 'POST':
146
 
            data = dict(req.get_fieldstorage())
147
 
            if data.get('old_password') is None or \
148
 
               not self.context.authenticate(data.get('old_password')):
149
 
                error = 'Incorrect password.'
150
 
            elif data.get('new_password') != data.get('new_password_again'):
151
 
                error = 'New passwords do not match.'
152
 
            elif not data.get('new_password'):
153
 
                error = 'New password cannot be empty.'
154
 
            else:
155
 
                self.context.password = data['new_password']
156
 
                req.store.commit()
157
 
                req.throw_redirect(req.uri)
158
 
 
159
 
        ctx['req'] = req
160
 
        ctx['user'] = self.context
161
 
        ctx['error'] = error
162
 
 
163
 
class PasswordResetView(XHTMLView):
164
 
    """A form to reset a user's password, without knowledge of the old one."""
165
 
    template = 'templates/user-password-reset.html'
166
 
    tab = 'users'
167
 
 
168
 
    def authorize(self, req):
169
 
        """Only allow access if the requesting user is an admin."""
170
 
        return req.user and req.user.admin
171
 
 
172
 
    def populate(self, req, ctx):
173
 
        error = None
174
 
        if req.method == 'POST':
175
 
            data = dict(req.get_fieldstorage())
176
 
            if data.get('new_password') != data.get('new_password_again'):
177
 
                error = 'New passwords do not match.'
178
 
            elif not data.get('new_password'):
179
 
                error = 'New password cannot be empty.'
180
 
            else:
181
 
                self.context.password = data['new_password']
182
 
                req.store.commit()
183
 
                req.throw_redirect(req.uri)
184
 
 
185
 
        ctx['user'] = self.context
186
 
        ctx['error'] = error
 
23
from ivle.webapp.errors import NotFound, Unauthorized
 
24
import ivle.database
 
25
import ivle.util
 
26
 
 
27
# List of fields returned as part of the user JSON dictionary
 
28
# (as returned by the get_user action)
 
29
user_fields_list = (
 
30
    "login", "state", "unixid", "email", "nick", "fullname",
 
31
    "admin", "studentid", "acct_exp", "pass_exp", "last_login",
 
32
    "svn_pass"
 
33
)
 
34
 
 
35
class UserRESTView(JSONRESTView):
 
36
    """
 
37
    A REST interface to the user object.
 
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()
 
44
 
 
45
    @require_permission('view')
 
46
    def GET(self, req):
 
47
        # XXX Check Caps
 
48
        user = ivle.util.object_to_dict(user_fields_list, self.context)
 
49
        # Convert time stamps to nice strings
 
50
        for k in 'pass_exp', 'acct_exp', 'last_login':
 
51
            if user[k] is not None:
 
52
                user[k] = unicode(user[k])
 
53
 
 
54
        user['local_password'] = self.context.passhash is not None
 
55
        return user
 
56
 
 
57
class UserSettingsView(XHTMLView):
 
58
    template = 'templates/user-settings.html'
 
59
    tab = '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
187
72
 
188
73
class Plugin(ViewPlugin, MediaPlugin):
189
74
    """
190
75
    The Plugin class for the user plugin.
191
76
    """
192
 
 
193
 
    forward_routes = (root_to_user,)
194
 
    reverse_routes = (user_url,)
195
 
    views = [(ApplicationRoot, 'users', UsersView),
196
 
             (User, '+index', UserEditView),
197
 
             (User, '+admin', UserAdminView),
198
 
             (User, '+changepassword', PasswordChangeView),
199
 
             (User, '+resetpassword', PasswordResetView),
200
 
             ]
201
 
 
202
 
    tabs = [
203
 
        ('users', 'Users', 'Display and edit all users',
204
 
         'users.png', 'users', 90, True)
 
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),
205
84
    ]
206
85
 
207
 
    public_forward_routes = forward_routes
208
 
    public_reverse_routes = reverse_routes
209
 
 
210
86
    media = 'user-media'