Skip to content

Commit c12c521

Browse files
authored
Merge pull request catalyst#9 from andrewhancox/master
Add user provisioning and test client code. Close catalyst#9
2 parents 1632d88 + 9ec87b0 commit c12c521

File tree

9 files changed

+430
-19
lines changed

9 files changed

+430
-19
lines changed

README.md

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,70 @@ You can set URL to redirect users before they see Moodle login page. For example
9494
to your web application to login page. You can use "enrolkey_skipsso" URL parameter to bypass this option.
9595
E.g. http://yourmoodle.com/login/index.php?enrolkey_skipsso=1
9696

97+
**Example client**
98+
99+
The code below defines a function that can be used to obtain a login url.
100+
You will need to add/remove parameters depending on whether you have iprestriction or update/create user enabled and which mapping field you are using.
101+
102+
The required library curl.php can be obtained from https://github.com/dongsheng/cURL
103+
```
104+
/**
105+
* @param string $useremail Email address of user to create token for.
106+
* @param string $firstname First name of user (used to update/create user).
107+
* @param string $lastname Last name of user (used to update/create user).
108+
* @param string $username Username of user (used to update/create user).
109+
* @param string $ipaddress IP address of end user that login request will come from (probably $_SERVER['REMOTE_ADDR']).
110+
* @param int $courseid Course id to send logged in users to, defaults to site home.
111+
* @param int $modname Name of course module to send users to, defaults to none.
112+
* @param int $activityid cmid to send logged in users to, defaults to site home.
113+
* @return bool|string
114+
*/
115+
function getloginurl($useremail, $firstname, $lastname, $username, $ipaddress, $courseid = null, $modname = null, $activityid = null) {
116+
require_once('./curl.php');
117+
118+
$token = 'YOUR_TOKEN';
119+
$domainname = 'http://MOODLE_WWW_ROOT';
120+
$functionname = 'auth_userkey_request_login_url';
121+
122+
$param = [
123+
'user' => [
124+
'firstname' => $firstname,
125+
'lastname' => $lastname,
126+
'username' => $username,
127+
'email' => $useremail,
128+
'ip' => $ipaddress
129+
]
130+
];
131+
132+
$serverurl = $domainname . '/webservice/rest/server.php' . '?wstoken=' . $token . '&wsfunction=' . $functionname . '&moodlewsrestformat=json';
133+
$curl = new curl;
134+
135+
try {
136+
$resp = $curl->post($serverurl, $param);
137+
$resp = json_decode($resp);
138+
$loginurl = $resp->loginurl;
139+
} catch (Exception $ex) {
140+
return false;
141+
}
142+
143+
if (!isset($loginurl)) {
144+
return false;
145+
}
146+
147+
$path = '';
148+
if (isset($courseid)) {
149+
$path = '&wantsurl=' . urlencode("$domainname/course/view.php?id=$courseid");
150+
}
151+
if (isset($modname) && isset($activityid)) {
152+
$path = '&wantsurl=' . urlencode("$domainname/mod/$modname/view.php?id=$activityid");
153+
}
154+
155+
return $loginurl . $path;
156+
}
157+
158+
echo getloginurl('barrywhite@googlemail.com', 'barry', 'white', 'barrywhite', '127.0.0.1', 2, 'certificate', 8);
159+
```
97160

98161
TODO:
99162
-----
100-
1. Add users provisioning.
101-
2. Implement logout webservice to be able to call it from external application.
102-
3. Add a test client code to README.
163+
1. Implement logout webservice to be able to call it from external application.

auth.php

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
require_once($CFG->libdir . "/externallib.php");
3131
require_once($CFG->libdir.'/authlib.php');
32+
require_once($CFG->dirroot . '/user/lib.php');
3233

