29
29
# It must do its own authentication and authorization.
33
# The one-and-only path segment to userservice determines the action being
35
# All actions require that you are logged in.
36
# All actions require method = POST, unless otherwise stated.
38
# userservice/activate_me
40
# declaration = "I accept the IVLE Terms of Service"
41
# Activate the currently-logged-in user's account. Requires that "declaration"
42
# is as above, and that the user's state is "no_agreement".
44
# userservice/create_user
45
# Required cap: CAP_CREATEUSER
46
# Arguments are the same as the database columns for the "login" table.
48
# login, fullname, rolenm
50
# password, nick, email, studentid
53
# userservice/get_user
55
# Required cap: None to see yourself.
56
# CAP_GETUSER to see another user.
57
# Gets the login details of a user. Returns as a JSON object.
58
# login = Optional login name of user to get. If omitted, get yourself.
60
# userservice/update_user
61
# Required cap: None to update yourself.
62
# CAP_UPDATEUSER to update another user (and also more fields).
63
# (This is all-powerful so should be only for admins)
64
# login = Optional login name of user to update. If omitted, update yourself.
65
# Other fields are optional, and will set the given field of the user.
66
# Without CAP_UPDATEUSER, you may change the following fields of yourself:
67
# password, nick, email
68
# With CAP_UPDATEUSER, you may also change the following fields of any user:
69
# password, nick, email, login, rolenm, unixid, fullname, studentid
70
# (You can't change "state", but see userservice/[en|dis]able_user).
73
# userservice/enable_user
74
# Required cap: CAP_UPDATEUSER
75
# Enable a user whose account has been disabled. Does not work for
76
# no_agreement or pending users.
77
# login = Login name of user to enable.
80
# userservice/disable_user
81
# Required cap: CAP_UPDATEUSER
82
# Disable a user's account. Does not work for no_agreement or pending users.
83
# login = Login name of user to disable.
79
134
"accepting" the terms - at least this way requires them to acknowledge
80
135
their acceptance). It must only be called through a POST request.
85
if req.method != "POST":
86
req.throw_error(req.HTTP_BAD_REQUEST)
87
fields = req.get_fieldstorage()
89
declaration = fields.getfirst('declaration')
90
except AttributeError:
91
req.throw_error(req.HTTP_BAD_REQUEST)
92
if declaration != USER_DECLARATION:
93
req.throw_error(req.HTTP_BAD_REQUEST)
95
# TODO: Check the DB that the user's status is "no_agreement".
96
# (Both to avoid redundant calls, and to stop disabled users from
97
# re-enabling their accounts).
99
# Get the arguments for usermgt.create_user from the session
100
# (The user must have already logged in to use this app)
101
session = req.get_session()
103
"login": req.username,
105
msg = {'activate_user': args}
107
response = chat.chat(USERMGT_HOST, USERMGT_PORT, msg, USERMGT_MAGIC,
109
# TODO: Figure out a way to let the user be "enabled" in this session.
110
# (Would require a write to the session?)
111
req.content_type = "text/plain"
137
if req.method != "POST":
138
req.throw_error(req.HTTP_BAD_REQUEST)
140
declaration = fields.getfirst('declaration')
141
except AttributeError:
142
req.throw_error(req.HTTP_BAD_REQUEST)
143
if declaration != USER_DECLARATION:
144
req.throw_error(req.HTTP_BAD_REQUEST)
146
session = req.get_session()
147
# Check that the user's status is "no_agreement".
148
# (Both to avoid redundant calls, and to stop disabled users from
149
# re-enabling their accounts).
150
if session['state'] != "no_agreement":
151
req.throw_error(req.HTTP_BAD_REQUEST)
153
# Get the arguments for usermgt.activate_user from the session
154
# (The user must have already logged in to use this app)
156
"login": req.username,
158
msg = {'activate_user': args}
160
response = chat.chat(USERMGT_HOST, USERMGT_PORT, msg, USERMGT_MAGIC,
162
# TODO: Figure out a way to let the user be "enabled" in this session.
163
# (Would require a write to the session?)
164
req.content_type = "text/plain"
167
create_user_fields_required = [
168
'login', 'fullname', 'rolenm'
170
create_user_fields_optional = [
171
'password', 'nick', 'email', 'studentid'
173
def handle_create_user(req, fields):
174
"""Create a new user, whose state is no_agreement.
175
This does not create the user's jail, just an entry in the database which
176
allows the user to accept an agreement.
178
session = req.get_session()
179
if req.method != "POST":
180
req.throw_error(req.HTTP_BAD_REQUEST)
181
# Check if this user has CAP_CREATEUSER
182
if not session['role'].hasCap(caps.CAP_UPDATEUSER):
183
req.throw_error(req.HTTP_FORBIDDEN)
185
# Make a dict of fields to create
187
for f in create_user_fields_required:
189
create[f] = fields.getfirst(f)
190
except AttributeError:
191
req.throw_error(req.HTTP_BAD_REQUEST)
192
for f in create_user_fields_optional:
194
create[f] = fields.getfirst(f)
195
except AttributeError:
198
# Get the arguments for usermgt.create_user from the session
199
# (The user must have already logged in to use this app)
200
msg = {'create_user': create}
206
response = chat.chat(USERMGT_HOST, USERMGT_PORT, msg, USERMGT_MAGIC,
208
req.content_type = "text/plain"
211
update_user_fields_anyone = [
212
'password', 'nick', 'email'
214
update_user_fields_admin = [
215
'password', 'nick', 'email', 'login', 'rolenm', 'unixid', 'fullname',
218
def handle_update_user(req, fields):
219
"""Update a user's account details.
220
This can be done in a limited form by any user, on their own account,
221
or with full powers by a user with CAP_UPDATEUSER on any account.
223
session = req.get_session()
224
if req.method != "POST":
225
req.throw_error(req.HTTP_BAD_REQUEST)
227
# Only give full powers if this user has CAP_UPDATEUSER
228
fullpowers = session['role'].hasCap(caps.CAP_UPDATEUSER)
229
# List of fields that may be changed
230
fieldlist = (update_user_fields_admin if fullpowers
231
else update_user_fields_anyone)
234
login = fields.getfirst('login')
235
if not fullpowers and login != req.username:
236
# Not allowed to edit other users
237
req.throw_error(req.HTTP_FORBIDDEN)
238
except AttributeError:
239
# If login not specified, update yourself
242
# Make a dict of fields to update
246
update[f] = fields.getfirst(f)
247
except AttributeError:
250
# Get the arguments for usermgt.create_user from the session
251
# (The user must have already logged in to use this app)
253
"login": req.username,
256
msg = {'update_user': args}
262
response = chat.chat(USERMGT_HOST, USERMGT_PORT, msg, USERMGT_MAGIC,
264
req.content_type = "text/plain"