source: trunk/include/ws_functions/pwg.users.php @ 31102

Last change on this file since 31102 was 29074, checked in by plg, 10 years ago

bug 3104: less rights for admins (compared to webmaster). Now an admin can't:

  • delete a webmaster
  • give webmaster/admin status to any user
  • change status of a webmaster/admin
File size: 16.8 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24/**
25 * API method
26 * Returns a list of users
27 * @param mixed[] $params
28 *    @option int[] user_id (optional)
29 *    @option string username (optional)
30 *    @option string[] status (optional)
31 *    @option int min_level (optional)
32 *    @option int[] group_id (optional)
33 *    @option int per_page
34 *    @option int page
35 *    @option string order
36 *    @option string display
37 */
38function ws_users_getList($params, &$service)
39{
40  global $conf;
41
42  $where_clauses = array('1=1');
43
44  if (!empty($params['user_id']))
45  {
46    $where_clauses[] = 'u.'.$conf['user_fields']['id'].' IN('. implode(',', $params['user_id']) .')';
47  }
48
49  if (!empty($params['username']))
50  {
51    $where_clauses[] = 'u.'.$conf['user_fields']['username'].' LIKE \''.pwg_db_real_escape_string($params['username']).'\'';
52  }
53
54  if (!empty($params['status']))
55  {
56    $params['status'] = array_intersect($params['status'], get_enums(USER_INFOS_TABLE, 'status'));
57    if (count($params['status']) > 0)
58    {
59      $where_clauses[] = 'ui.status IN("'. implode('","', $params['status']) .'")';
60    }
61  }
62
63  if (!empty($params['min_level']))
64  {
65    if ( !in_array($params['min_level'], $conf['available_permission_levels']) )
66    {
67      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level');
68    }
69    $where_clauses[] = 'ui.level >= '.$params['min_level'];
70  }
71
72  if (!empty($params['group_id']))
73  {
74    $where_clauses[] = 'ug.group_id IN('. implode(',', $params['group_id']) .')';
75  }
76
77  $display = array('u.'.$conf['user_fields']['id'] => 'id');
78
79  if ($params['display'] != 'none')
80  {
81    $params['display'] = array_map('trim', explode(',', $params['display']));
82
83    if (in_array('all', $params['display']))
84    {
85      $params['display'] = array(
86        'username','email','status','level','groups','language','theme',
87        'nb_image_page','recent_period','expand','show_nb_comments','show_nb_hits',
88        'enabled_high','registration_date','registration_date_string',
89        'registration_date_since', 'last_visit', 'last_visit_string',
90        'last_visit_since'
91        );
92    }
93    else if (in_array('basics', $params['display']))
94    {
95      $params['display'] = array_merge($params['display'], array(
96        'username','email','status','level','groups',
97        ));
98    }
99    $params['display'] = array_flip($params['display']);
100
101    // if registration_date_string or registration_date_since is requested,
102    // then registration_date is automatically added
103    if (isset($params['display']['registration_date_string']) or isset($params['display']['registration_date_since']))
104    {
105      $params['display']['registration_date'] = true;
106    }
107
108    // if last_visit_string or last_visit_since is requested, then
109    // last_visit is automatically added
110    if (isset($params['display']['last_visit_string']) or isset($params['display']['last_visit_since']))
111    {
112      $params['display']['last_visit'] = true;
113    }
114
115    if (isset($params['display']['username']))
116    {
117      $display['u.'.$conf['user_fields']['username']] = 'username';
118    }
119    if (isset($params['display']['email']))
120    {
121      $display['u.'.$conf['user_fields']['email']] = 'email';
122    }
123
124    $ui_fields = array(
125      'status','level','language','theme','nb_image_page','recent_period','expand',
126      'show_nb_comments','show_nb_hits','enabled_high','registration_date'
127      );
128    foreach ($ui_fields as $field)
129    {
130      if (isset($params['display'][$field]))
131      {
132        $display['ui.'.$field] = $field;
133      }
134    }
135  }
136  else
137  {
138    $params['display'] = array();
139  }
140
141  $query = '
142SELECT DISTINCT ';
143
144  $first = true;
145  foreach ($display as $field => $name)
146  {
147    if (!$first) $query.= ', ';
148    else $first = false;
149    $query.= $field .' AS '. $name;
150  }
151  if (isset($params['display']['groups']))
152  {
153    if (!$first) $query.= ', ';
154    $query.= '"" AS groups';
155  }
156
157  $query.= '
158  FROM '. USERS_TABLE .' AS u
159    INNER JOIN '. USER_INFOS_TABLE .' AS ui
160      ON u.'. $conf['user_fields']['id'] .' = ui.user_id
161    LEFT JOIN '. USER_GROUP_TABLE .' AS ug
162      ON u.'. $conf['user_fields']['id'] .' = ug.user_id
163  WHERE
164    '. implode(' AND ', $where_clauses) .'
165  ORDER BY '. $params['order'] .'
166  LIMIT '. $params['per_page'] .'
167  OFFSET '. ($params['per_page']*$params['page']) .'
168;';
169
170  $users = array();
171  $result = pwg_query($query);
172  while ($row = pwg_db_fetch_assoc($result))
173  {
174    $row['id'] = intval($row['id']);
175    $users[ $row['id'] ] = $row;
176  }
177
178  if (count($users) > 0)
179  {
180    if (isset($params['display']['groups']))
181    {
182      $query = '
183SELECT user_id, group_id
184  FROM '. USER_GROUP_TABLE .'
185  WHERE user_id IN ('. implode(',', array_keys($users)) .')
186;';
187      $result = pwg_query($query);
188     
189      while ($row = pwg_db_fetch_assoc($result))
190      {
191        $users[ $row['user_id'] ]['groups'][] = intval($row['group_id']);
192      }
193    }
194   
195    if (isset($params['display']['registration_date_string']))
196    {
197      foreach ($users as $cur_user)
198      {
199        $users[$cur_user['id']]['registration_date_string'] = format_date($cur_user['registration_date'], array('day', 'month', 'year'));
200      }
201    }
202
203    if (isset($params['display']['registration_date_since']))
204    {
205      foreach ($users as $cur_user)
206      {
207        $users[ $cur_user['id'] ]['registration_date_since'] = time_since($cur_user['registration_date'], 'month');
208      }
209    }
210
211    if (isset($params['display']['last_visit']))
212    {
213      $query = '
214SELECT
215    MAX(id) as history_id
216  FROM '.HISTORY_TABLE.'
217  WHERE user_id IN ('.implode(',', array_keys($users)).')
218  GROUP BY user_id
219;';
220      $history_ids = array_from_query($query, 'history_id');
221     
222      if (count($history_ids) == 0)
223      {
224        $history_ids[] = -1;
225      }
226     
227      $query = '
228SELECT
229    user_id,
230    date,
231    time
232  FROM '.HISTORY_TABLE.'
233  WHERE id IN ('.implode(',', $history_ids).')
234;';
235      $result = pwg_query($query);
236      while ($row = pwg_db_fetch_assoc($result))
237      {
238        $last_visit = $row['date'].' '.$row['time'];
239        $users[ $row['user_id'] ]['last_visit'] = $last_visit;
240       
241        if (isset($params['display']['last_visit_string']))
242        {
243          $users[ $row['user_id'] ]['last_visit_string'] = format_date($last_visit, array('day', 'month', 'year'));
244        }
245       
246        if (isset($params['display']['last_visit_since']))
247        {
248          $users[ $row['user_id'] ]['last_visit_since'] = time_since($last_visit, 'day');
249        }
250      }
251    }
252  }
253
254  $users = trigger_change('ws_users_getList', $users);
255 
256  return array(
257    'paging' => new PwgNamedStruct(
258      array(
259        'page' => $params['page'],
260        'per_page' => $params['per_page'],
261        'count' => count($users)
262        )
263      ),
264    'users' => new PwgNamedArray(array_values($users), 'user')
265    );
266}
267
268/**
269 * API method
270 * Adds a user
271 * @param mixed[] $params
272 *    @option string username
273 *    @option string password (optional)
274 *    @option string email (optional)
275 */
276function ws_users_add($params, &$service)
277{
278  if (get_pwg_token() != $params['pwg_token'])
279  {
280    return new PwgError(403, 'Invalid security token');
281  }
282 
283  global $conf;
284
285  if ($conf['double_password_type_in_admin'])
286  {
287    if ($params['password'] != $params['password_confirm'])
288    {
289      return new PwgError(WS_ERR_INVALID_PARAM, l10n('The passwords do not match'));
290    }
291  }
292
293  $user_id = register_user(
294    $params['username'],
295    $params['password'],
296    $params['email'],
297    false, // notify admin
298    $errors,
299    $params['send_password_by_mail']
300    );
301
302  if (!$user_id)
303  {
304    return new PwgError(WS_ERR_INVALID_PARAM, $errors[0]);
305  }
306
307  return $service->invoke('pwg.users.getList', array('user_id'=>$user_id));
308}
309
310/**
311 * API method
312 * Deletes users
313 * @param mixed[] $params
314 *    @option int[] user_id
315 *    @option string pwg_token
316 */
317function ws_users_delete($params, &$service)
318{
319  if (get_pwg_token() != $params['pwg_token'])
320  {
321    return new PwgError(403, 'Invalid security token');
322  }
323
324  global $conf, $user;
325
326  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
327
328  $protected_users = array(
329    $user['id'],
330    $conf['guest_id'],
331    $conf['default_user_id'],
332    $conf['webmaster_id'],
333    );
334
335  // an admin can't delete other admin/webmaster
336  if ('admin' == $user['status'])
337  {
338    $query = '
339SELECT
340    user_id
341  FROM '.USER_INFOS_TABLE.'
342  WHERE status IN (\'webmaster\', \'admin\')
343;';
344    $protected_users = array_merge($protected_users, query2array($query, null, 'user_id'));
345  }
346 
347  // protect some users
348  $params['user_id'] = array_diff($params['user_id'], $protected_users);
349
350  $counter = 0;
351 
352  foreach ($params['user_id'] as $user_id)
353  {
354    delete_user($user_id);
355    $counter++;
356  }
357
358  return l10n_dec(
359    '%d user deleted', '%d users deleted',
360    $counter
361    );
362}
363
364/**
365 * API method
366 * Updates users
367 * @param mixed[] $params
368 *    @option int[] user_id
369 *    @option string username (optional)
370 *    @option string password (optional)
371 *    @option string email (optional)
372 *    @option string status (optional)
373 *    @option int level (optional)
374 *    @option string language (optional)
375 *    @option string theme (optional)
376 *    @option int nb_image_page (optional)
377 *    @option int recent_period (optional)
378 *    @option bool expand (optional)
379 *    @option bool show_nb_comments (optional)
380 *    @option bool show_nb_hits (optional)
381 *    @option bool enabled_high (optional)
382 */
383function ws_users_setInfo($params, &$service)
384{
385  if (get_pwg_token() != $params['pwg_token'])
386  {
387    return new PwgError(403, 'Invalid security token');
388  }
389
390  global $conf, $user;
391
392  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
393
394  $updates = $updates_infos = array();
395  $update_status = null;
396
397  if (count($params['user_id']) == 1)
398  {
399    if (get_username($params['user_id'][0]) === false)
400    {
401      return new PwgError(WS_ERR_INVALID_PARAM, 'This user does not exist.');
402    }
403
404    if (!empty($params['username']))
405    {
406      $user_id = get_userid($params['username']);
407      if ($user_id and $user_id != $params['user_id'][0])
408      {
409        return new PwgError(WS_ERR_INVALID_PARAM, l10n('this login is already used'));
410      }
411      if ($params['username'] != strip_tags($params['username']))
412      {
413        return new PwgError(WS_ERR_INVALID_PARAM, l10n('html tags are not allowed in login'));
414      }
415      $updates[ $conf['user_fields']['username'] ] = $params['username'];
416    }
417
418    if (!empty($params['email']))
419    {
420      if ( ($error = validate_mail_address($params['user_id'][0], $params['email'])) != '')
421      {
422        return new PwgError(WS_ERR_INVALID_PARAM, $error);
423      }
424      $updates[ $conf['user_fields']['email'] ] = $params['email'];
425    }
426
427    if (!empty($params['password']))
428    {
429      $updates[ $conf['user_fields']['password'] ] = $conf['password_hash']($params['password']);
430    }
431  }
432
433  if (!empty($params['status']))
434  {
435    if (in_array($params['status'], array('webmaster', 'admin')) and !is_webmaster() )
436    {
437      return new PwgError(403, 'Only webmasters can grant "webmaster/admin" status');
438    }
439   
440    if ( !in_array($params['status'], array('guest','generic','normal','admin','webmaster')) )
441    {
442      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid status');
443    }
444
445    $protected_users = array(
446      $user['id'],
447      $conf['guest_id'],
448      $conf['webmaster_id'],
449      );
450
451    // an admin can't change status of other admin/webmaster
452    if ('admin' == $user['status'])
453    {
454      $query = '
455SELECT
456    user_id
457  FROM '.USER_INFOS_TABLE.'
458  WHERE status IN (\'webmaster\', \'admin\')
459;';
460      $protected_users = array_merge($protected_users, query2array($query, null, 'user_id'));
461    }
462
463    // status update query is separated from the rest as not applying to the same
464    // set of users (current, guest and webmaster can't be changed)
465    $params['user_id_for_status'] = array_diff($params['user_id'], $protected_users);
466
467    $update_status = $params['status'];
468  }
469
470  if (!empty($params['level']) or @$params['level']===0)
471  {
472    if ( !in_array($params['level'], $conf['available_permission_levels']) )
473    {
474      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid level');
475    }
476    $updates_infos['level'] = $params['level'];
477  }
478
479  if (!empty($params['language']))
480  {
481    if ( !in_array($params['language'], array_keys(get_languages())) )
482    {
483      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid language');
484    }
485    $updates_infos['language'] = $params['language'];
486  }
487
488  if (!empty($params['theme']))
489  {
490    if ( !in_array($params['theme'], array_keys(get_pwg_themes())) )
491    {
492      return new PwgError(WS_ERR_INVALID_PARAM, 'Invalid theme');
493    }
494    $updates_infos['theme'] = $params['theme'];
495  }
496
497  if (!empty($params['nb_image_page']))
498  {
499    $updates_infos['nb_image_page'] = $params['nb_image_page'];
500  }
501
502  if (!empty($params['recent_period']) or @$params['recent_period']===0)
503  {
504    $updates_infos['recent_period'] = $params['recent_period'];
505  }
506
507  if (!empty($params['expand']) or @$params['expand']===false)
508  {
509    $updates_infos['expand'] = boolean_to_string($params['expand']);
510  }
511
512  if (!empty($params['show_nb_comments']) or @$params['show_nb_comments']===false)
513  {
514    $updates_infos['show_nb_comments'] = boolean_to_string($params['show_nb_comments']);
515  }
516
517  if (!empty($params['show_nb_hits']) or @$params['show_nb_hits']===false)
518  {
519    $updates_infos['show_nb_hits'] = boolean_to_string($params['show_nb_hits']);
520  }
521
522  if (!empty($params['enabled_high']) or @$params['enabled_high']===false)
523  {
524    $updates_infos['enabled_high'] = boolean_to_string($params['enabled_high']);
525  }
526
527  // perform updates
528  single_update(
529    USERS_TABLE,
530    $updates,
531    array($conf['user_fields']['id'] => $params['user_id'][0])
532    );
533
534  if (isset($update_status) and count($params['user_id_for_status']) > 0)
535  {
536    $query = '
537UPDATE '. USER_INFOS_TABLE .' SET
538    status = "'. $update_status .'"
539  WHERE user_id IN('. implode(',', $params['user_id_for_status']) .')
540;';
541    pwg_query($query);
542  }
543
544  if (count($updates_infos) > 0)
545  {
546    $query = '
547UPDATE '. USER_INFOS_TABLE .' SET ';
548
549    $first = true;
550    foreach ($updates_infos as $field => $value)
551    {
552      if (!$first) $query.= ', ';
553      else $first = false;
554      $query.= $field .' = "'. $value .'"';
555    }
556
557    $query.= '
558  WHERE user_id IN('. implode(',', $params['user_id']) .')
559;';
560    pwg_query($query);
561  }
562
563  // manage association to groups
564  if (!empty($params['group_id']))
565  {
566    $query = '
567DELETE
568  FROM '.USER_GROUP_TABLE.'
569  WHERE user_id IN ('.implode(',', $params['user_id']).')
570;';
571    pwg_query($query);
572
573    // we remove all provided groups that do not really exist
574    $query = '
575SELECT
576    id
577  FROM '.GROUPS_TABLE.'
578  WHERE id IN ('.implode(',', $params['group_id']).')
579;';
580    $group_ids = array_from_query($query, 'id');
581
582    // if only -1 (a group id that can't exist) is in the list, then no
583    // group is associated
584   
585    if (count($group_ids) > 0)
586    {
587      $inserts = array();
588     
589      foreach ($group_ids as $group_id)
590      {
591        foreach ($params['user_id'] as $user_id)
592        {
593          $inserts[] = array('user_id' => $user_id, 'group_id' => $group_id);
594        }
595      }
596
597      mass_inserts(USER_GROUP_TABLE, array_keys($inserts[0]), $inserts);
598    }
599  }
600
601  invalidate_user_cache();
602
603  return $service->invoke('pwg.users.getList', array(
604    'user_id' => $params['user_id'],
605    'display' => 'basics,'.implode(',', array_keys($updates_infos)),
606    ));
607}
608
609?>
Note: See TracBrowser for help on using the repository browser.