3334
/**
3435
* User key authentication plugin.
@@ -58,7 +59,8 @@ class auth_plugin_userkey extends auth_plugin_base {
5859
'iprestriction' => 0,
5960
'redirecturl' => '',
6061
'ssourl' => '',
61-
// TODO: use this field when implementing user creation. 'createuser' => 0.
62+
'createuser' => false,
63+
'updateuser' => false,
6264
);
6365

6466
/**
@@ -302,6 +304,19 @@ protected function should_create_user() {
302304
return false;
303305
}
304306

307+
/**
308+
* Check if we need to update users.
309+
*
310+
* @return bool
311+
*/
312+
protected function should_update_user() {
313+
if (isset($this->config->updateuser) && $this->config->updateuser == true) {
314+
return true;
315+
}
316+
317+
return false;
318+
}
319+
305320
/**
306321
* Check if restriction by IP is enabled.
307322
*
@@ -323,10 +338,88 @@ protected function is_ip_restriction_enabled() {
323338
* @return object User object.
324339
*/
325340
protected function create_user(array $data) {
326-
// TODO:
327-
// 1. Validate user
328-
// 2. Create user.
329-
// 3. Throw exception if something went wrong.
341+
global $DB, $CFG;
342+
343+
$user = $data;
344+
unset($user['ip']);
345+
$user['auth'] = 'userkey';
346+
$user['mnethostid'] = $CFG->mnet_localhost_id;
347+
348+
$requiredfieds = ['username', 'email', 'firstname', 'lastname'];
349+
$missingfields = [];
350+
foreach ($requiredfieds as $requiredfied) {
351+
if (empty($user[$requiredfied])) {
352+
$missingfields[] = $requiredfied;
353+
}
354+
}
355+
if (!empty($missingfields)) {
356+
throw new invalid_parameter_exception('Unable to create user, missing value(s): ' . implode(',', $missingfields));
357+
}
358+
359+
if ($DB->record_exists('user', array('username' => $user['username'], 'mnethostid' => $CFG->mnet_localhost_id))) {
360+
throw new invalid_parameter_exception('Username already exists: '.$user['username']);
361+
}
362+
if (!validate_email($user['email'])) {
363+
throw new invalid_parameter_exception('Email address is invalid: '.$user['email']);
364+
} else if (empty($CFG->allowaccountssameemail) &&
365+
$DB->record_exists('user', array('email' => $user['email'], 'mnethostid' => $user['mnethostid']))) {
366+
throw new invalid_parameter_exception('Email address already exists: '.$user['email']);
367+
}
368+
369+
$userid = user_create_user($user);
370+
return $DB->get_record('user', ['id' => $userid]);
371+
}
372+
373+
/**
374+
* Update an existing user.
375+
*
376+
* @param stdClass $user Existing user record.
377+
* @param array $data Validated user data from web service.
378+
*
379+
* @return object User object.
380+
*/
381+
protected function update_user(\stdClass $user, array $data) {
382+
global $DB, $CFG;
383+
384+
$userdata = $data;
385+
unset($userdata['ip']);
386+
$userdata['auth'] = 'userkey';
387+
388+
$changed = false;
389+
foreach ($userdata as $key => $value) {
390+
if ($user->$key != $value) {
391+
$changed = true;
392+
break;
393+
}
394+
}
395+
396+
if (!$changed) {
397+
return $user;
398+
}
399+
400+
if (
401+
$user->username != $userdata['username']
402+
&&
403+
$DB->record_exists('user', array('username' => $userdata['username'], 'mnethostid' => $CFG->mnet_localhost_id))
404+
) {
405+
throw new invalid_parameter_exception('Username already exists: '.$userdata['username']);
406+
}
407+
if (!validate_email($userdata['email'])) {
408+
throw new invalid_parameter_exception('Email address is invalid: '.$userdata['email']);
409+
} else if (
410+
empty($CFG->allowaccountssameemail)
411+
&&
412+
$user->email != $userdata['email']
413+
&&
414+
$DB->record_exists('user', array('email' => $userdata['email'], 'mnethostid' => $CFG->mnet_localhost_id))
415+
) {
416+
throw new invalid_parameter_exception('Email address already exists: '.$userdata['email']);
417+
}
418+
$userdata['id'] = $user->id;
419+
420+
$userdata = (object) $userdata;
421+
user_update_user($userdata, false);
422+
return $DB->get_record('user', ['id' => $user->id]);
330423
}
331424

