-
Notifications
You must be signed in to change notification settings - Fork 1
/
user_resource.inc
executable file
·987 lines (895 loc) · 31.9 KB
/
user_resource.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
<?php
function _user_resource_definition() {
$definition = array(
'user' => array(
'operations' => array(
'retrieve' => array(
'help' => 'Retrieve a user',
'callback' => '_user_resource_retrieve',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'access callback' => '_user_resource_access',
'access arguments' => array('view'),
'access arguments append' => TRUE,
'args' => array(
array(
'name' => 'uid',
'type' => 'int',
'description' => 'The uid of the user to retrieve.',
'source' => array('path' => 0),
'optional' => FALSE,
),
),
),
'create' => array(
'help' => 'Create a user',
'callback' => '_user_resource_create',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'access callback' => '_user_resource_access',
'access arguments' => array('create'),
'access arguments append' => FALSE,
'args' => array(
array(
'name' => 'account',
'type' => 'array',
'description' => 'The user object',
'source' => 'data',
'optional' => FALSE,
),
),
),
'update' => array(
'help' => 'Update a user',
'callback' => '_user_resource_update',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'access callback' => '_user_resource_access',
'access arguments' => array('update'),
'access arguments append' => TRUE,
'args' => array(
array(
'name' => 'uid',
'type' => 'int',
'description' => 'Unique identifier for this user',
'source' => array('path' => 0),
'optional' => FALSE,
),
array(
'name' => 'data',
'type' => 'array',
'description' => 'The user object with updated information',
'source' => 'data',
'optional' => FALSE,
),
),
),
'delete' => array(
'help' => 'Delete a user',
'callback' => '_user_resource_delete',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'access callback' => '_user_resource_access',
'access arguments' => array('delete'),
'access arguments append' => TRUE,
'args' => array(
array(
'name' => 'uid',
'type' => 'int',
'description' => 'The id of the user to delete',
'source' => array('path' => 0),
'optional' => FALSE,
),
),
),
'get_index' => array(
'help' => 'Get user id from its card id',
'callback' => '_user_resource_get_index',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
/*'access callback' => '_user_resource_access',
'access arguments' => array('cidtoindex'),
'access arguments append' => TRUE,*/
'args' => array(
array(
'name' => 'cid',
'optional' => FALSE,
'type' => 'string',
'source' => array('data' => 'cid'),
'description' => 'The card id.',
),
),
),
'index' => array(
'help' => 'List all users',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'callback' => '_user_resource_index',
'args' => array(
array(
'name' => 'page',
'optional' => TRUE,
'type' => 'int',
'description' => 'The zero-based index of the page to get, defaults to 0.',
'default value' => 0,
'source' => array('param' => 'page'),
),
array(
'name' => 'fields',
'optional' => TRUE,
'type' => 'string',
'description' => 'The fields to get.',
'default value' => '*',
'source' => array('param' => 'fields'),
),
array(
'name' => 'parameters',
'optional' => TRUE,
'type' => 'array',
'description' => 'Parameters',
'default value' => array(),
'source' => array('param' => 'parameters'),
),
array(
'name' => 'pagesize',
'optional' => TRUE,
'type' => 'int',
'description' => 'Number of records to get per page.',
'default value' => variable_get('services_user_index_page_size', 20),
'source' => array('param' => 'pagesize'),
),
),
'access arguments' => array('access user profiles'),
'access arguments append' => FALSE,
),
),
'actions' => array(
'login' => array(
'help' => 'Login a user for a new session',
'callback' => '_user_resource_login',
'args' => array(
array(
'name' => 'username',
'type' => 'string',
'description' => 'A valid username',
'source' => array('data' => 'username'),
'optional' => FALSE,
),
array(
'name' => 'password',
'type' => 'string',
'description' => 'A valid password',
'source' => array('data' => 'password'),
'optional' => FALSE,
),
),
'access callback' => 'services_access_menu',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
),
'logout' => array(
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'help' => 'Logout a user session',
'callback' => '_user_resource_logout',
'access callback' => 'services_access_menu',
),
'token' => array(
'file' => array(
'type' => 'inc',
'module' => 'services',
'name' => 'user_resource',
),
'callback' => '_user_resource_get_token',
'access callback' => 'services_access_menu',
'help' => t('Returns the CSRF token.'),
),
'request_new_password' => array(
'help' => 'Request a new password, given a user name or e-mail address',
'callback' => '_user_resource_request_new_password',
'args' => array(
array(
'name' => 'name',
'type' => 'string',
'description' => 'A valid user name or e-mail address',
'source' => array('data' => 'name'),
'optional' => FALSE,
),
),
'access callback' => 'services_access_menu',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
),
),
'targeted_actions' => array(
'cancel' => array(
'help' => 'Cancel a user',
'callback' => '_user_resource_cancel',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource'),
'access callback' => '_user_resource_access',
'access arguments' => array('cancel'),
'access arguments append' => TRUE,
'args' => array(
array(
'name' => 'uid',
'optional' => FALSE,
'source' => array('path' => 0),
'type' => 'int',
'description' => 'The id of the user to cancel.',
),
),
),
'password_reset' => array(
'access callback' => '_user_resource_access',
'access arguments' => array('password_reset'),
'access arguments append' => TRUE,
'callback' => '_user_resource_password_reset',
'args' => array(
array(
'name' => 'uid',
'optional' => FALSE,
'source' => array('path' => 0),
'type' => 'int',
'description' => 'The id of the user whose password to reset.',
),
),
),
'resend_welcome_email' => array(
'access callback' => '_user_resource_access',
'access arguments' => array('resend_welcome_email'),
'access arguments append' => TRUE,
'callback' => '_user_resource_resend_welcome_email',
'args' => array(
array(
'name' => 'uid',
'optional' => FALSE,
'source' => array('path' => 0),
'type' => 'int',
'description' => 'The id of the user whose welcome email to resend.',
),
),
),
),
),
);
$definition['user']['actions']['register'] = array_merge($definition['user']['operations']['create'], array(
'help' => 'Register a user',
));
return $definition;
}
/**
* Get user details.
*
* @param $uid
* UID of the user to be loaded.
*
* @return
* A user object.
*
* @see user_load()
*/
function _user_resource_retrieve($uid) {
$account = user_load($uid);
if (empty($account)) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $uid)), 404);
}
services_remove_user_data($account);
// Everything went right.
return $account;
}
/**
* Create a new user.
*
* This function uses drupal_form_submit() and as such expects all input to match
* the submitting form in question.
*
* @param $account
* A object containing account information. The $account object should
* contain, at minimum, the following properties:
* - name (user name)
* - mail (email address)
* - pass (plain text unencrypted password)
*
* These properties can be passed but are optional
* - status (0 for blocked, otherwise will be active by default)
* - notify (1 to notify user of new account, will not notify by default)
*
* Roles can be passed in a roles property which is an associative
* array formatted with '<role id>' => '<role id>', not including
* the authenticated user role, which is given by default.
*
* @return
* The user object of the newly created user.
*/
function _user_resource_create($account) {
// Adds backwards compatability with regression fixed in #1083242
$account = _services_arg_value($account, 'account');
// Load the required includes for saving profile information
// with drupal_form_submit().
module_load_include('inc', 'user', 'user.pages');
// Register a new user.
$form_state['values'] = $account;
// Determine the password(s). Passwords may not be available as this callback
// is used for registration as well.
$pass1 = '';
$pass2 = '';
if (isset($account['pass'])) {
// For legacy usage, passwords come in as a single string. To match the
// actual form state value keys used by Drupal, we also can collect two
// passwords via an array.
if (is_array($account['pass'])) {
$pass1 = $account['pass']['pass1'];
$pass2 = $account['pass']['pass2'];
}
else {
$pass1 = $account['pass'];
$pass2 = $account['pass'];
}
}
$form_state['values']['pass'] = array(
'pass1' => $pass1,
'pass2' => $pass2
);
// Set the form state op.
$form_state['values']['op'] = variable_get('services_user_create_button_resource_create', t('Create new account'));
// execute the register form
$form_state['programmed_bypass_access_check'] = FALSE;
drupal_form_submit('user_register_form', $form_state);
// find and store the new user into the form_state
if(isset($form_state['values']['uid'])) {
$form_state['user'] = user_load($form_state['values']['uid']);
}
// Error if needed.
if ($errors = form_get_errors()) {
return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
}
else {
$user = array('uid' => $form_state['user']->uid);
if ($uri = services_resource_uri(array('user', $user['uid']))) {
$user['uri'] = $uri;
}
_user_resource_update_services_user($user['uid'], time());
return $user;
}
}
/**
* Update an existing user.
*
* This function uses drupal_form_submit() and as such expects all input to match
* the submitting form in question.
*
* @param $uid
* Unique identifier for this user
* @param $account
* Fields to modify for this user.
*
* @return
* The modified user object.
*/
function _user_resource_update($uid, $account) {
// Adds backwards compatability with regression fixed in #1083242
$account = _services_arg_value($account, 'data');
$account['uid'] = $uid;
$account_loaded = user_load($uid);
// Load the required includes for saving profile information
// with drupal_form_submit().
module_load_include('inc', 'user', 'user.pages');
// If a profile category was passed in, use it. Otherwise default
// to 'account' (for saving core user data.)
$category = 'account';
if (isset($account['category'])) {
$category = $account['category'];
unset($account['category']);
}
// Drop any passed in values into the $account var. Anything
// unused by the form just gets ignored. We handle roles and
// password separately.
foreach ($account as $key => $value) {
if ($key != 'pass' && $key != 'roles') {
$form_state['values'][$key] = $value;
}
}
// Prepare values of roles. Check user's permission before allowing changes to roles.
if (!isset($account['roles']) || !user_access('administer users')) {
$account['roles'] = $account_loaded->roles;
}
foreach ($account['roles'] as $key => $value) {
if (!empty($value)) {
$form_state['values']['roles'][$key] = $key;
}
}
unset($form_state['values']['roles'][2]);
// Prepare values for password.
if (isset($account['pass'])) {
$form_state['values']['pass']['pass1'] = $account['pass'];
$form_state['values']['pass']['pass2'] = $account['pass'];
}
// If user is changing name, make sure they have permission.
if (isset($account['name']) && $account['name'] != $account_loaded->name && !(user_access('change own username') || user_access('administer users'))) {
return services_error(t('You are not allowed to change your username.'), 406);
}
$form_state['values']['op'] = variable_get('services_user_save_button_resource_update', t('Save'));
$form_state['values']['#user_category'] = $category;
$form_state['values']['#account'] = $account_loaded;
$form_state['programmed_bypass_access_check'] = FALSE;
$ret = drupal_form_submit('user_profile_form', $form_state, $account_loaded, $category);
// Error if needed.
if ($errors = form_get_errors()) {
return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
}
else {
$account = (object) $account;
services_remove_user_data($account);
$account = (array) $account;
_user_resource_update_services_user($uid, time());
return $account;
}
}
function _user_resource_update_services_user($uid, $time) {
//Determine if a row exists, if not that means we are creating the user,
//If so that means we are updating it.
$result = db_select('services_user', 'su')
->fields('su')
->condition('uid', $uid,'=')
->execute()
->fetchAssoc();
//check the result
if (!$result) {
$id = db_insert('services_user')
->fields(array(
'uid' => $uid,
'created' => $time,
'changed' => $time,
))
->execute();
} else {
db_update('services_user')
->fields(array(
'uid' => $uid,
'changed' => $time,
)
)
->execute();
}
}
/**
* Delete a user.
*
* @param $uid
* UID of the user to be deleted.
*
* @see user_delete()
*/
function _user_resource_delete($uid) {
if ($uid == 1) {
return services_error(t('The admin user cannot be deleted.'), 403);
}
$account = user_load($uid);
if (empty($account)) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $uid)), 404);
}
user_delete($uid);
// Everything went right.
return TRUE;
}
/**
* Cancel a user.
*
* @param $uid
* UID of the user to be canceled.
*
* @see user_cancel()
*/
function _user_resource_cancel($uid) {
if ($uid == 1) {
return services_error(t('The admin user cannot be canceled.'), 403);
}
$account = user_load($uid);
if (empty($account)) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $uid)), 404);
}
$edit = array(
'user_cancel_notify' => isset($account->data['user_cancel_notify']) ? $account->data['user_cancel_notify'] : variable_get('user_mail_status_canceled_notify', FALSE),
);
// This defult setting is defined under "admin/config/people/accounts".
$default_method = variable_get('user_cancel_method', 'user_cancel_block');
switch ($default_method) {
case 'user_cancel_block_unpublish':
// Unpublish nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
$nodes = db_select('node', 'n')->fields('n', array('nid'))->condition('uid', $account->uid)->execute()->fetchCol();
node_mass_update($nodes, array('status' => 0));
break;
case 'user_cancel_reassign':
// Anonymize nodes (current revisions).
module_load_include('inc', 'node', 'node.admin');
$nodes = db_select('node', 'n')->fields('n', array('nid'))->condition('uid', $account->uid)->execute()->fetchCol();
node_mass_update($nodes, array('uid' => 0));
// Anonymize old revisions.
db_update('node_revision')->fields(array('uid' => 0))->condition('uid', $account->uid)->execute();
// Clean history.
db_delete('history')->condition('uid', $account->uid)->execute();
break;
}
_user_cancel($edit, $account, $default_method);
// Everything went right.
return TRUE;
}
/**
* Login a user using the specified credentials.
*
* Note this will transfer a plaintext password.
*
* @param $username
* Username to be logged in.
* @param $password
* Password, must be plain text and not hashed.
*
* @return
* A valid session object.
*/
function _user_resource_login($username, $password) {
global $user;
if ($user->uid) {
// user is already logged in
return services_error(t('Already logged in as @user.', array('@user' => $user->name)), 406);
}
// Check if account is active.
if (user_is_blocked($username)) {
return services_error(t('The username %name has not been activated or is blocked.', array('%name' => $username)), 403);
}
// Emulate drupal native flood control: check for flood condition.
$flood_state = array();
if (variable_get('services_flood_control_enabled', TRUE)) {
$flood_state = _user_resource_flood_control_precheck($username);
}
// Only authenticate if a flood condition was not detected.
if (empty($flood_state['flood_control_triggered'])) {
$uid = user_authenticate($username, $password);
}
else {
$uid = FALSE;
}
// Emulate drupal native flood control: register flood event, and throw error
// if a flood condition was previously detected
if (variable_get('services_flood_control_enabled', TRUE)) {
$flood_state['uid'] = $uid;
_user_resource_flood_control_postcheck($flood_state);
}
if ($uid) {
$user = user_load($uid);
if ($user->uid) {
user_login_finalize();
$return = new stdClass();
$return->sessid = session_id();
$return->session_name = session_name();
$return->token = drupal_get_token('services');
$account = clone $user;
services_remove_user_data($account);
$return->user = $account;
return $return;
}
}
watchdog('user', 'Invalid login attempt for %username.', array('%username' => $username));
return services_error(t('Wrong username or password.'), 401);
}
/**
* Logout the current user.
*/
function _user_resource_logout() {
global $user;
if (!$user->uid) {
// User is not logged in
return services_error(t('User is not logged in.'), 406);
}
watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
// Destroy the current session.
module_invoke_all('user_logout', $user);
session_destroy();
// Load the anonymous user.
$user = drupal_anonymous_user();
return TRUE;
}
/**
* Update the current user logout callback to the new callback with a better return value.
*/
function _user_resource_logout_update_1_1() {
$new_set = array(
'callback' => '_user_resource_logout_1_1',
);
return $new_set;
}
/**
* Logs out the currently logged in user and returns the new user object.
*/
function _user_resource_logout_1_1() {
global $user;
if (!$user->uid) {
// User is not logged in
return services_error(t('User is not logged in.'), 406);
}
watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
// Destroy the current session.
module_invoke_all('user_logout', $user);
session_destroy();
// Load the anonymous user.
$user = drupal_anonymous_user();
return $user;
}
/**
* Request a new password given a user name or e-mail address.
*
* @param $name
* The username or e-mail address of the requesting account.
*
* @see https://api.drupal.org/api/drupal/modules!user!user.pages.inc/function/user_pass_validate/7
* @see https://api.drupal.org/api/drupal/modules!user!user.pages.inc/function/user_pass_submit/7
*/
function _user_resource_request_new_password($name) {
$name = trim($name);
// Try to load by email.
$users = user_load_multiple(array(), array('mail' => $name, 'status' => '1'));
$account = reset($users);
if (!$account) {
// No success, try to load by name.
$users = user_load_multiple(array(), array('name' => $name, 'status' => '1'));
$account = reset($users);
}
if (!isset($account->uid)) {
return services_error(t('Sorry, %name is not recognized as a user name or an e-mail address.', array('%name' => $name)), 406);
}
// Mail one time login URL and instructions using current language.
global $language;
$mail = _user_mail_notify('password_reset', $account, $language);
if (!empty($mail)) {
watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
return TRUE;
}
else {
return FALSE;
}
}
/**
* Send a password reset email for the specified user.
*/
function _user_resource_password_reset($uid) {
global $language;
$account = user_load($uid);
if (empty($account)) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $uid)), 404);
}
// Mail one time login URL and instructions using current language.
$mail = _user_mail_notify('password_reset', $account, $language);
if (!empty($mail)) {
watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
}
else {
watchdog('user', 'There was an error re-sending password reset instructions mailed to %name at %email', array('%name' => $account->name, '%email' => $account->mail));
}
// Everything went right.
return TRUE;
}
/**
* Send a welcome email for the specified user.
*/
function _user_resource_resend_welcome_email($uid) {
global $language;
$account = user_load($uid);
if (empty($account)) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $uid)), 404);
}
$user_register = variable_get('user_register', 2);
switch ($user_register) {
case USER_REGISTER_ADMINISTRATORS_ONLY:
$op = 'register_admin_created';
break;
case USER_REGISTER_VISITORS:
$op = 'register_no_approval_required';
break;
case USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL:
$op = 'register_pending_approval';
}
// Mail the welcome emaiil using current language.
$mail = _user_mail_notify($op, $account, $language);
if (!empty($mail)) {
watchdog('user', 'Welcome message has been re-sent to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
}
else {
watchdog('user', 'There was an error re-sending welcome message to %name at %email', array('%name' => $account->name, '%email' => $account->mail));
}
// Everything went right.
return TRUE;
}
/**
* Return an array of optionally paged uids baed on a set of criteria.
*
* An example request might look like
*
* http://domain/endpoint/user?fields=uid,name,mail¶meters[uid]=1
*
* This would return an array of objects with only uid, name and mail defined,
* where uid = 1.
*
* @param $page
* Page number of results to return (in pages of 20).
* @param $fields
* The fields you want returned.
* @param $parameters
* An array containing fields and values used to build a sql WHERE clause
* indicating items to retrieve.
* @param $page_size
* Integer number of items to be returned.
* @return
* An array of user objects.
*
* @see _node_resource_index() for more notes
*/
function _user_resource_index($page, $fields, $parameters, $page_size) {
$user_select = db_select('users', 't')
->orderBy('created', 'DESC');
services_resource_build_index_query($user_select, $page, $fields, $parameters, $page_size, 'user');
$results = services_resource_execute_index_query($user_select);
return services_resource_build_index_list($results, 'user', 'uid');
}
/**
* Get the user id for the card id.
*/
function _user_resource_get_index($cid) {
$query = db_select('field_data_field_id', 'u')
->fields('u', array('entity_id'))
->condition('u.field_id_value', $cid, '=');
$result = $query->execute();
return $result->fetchField();
/*$result = db_query('SELECT entity_id FROM field_data_field_id WHERE field_id_value = \':cid\'', array(':cid' => $cid))->fetchField();
return $result;*/
}
/**
* Access check callback for user resource.
*/
function _user_resource_access($op = 'view', $args = array()) {
// Adds backwards compatability with regression fixed in #1083242
if (isset($args[0])) {
$args[0] = _services_access_value($args[0], array('account', 'data'));
}
// Check if the user exists if appropriate.
if ($op != 'create' && $op != 'register' ) {
$account = user_load($args[0]);
if (!$account) {
return services_error(t('There is no user with ID @uid.', array('@uid' => $args[0])), 406);
}
}
global $user;
switch ($op) {
case 'get_index':
return TRUE;
case 'view':
return user_view_access($account);
case 'update':
return ($user->uid == $account->uid || user_access('administer users'));
case 'create':
case 'register':
if (!$user->uid && variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) != USER_REGISTER_ADMINISTRATORS_ONLY) {
return TRUE;
}
else {
return user_access('administer users');
}
case 'password_reset':
return TRUE;
case 'delete':
case 'cancel':
case 'resend_welcome_email':
return user_access('administer users');
}
}
/**
* Changes the user/login endpoint to accept the same parameters as the user/register endpoint, namely
* "name" instead of "username" and "pass" instead of "password"
*/
function _user_resource_login_update_1_1() {
$new_set = array(
'args' => array(
array(
'name' => 'name',
'type' => 'string',
'description' => 'A valid username',
'source' => array('data' => 'name'),
'optional' => FALSE,
),
array(
'name' => 'pass',
'type' => 'string',
'description' => 'A valid password',
'source' => array('data' => 'pass'),
'optional' => FALSE,
),
),
);
return $new_set;
}
function _user_resource_get_token() {
return array('token' => drupal_get_token('services'));
}
/**
* Emulate native Drupal flood control, phase 1.
*
* This function checks for a flood condition, and determines the identifier
* for user based flood checks. This is done prior to user authentication.
*
* @param string $username
* The name of the user who is attempting to log in.
* @return array
* An array containing zero or more of the following keys:
* - flood_control_triggered: either 'user' or 'ip' if a flood condition
* was detected.
* - flood_control_user_identifier: the identifier to use to register
* user-based flood events.
*
* @see _user_resource_flood_control_postcheck().
* @see user_login_authenticate_validate().
*/
function _user_resource_flood_control_precheck($username) {
$flood_state = array();
// Do not allow any login from the current user's IP if the limit has been
// reached. Default is 50 failed attempts allowed in one hour. This is
// independent of the per-user limit to catch attempts from one IP to log
// in to many different user accounts. We have a reasonably high limit
// since there may be only one apparent IP for all users at an institution.
if (!flood_is_allowed('failed_login_attempt_ip', variable_get('user_failed_login_ip_limit', 50), variable_get('user_failed_login_ip_window', 3600))) {
$flood_state['flood_control_triggered'] = 'ip';
}
else {
$account = db_query("SELECT * FROM {users} WHERE name = :name AND status = 1", array(':name' => $username))->fetchObject();
if ($account) {
if (variable_get('user_failed_login_identifier_uid_only', FALSE)) {
// Register flood events based on the uid only, so they apply for any
// IP address. This is the most secure option.
$identifier = $account->uid;
}
else {
// The default identifier is a combination of uid and IP address. This
// is less secure but more resistant to denial-of-service attacks that
// could lock out all users with public user names.
$identifier = $account->uid . '-' . ip_address();
}
$flood_state['flood_control_user_identifier'] = $identifier;
// Don't allow login if the limit for this user has been reached.
// Default is to allow 5 failed attempts every 6 hours.
if (!flood_is_allowed('failed_login_attempt_user', variable_get('user_failed_login_user_limit', 5), variable_get('user_failed_login_user_window', 21600), $identifier)) {
$flood_state['flood_control_triggered'] = 'user';
}
}
}
return $flood_state;
}
/**
+ * Emulate native Drupal flood control, phase 2.
+ *
+ * This function records a failed login attempt, and triggers an error if a
+ * flood condition was previously detected.
+ *
+ * @param array $flood_state
+ * An array of flood information as returned by
+ * _user_resource_flood_control_precheck().
+ *
+ * @throws ServicesException
+ * If a flood condition was previously detected.
+ *
+ * @see _user_resource_flood_control_precheck().
+ * @see user_login_final_validate().
+ */
function _user_resource_flood_control_postcheck($flood_state) {
if (empty($flood_state['uid'])) {
// Always register an IP-based failed login event.
flood_register_event('failed_login_attempt_ip', variable_get('user_failed_login_ip_window', 3600));
// Register a per-user failed login event.
if (isset($flood_state['flood_control_user_identifier'])) {
flood_register_event('failed_login_attempt_user', variable_get('user_failed_login_user_window', 21600), $flood_state['flood_control_user_identifier']);
}
if (isset($flood_state['flood_control_triggered'])) {
if ($flood_state['flood_control_triggered'] == 'user') {
services_error(t('Account is temporarily blocked.'), 406);
}
else {
// We did not find a uid, so the limit is IP-based.
services_error(t('This IP address is temporarily blocked.'), 406);
}
}
}
elseif (isset($flood_state['flood_control_user_identifier'])) {
// Clear past failures for this user so as not to block a user who might
// log in and out more than once in an hour.
flood_clear_event('failed_login_attempt_user', $flood_state['flood_control_user_identifier']);
}
}