332425
/**
@@ -381,6 +474,8 @@ protected function get_user(array $data) {
381474
} else {
382475
throw new invalid_parameter_exception('User is not exist');
383476
}
477+
} else if ($this->should_update_user()) {
478+
$user = $this->update_user($user, $data);
384479
}
385480

386481
return $user;
@@ -506,7 +601,18 @@ protected function get_user_fields_parameters() {
506601
);
507602
}
508603

509-
// TODO: add more fields here when we implement user creation.
604+
$mappingfield = $this->get_mapping_field();
605+
if ($this->should_create_user() || $this->should_update_user()) {
606+
$parameters['firstname'] = new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL);
607+
$parameters['lastname'] = new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL);
608+
609+
if ($mappingfield != 'email') {
610+
$parameters['email'] = new external_value(PARAM_RAW_TRIMMED, 'A valid and unique email address', VALUE_OPTIONAL);
611+
}
612+
if ($mappingfield != 'username') {
613+
$parameters['username'] = new external_value(PARAM_USERNAME, 'A valid and unique username', VALUE_OPTIONAL);
614+
}
615+
}
510616

511617
return $parameters;
512618
}

classes/userkey_manager_interface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
namespace auth_userkey;
2626

27+
defined('MOODLE_INTERNAL') || die();
28+
2729
/**
2830
* Interface userkey_manager_interface describes key manager behaviour.
2931
*

externallib.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
2323
*/
2424

25+
defined('MOODLE_INTERNAL') || die();
26+
2527
require_once($CFG->libdir . "/externallib.php");
2628
require_once($CFG->dirroot . "/webservice/lib.php");
2729
require_once($CFG->dirroot . "/auth/userkey/auth.php");

lang/en/auth_userkey.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
$string['keylifetime'] = 'User key life time';
3333
$string['keylifetime_desc'] = 'Life time in seconds of the each user login key.';
3434
$string['incorrectkeylifetime'] = 'User key life time should be a number';
35-
$string['createuser'] = 'Crete user?';
35+
$string['createuser'] = 'Create user?';
3636
$string['createuser_desc'] = 'If enabled, a new user will be created if fail to find one in LMS.';
37+
$string['updateuser'] = 'Update user?';
38+
$string['updateuser_desc'] = 'If enabled, users will be updated with the properties supplied when the webservice is called.';
3739
$string['redirecturl'] = 'Logout redirect URL';
3840
$string['redirecturl_desc'] = 'Optionally you can redirect users to this URL after they logged out from LMS.';
3941
$string['incorrectredirecturl'] = 'You should provide valid URL';
@@ -43,3 +45,4 @@
4345
$string['ssourl'] = 'URL of SSO host';
4446
$string['ssourl_desc'] = 'URL of the SSO host to redirect users to. If defined users will be redirected here on login instead of the Moodle Login page';
4547
$string['redirecterrordetected'] = 'Unsupported redirect to {$a} detected, execution terminated.';
48+
$string['noip'] = 'Unable to fetch IP address of client.';

settings.html

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,19 @@
6363
<?php if (isset($err[$field])) { echo $OUTPUT->notification($err[$field], 'notifyfailure'); } ?>
6464
<?php print_string($field.'_desc', 'auth_userkey') ?></td>
6565
</tr>
66-
<!--UNCOMMENT FOLLOWING WHEN IMPLEMENT USER CREATION.-->
67-
<!--<tr valign="top">-->
68-
<!--<?php $field = 'createuser' ?>-->
69-
<!--<td align="right"><label for="<?php echo $field ?>"><?php print_string($field, 'auth_userkey') ?></label></td>-->
70-
<!--<td><?php echo html_writer::select($yesno, $field, $config->$field, false) ?>-->
71-
<!--<?php if (isset($err[$field])) { echo $OUTPUT->notification($err[$field], 'notifyfailure'); } ?>-->
72-
<!--<?php print_string($field.'_desc', 'auth_userkey')?></td>-->
73-
<!--</tr>-->
66+
<tr valign="top">
67+
<?php $field = 'createuser' ?>
68+
<td align="right"><label for="<?php echo $field ?>"><?php print_string($field, 'auth_userkey') ?></label></td>
69+
<td><?php echo html_writer::select($yesno, $field, $config->$field, false) ?>
70+
<?php if (isset($err[$field])) { echo $OUTPUT->notification($err[$field], 'notifyfailure'); } ?>
71+
<?php print_string($field.'_desc', 'auth_userkey')?></td>
72+
</tr>
73+
<tr valign="top">
74+
<?php $field = 'updateuser' ?>
75+
<td align="right"><label for="<?php echo $field ?>"><?php print_string($field, 'auth_userkey') ?></label></td>
76+
<td><?php echo html_writer::select($yesno, $field, $config->$field, false) ?>
77+
<?php if (isset($err[$field])) { echo $OUTPUT->notification($err[$field], 'notifyfailure'); } ?>
78+
<?php print_string($field.'_desc', 'auth_userkey')?></td>
79+
</tr>
7480
</table>
7581

0 commit comments

Comments
 (0)