dbXapp 2.0
RAD, CMS, Module und Runtime-IDE fuer dbXapp
Loading...
Searching...
No Matches
dbxUser.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxAdmin;
3
4dbx()->use_system_class('dbxReport');
5
7}
8
9class dbxUser {
10
11 private string $ddUser = 'dbxUser';
12 private string $ddGroup = 'dbxUser_groups';
13 private string $actionError = '';
14
15 private function url($run2, $params = array()) {
16 $url = '?dbx_modul=dbxAdmin&dbx_run1=user&dbx_run2=' . rawurlencode((string)$run2);
17 foreach ($params as $key => $value) {
18 $url .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((string)$value);
19 }
20 return $url;
21 }
22
23 private function action_url($run2, $params = array()) {
24 $params['dbx_token'] = dbx()->action_token('dbxAdmin.user');
25 return $this->url($run2, $params);
26 }
27
28 private function check_action_token(&$message = '') {
29 $token = dbx()->get_modul_var('dbx_token', '', 'varchar|max=128');
30 if (dbx()->check_action_token('dbxAdmin.user', $token)) {
31 return true;
32 }
33
34 $message = 'Aktion abgelehnt: Sicherheits-Token fehlt oder ist ungueltig.';
35 $this->actionError = $message;
36 dbx()->sys_msg('security', 'dbxAdmin', dbx()->user(), 'invalid admin user action token', $_SERVER['REQUEST_URI'] ?? '');
37 return false;
38 }
39
40 private function badge($label, $class = 'secondary') {
41 return '<span class="badge bg-' . dbx()->esc($class) . '">' . dbx()->esc($label) . '</span>';
42 }
43
44 private function action_button($url, $icon, $title, $class = 'btn-outline-secondary') {
45 return '<a class="btn btn-sm ' . dbx()->esc($class) . ' me-1 dbxAjax" href="' . dbx()->esc($url) . '" title="' . dbx()->esc($title) . '">'
46 . '<i class="' . dbx()->esc($icon) . '"></i></a>';
47 }
48
49 private function ajax_url($url) {
50 $sep = (strpos((string)$url, '?') === false) ? '?' : '&';
51 return $url . $sep . 'dbx_ajax=1';
52 }
53
54 private function modal_button($url, $icon, $title, $class = 'btn-outline-primary', $label = '', $size = 'btn-sm') {
55 $size = trim((string)$size);
56 $sizeClass = $size !== '' ? $size . ' ' : '';
57 $text = $label !== '' ? ' ' . dbx()->esc($label) : '';
58 return '<a class="btn dbx-win ' . $sizeClass . dbx()->esc($class) . ' me-1" href="' . dbx()->esc($url) . '" '
59 . 'data-url="' . dbx()->esc($url) . '" data-title="' . dbx()->esc($title) . '" role="button" title="' . dbx()->esc($title) . '">'
60 . '<i class="' . dbx()->esc($icon) . '"></i>' . $text . '</a>';
61 }
62
63 private function delete_button($url, $title = 'Datensatz loeschen') {
64 return '<a class="btn btn-sm btn-outline-danger me-1 dbxAjax dbxConfirm" href="' . dbx()->esc($url) . '" '
65 . 'data-confirm-title="<i class=\'bi bi-trash\'></i> ' . dbx()->esc($title) . '" '
66 . 'data-confirm="Datensatz wirklich loeschen?" '
67 . 'data-confirm-hint="<small>Dieser Vorgang kann nicht rueckgaengig gemacht werden.</small>" '
68 . 'data-confirm-buttons="yesno" title="' . dbx()->esc($title) . '">'
69 . '<i class="bi bi-trash"></i></a>';
70 }
71
72 private function role_options() {
73 $options = array(
74 'admin' => 'Admin',
75 'owner' => 'Owner',
76 'member' => 'Member',
77 'guest' => 'Guest',
78 'api' => 'API',
79 );
80
81 $db = dbx()->get_system_obj('dbxDB');
82 $groups = $db->select($this->ddGroup, '', array('name', 'description', 'active'), 'name', 'ASC', '', 0, 0, 0);
83 if (is_array($groups)) {
84 foreach ($groups as $group) {
85 $name = trim((string)($group['name'] ?? ''));
86 if ($name === '') {
87 continue;
88 }
89 $description = trim((string)($group['description'] ?? ''));
90 $options[$name] = $description !== '' ? $description : $name;
91 }
92 }
93
94 return $options;
95 }
96
97 private function status_label($status) {
98 if ((string)$status === '0') {
99 return $this->badge('gesperrt', 'danger');
100 }
101 if ((string)$status === '1') {
102 return $this->badge('aktiv', 'success');
103 }
104 if ((string)$status === '2') {
105 return $this->badge('wartet', 'warning');
106 }
107 return $this->badge('unbekannt', 'secondary');
108 }
109
110 private function verified_label($value) {
111 return ((string)$value === '1')
112 ? $this->badge('verified', 'success')
113 : $this->badge('offen', 'warning');
114 }
115
116 private function roles_label($roles) {
117 $items = array_filter(array_map('trim', explode(',', (string)$roles)));
118 if (!$items) {
119 return $this->badge('keine Rollen', 'secondary');
120 }
121
122 $html = '';
123 foreach ($items as $role) {
124 $class = ($role === 'admin') ? 'primary' : (($role === 'api') ? 'dark' : 'info');
125 $html .= $this->badge($role, $class) . ' ';
126 }
127 return trim($html);
128 }
129
130 private function user_identity($row) {
131 $name = trim((string)($row['name'] ?? ''));
132 $uname = trim((string)($row['uname'] ?? ''));
133 $email = trim((string)($row['email'] ?? ''));
134
135 $title = $name !== '' ? $name : $uname;
136 $html = '<div class="fw-semibold">' . dbx()->esc($title) . '</div>';
137 $html .= '<div class="text-muted small">@' . dbx()->esc($uname) . '</div>';
138 if ($email !== '') {
139 $html .= '<div class="small"><a href="mailto:' . dbx()->esc($email) . '">' . dbx()->esc($email) . '</a></div>';
140 }
141 return $html;
142 }
143
144 private function user_actions($row) {
145 $id = (int)($row['id'] ?? 0);
146 if ($id <= 0) {
147 return '';
148 }
149
150 $html = '';
151 $protected = ($id <= 1 || $id == dbx()->user());
152 $html .= $this->modal_button($this->url('edit_user', array('rid' => $id)), 'bi bi-pencil-square', 'Benutzer bearbeiten');
153
154 if ($protected) {
155 $html .= '<span class="badge bg-secondary me-1">geschuetzt</span>';
156 } else {
157 if ((string)($row['is_confirm'] ?? '') === '1') {
158 $html .= $this->action_button($this->action_url('list_user', array('dbx_do' => 'unverify', 'rid' => $id)), 'bi bi-patch-minus', 'Verified entfernen');
159 } else {
160 $html .= $this->action_button($this->action_url('list_user', array('dbx_do' => 'verify', 'rid' => $id)), 'bi bi-patch-check', 'Benutzer verifizieren', 'btn-outline-success');
161 }
162
163 if ((string)($row['status'] ?? '') === '0') {
164 $html .= $this->action_button($this->action_url('list_user', array('dbx_do' => 'unlock', 'rid' => $id)), 'bi bi-unlock', 'Login entsperren', 'btn-outline-success');
165 } else {
166 $html .= $this->action_button($this->action_url('list_user', array('dbx_do' => 'lock', 'rid' => $id)), 'bi bi-lock', 'Login sperren', 'btn-outline-danger');
167 }
168
169 $html .= $this->action_button($this->action_url('list_user', array('dbx_do' => 'reset_password', 'rid' => $id)), 'bi bi-key', 'Neues Passwort erzeugen', 'btn-outline-warning');
170 $html .= $this->delete_button($this->action_url('list_user', array('dbx_do' => 'row_delete', 'rid' => $id)), 'Benutzer loeschen');
171 }
172 return $html;
173 }
174
175 private function stats_html() {
176 $db = dbx()->get_system_obj('dbxDB');
177 $all = (int)$db->count($this->ddUser);
178 $active = (int)$db->count($this->ddUser, 'status = 1');
179 $locked = (int)$db->count($this->ddUser, 'status = 0');
180 $verified = (int)$db->count($this->ddUser, 'is_confirm = 1');
181
182 $items = array(
183 array('label' => 'Benutzer', 'value' => $all, 'class' => 'primary', 'filter' => ''),
184 array('label' => 'Aktiv', 'value' => $active, 'class' => 'success', 'filter' => 'active'),
185 array('label' => 'Gesperrt', 'value' => $locked, 'class' => 'danger', 'filter' => 'locked'),
186 array('label' => 'Verified', 'value' => $verified, 'class' => 'info', 'filter' => 'verified'),
187 );
188
189 $html = '<div class="row g-2 mb-3">';
190 foreach ($items as $item) {
191 $url = $item['filter'] === '' ? $this->url('list_user') : $this->url('list_user', array('filter' => $item['filter']));
192 $html .= '<div class="col-6 col-lg-3"><a class="text-decoration-none" href="' . dbx()->esc($url) . '"><div class="border rounded p-3 bg-light h-100">'
193 . '<div class="text-muted small">' . dbx()->esc($item['label']) . '</div>'
194 . '<div class="fs-4 fw-semibold text-' . dbx()->esc($item['class']) . '">' . dbx()->esc($item['value']) . '</div>'
195 . '</div></a></div>';
196 }
197 $html .= '</div>';
198 return $html;
199 }
200
201 private function nav_html($active = 'users') {
202 $tabs = array(
203 'users' => array('label' => 'Benutzer', 'url' => $this->url('list_user')),
204 'groups' => array('label' => 'Rollen / Gruppen', 'url' => $this->url('list_groups')),
205 );
206
207 $html = '<ul class="nav nav-tabs mb-3">';
208 foreach ($tabs as $key => $tab) {
209 $class = ($key === $active) ? ' active' : '';
210 $html .= '<li class="nav-item"><a class="nav-link' . $class . '" href="' . dbx()->esc($tab['url']) . '">' . dbx()->esc($tab['label']) . '</a></li>';
211 }
212 $html .= '</ul>';
213 return $html;
214 }
215
216 private function handle_user_action(&$message = '') {
217 $db = dbx()->get_system_obj('dbxDB');
218 $do = dbx()->get_modul_var('dbx_do', '', 'parameter');
219 if (!$do) {
220 $do = dbx()->get_modul_var('dbx_run3', '', 'parameter');
221 }
222
223 $rid = dbx()->get_modul_var('rid', 0, 'int');
224 if (!$do || !$rid) {
225 return '';
226 }
227
228 if ($do === 'row_edit') {
229 return $this->edit_user($rid);
230 }
231
232 if (!$this->check_action_token($message)) {
233 return '';
234 }
235
236 if ($do === 'row_delete') {
237 if ($rid <= 1 || $rid == dbx()->user()) {
238 $message = 'Dieser Benutzer wird nicht geloescht.';
239 return '';
240 }
241 $ok = $db->delete($this->ddUser, $rid);
242 $message = $ok ? 'Benutzer geloescht.' : 'Benutzer konnte nicht geloescht werden.';
243 return '';
244 }
245
246 $data = array();
247 if ($do === 'verify') {
248 $data['is_confirm'] = 1;
249 }
250 if ($do === 'unverify') {
251 $data['is_confirm'] = 0;
252 }
253 if ($do === 'lock') {
254 if ($rid <= 1 || $rid == dbx()->user()) {
255 $message = 'Dieser Benutzer wird nicht gesperrt.';
256 return '';
257 }
258 $data['status'] = 0;
259 }
260 if ($do === 'unlock') {
261 $data['status'] = 1;
262 }
263 if ($do === 'reset_password') {
264 $newPassword = dbx()->new_password(12);
265 $data['pass'] = password_hash($newPassword, PASSWORD_DEFAULT);
266 }
267
268 if ($data) {
269 $ok = $db->update($this->ddUser, $data, $rid);
270 if ($ok && $do === 'reset_password') {
271 $message = 'Neues Passwort fuer Benutzer #' . $rid . ': ' . $newPassword;
272 } else {
273 $message = $ok ? 'Benutzer aktualisiert.' : 'Benutzer konnte nicht aktualisiert werden.';
274 }
275 }
276
277 return '';
278 }
279
280 private function decorate_users($rows) {
281 $out = array();
282 foreach ((array)$rows as $row) {
283 $row['user'] = $this->user_identity($row);
284 $row['roles_view'] = $this->roles_label($row['roles'] ?? '');
285 $row['verified'] = $this->verified_label($row['is_confirm'] ?? '');
286 $row['login'] = $this->status_label($row['status'] ?? '');
287 $row['profile'] = '<span class="small text-muted">'
288 . dbx()->esc(trim((string)($row['language'] ?? '')))
289 . ' / ' . dbx()->esc(trim((string)($row['design'] ?? '')))
290 . ' / ' . dbx()->esc(trim((string)($row['color'] ?? '')))
291 . '</span>';
292 $row['ops'] = $this->user_actions($row);
293 $out[] = $row;
294 }
295 return $out;
296 }
297
298 private function report_users() {
299 $message = '';
300 $content = $this->handle_user_action($message);
301 if ($content !== '') {
302 return $content;
303 }
304
305 $db = dbx()->get_system_obj('dbxDB');
306 $oReport = new dbxReport_AdminUser;
307 $oReport->init('report-admin-user', 'report-admin-user');
308 $oReport->add_rep('frame_use_form', '0');
309 $oReport->add_rep('report_shell_class', 'dbx-admin-users');
310 $oReport->add_rep('report_shell_attrs', 'data-dbx="lib=report|form=0"');
311 $oReport->_dd = $this->ddUser;
312 $oReport->_action = $this->url('list_user');
313 $oReport->_pages = true;
314 $oReport->_create_row_select = true;
315 $oReport->_create_row_edit = false;
316 $oReport->_create_row_delete = false;
317 $oReport->_create_sel_flds = true;
318 $oReport->_but_pagination = 7;
319 $oReport->_fld_id = 'id';
320 $oReport->_data = array('dbx_rrows' => 25, 'dbx_rsort' => 'id', 'dbx_rdesc' => 'ASC');
321 $oReport->_msg_info = '';
322 $oReport->_rpt_format = array(
323 'id' => 'html-chars',
324 'uname' => 'html-chars',
325 'name' => 'html-chars',
326 'email' => 'html-chars',
327 'user' => 'html',
328 'roles_view' => 'html',
329 'verified' => 'html',
330 'login' => 'html',
331 'profile' => 'html',
332 'ops' => 'html',
333 'lastvisit' => 'php-datetime-usr',
334 'update_date' => 'php-datetime-usr',
335 );
336
337 $newUserBtn = $this->modal_button(
338 $this->url('edit_user', array('rid' => 'new')),
339 'bi bi-person-plus',
340 'Neuer Benutzer',
341 'btn-success',
342 'Neuer Benutzer',
343 ''
344 );
345 $oReport->add_obj('new_user', 'obj-value', $newUserBtn);
346 $oReport->add_obj('bar_actions', 'obj-value', $newUserBtn);
347 $oReport->add_obj('stats', 'obj-value', $this->stats_html());
348 $oReport->add_obj('tabs', 'obj-value', $this->nav_html('users'));
349 $oReport->add_obj('rows_delete', 'obj-value', '');
350 $oReport->create_selection_fields('dbxAdmin|rpt-admin-user-selection');
351
352 if ($message !== '') {
353 if ($this->actionError !== '') {
354 $oReport->_msg_error = $message;
355 } else {
356 $oReport->_msg_success = $message;
357 }
358 }
359
360 if ($oReport->submit()) {
361 if (!$oReport->errors()) {
362 $oReport->_msg_success = $message ?: '';
363 } else {
364 $oReport->_msg_error = 'Pruefen sie bitte ihre Eingaben.';
365 }
366 }
367
368 $search = $oReport->get_fld_val('dbx_rwhere', '', 'sqlsearch|max=64');
369 $rrows = $oReport->get_fld_val('dbx_rrows', 25, 'int');
370 $rpos = $oReport->get_fld_val('dbx_rpos', 0, 'int');
371 $rsort = $oReport->get_fld_val('dbx_rsort', 'id', 'parameter');
372 $rdesc = $oReport->get_fld_val('dbx_rdesc', 'ASC', 'parameter');
373 $select = $oReport->get_fld_val('dbx_rselect', 0, 'int');
374 $filter = dbx()->get_modul_var('filter', '', 'parameter');
375
376 $where = array();
377 if ($search !== '') {
378 $where['search'] = array(
379 'value' => $search,
380 'like' => array('uname', 'name', 'name2', 'email', 'roles', 'ort'),
381 'equal' => array('id'),
382 'mode' => 'contains',
383 );
384 }
385 if ($filter === 'locked') {
386 $where['status'] = 0;
387 } elseif ($filter === 'active') {
388 $where['status'] = 1;
389 } elseif ($filter === 'unverified') {
390 $where['is_confirm'] = 0;
391 } elseif ($filter === 'admin') {
392 $where['roles'] = array('op' => 'LIKE', 'value' => '%admin%');
393 } elseif ($filter === 'verified') {
394 $where['is_confirm'] = 1;
395 }
396 if (!$where) {
397 $where = '';
398 }
399 if ($select) {
400 if (is_array($where)) {
401 $where = $db->normalize_where($this->ddUser, $where);
402 }
403 $where = $oReport->add_rwhere_select($where);
404 }
405
406 $dbFields = array('id', 'uname', 'name', 'name2', 'email', 'roles', 'is_confirm', 'status', 'language', 'design', 'color', 'lastvisit', 'update_date');
407 $flds = array(
408 'id' => 'ID',
409 'user' => 'Benutzer',
410 'roles_view' => 'Rollen',
411 'verified' => 'Verified',
412 'login' => 'Login',
413 'profile' => 'Profil',
414 'lastvisit' => 'Letzter Besuch',
415 'update_date'=> 'Update',
416 'ops' => 'Aktionen',
417 );
418
419 $oReport->_rflds = $flds;
420 $oReport->_rrows = $rrows;
421 $oReport->_rpos = $rpos;
422 $oReport->_count_all = $db->count($this->ddUser);
423 $oReport->_rcount = $db->count($this->ddUser, $where);
424 $rows = $db->select($this->ddUser, $where, $dbFields, $rsort, $rdesc, '', $rrows, $rpos, 0);
425 $oReport->_rdata = $this->decorate_users($rows);
426
427 return $oReport->run();
428 }
429
430 private function edit_user($rid = 'new') {
431 $db = dbx()->get_system_obj('dbxDB');
432 $isNew = ($rid === 'new' || !$rid);
433 $data = array(
434 'status' => 1,
435 'is_confirm' => 1,
436 'language' => 'de',
437 'roles' => 'member',
438 'edit' => 0,
439 'password_new' => '',
440 );
441
442 if (!$isNew) {
443 $record = $db->select1($this->ddUser, (int)$rid, '*', 0);
444 if (is_array($record)) {
445 $data = array_merge($data, $record);
446 }
447 }
448
449 $oForm = dbx()->get_system_obj('dbxForm');
450 $oForm->init('form-admin-user');
451 $oForm->add_rep('bar_title', $isNew ? 'Neuer Benutzer' : 'Benutzer bearbeiten');
452 $oForm->add_rep('bar_subtitle', $isNew ? 'Login, Profil und Rollen anlegen' : 'Benutzerdaten pflegen');
453 $oForm->add_obj('bar_actions', 'obj-value', '<button class="btn btn-primary btn-sm" type="submit"><i class="bi bi-save"></i> Speichern</button>');
454 $oForm->_dd = $this->ddUser;
455 $oForm->_fld_id = 'id';
456 $oForm->_data = $data;
457 $oForm->_msg_info = $isNew ? 'Neuen Benutzer anlegen.' : 'Benutzer bearbeiten.';
458 $oForm->_action = $this->url('edit_user', array('rid' => ($isNew ? 'new' : (int)$rid)));
459 $oForm->set_activ_id($isNew ? 0 : (int)$rid);
460
461 $oForm->add_fld('uname', 'text-label', 'Loginname', 'alphanum|min=4|max=60');
462 $oForm->add_fld('password_new', 'password-label', 'Neues Passwort', 'varchar|max=128', placeholder: 'Leer lassen, um das Passwort nicht zu aendern');
463 $oForm->add_fld('name', 'text-label', 'Name', 'parameter|max=255');
464 $oForm->add_fld('name2', 'text-label', 'Zusatz', 'parameter|max=255');
465 $oForm->add_fld('email', 'text-label', 'E-Mail', 'email|max=255');
466 $oForm->add_fld('roles', 'multi-select', 'Rollen', 'array|parameter', data: array('size' => 7), options: $this->role_options());
467 $oForm->add_fld('status', 'select-single-label', 'Loginstatus', 'int', options: array('1' => 'Aktiv', '0' => 'Gesperrt', '2' => 'Wartet'));
468 $oForm->add_fld('is_confirm', 'select-single-label', 'Verified', 'int', options: array('1' => 'Verified', '0' => 'Offen'));
469 $oForm->add_fld('edit', 'select-single-label', 'Editor', 'int', options: array('1' => 'Ja', '0' => 'Nein'));
470 $oForm->add_fld('language', 'select-single-label', 'Sprache', 'parameter|max=3', options: array('de' => 'Deutsch', 'en' => 'English'));
471 $oForm->add_fld('design', 'text-label', 'Design', 'parameter|max=32');
472 $oForm->add_fld('color', 'text-label', 'Farbe', 'parameter|max=32');
473 $oForm->add_fld('telefon', 'text-label', 'Telefon', 'parameter|max=64');
474 $oForm->add_fld('handy', 'text-label', 'Mobil', 'parameter|max=64');
475 $oForm->add_fld('strasse', 'text-label', 'Strasse', 'parameter|max=255');
476 $oForm->add_fld('plz', 'text-label', 'PLZ', 'parameter|max=16');
477 $oForm->add_fld('ort', 'text-label', 'Ort', 'parameter|max=255');
478 $oForm->add_fld('land', 'text-label', 'Land', 'parameter|max=32');
479 $oForm->add_fld('settings', 'textarea-label', 'Einstellungen', '*', data: array('rows' => 8));
480
481 if ($oForm->submit()) {
482 if (!$oForm->errors()) {
483 $roles = $oForm->get_post('roles', array(), 'array|parameter');
484 if (!is_array($roles)) {
485 $roles = array_filter(array_map('trim', explode(',', (string)$roles)));
486 }
487
488 $values = array(
489 'uname' => $oForm->get_post('uname', '', 'alphanum|max=60'),
490 'name' => $oForm->get_post('name', '', 'parameter|max=255'),
491 'name2' => $oForm->get_post('name2', '', 'parameter|max=255'),
492 'email' => $oForm->get_post('email', '', 'email|max=255'),
493 'roles' => implode(',', array_filter(array_map('trim', $roles))),
494 'status' => $oForm->get_post('status', 1, 'int'),
495 'is_confirm' => $oForm->get_post('is_confirm', 0, 'int'),
496 'edit' => $oForm->get_post('edit', 0, 'int'),
497 'language' => $oForm->get_post('language', 'de', 'parameter|max=3'),
498 'design' => $oForm->get_post('design', '', 'parameter|max=32'),
499 'color' => $oForm->get_post('color', '', 'parameter|max=32'),
500 'telefon' => $oForm->get_post('telefon', '', 'parameter|max=64'),
501 'handy' => $oForm->get_post('handy', '', 'parameter|max=64'),
502 'strasse' => $oForm->get_post('strasse', '', 'parameter|max=255'),
503 'plz' => $oForm->get_post('plz', '', 'parameter|max=16'),
504 'ort' => $oForm->get_post('ort', '', 'parameter|max=255'),
505 'land' => $oForm->get_post('land', '', 'parameter|max=32'),
506 'settings' => $oForm->get_post('settings', '', '*'),
507 );
508
509 $password = $oForm->get_post_data('password_new', '', '*');
510 if ($password !== '') {
511 $values['pass'] = password_hash($password, PASSWORD_DEFAULT);
512 }
513
514 $server = $db->get_dd_server($this->ddUser);
515 $uname = $db->escape($values['uname'], $server);
516 $duplicateWhere = "uname='$uname'";
517 if (!$isNew) {
518 $duplicateWhere .= ' AND id <> ' . (int)$rid;
519 }
520 if ($db->count($this->ddUser, $duplicateWhere) > 0) {
521 $oForm->add_fld_error('uname', 'Loginname existiert bereits.');
522 $oForm->_msg_error = 'Loginname existiert bereits.';
523 } else {
524 $ok = $db->save($this->ddUser, $values, $isNew ? 0 : (int)$rid);
525 $oForm->_msg_success = $ok ? 'Benutzer gespeichert.' : 'Benutzer konnte nicht gespeichert werden.';
526 }
527 } else {
528 $oForm->_msg_error = 'Pruefen sie bitte ihre Eingaben.';
529 }
530 }
531
532 return $oForm->run();
533 }
534
535 private function group_actions($row) {
536 $id = (int)($row['id'] ?? 0);
537 if ($id <= 0) {
538 return '';
539 }
540 $html = $this->modal_button($this->url('edit_group', array('rid' => $id)), 'bi bi-pencil-square', 'Gruppe bearbeiten');
541 if ((string)($row['active'] ?? '') === '1') {
542 $html .= $this->action_button($this->action_url('list_groups', array('dbx_do' => 'group_deactivate', 'rid' => $id)), 'bi bi-pause-circle', 'Gruppe deaktivieren', 'btn-outline-warning');
543 } else {
544 $html .= $this->action_button($this->action_url('list_groups', array('dbx_do' => 'group_activate', 'rid' => $id)), 'bi bi-check-circle', 'Gruppe aktivieren', 'btn-outline-success');
545 }
546 $html .= $this->delete_button($this->action_url('list_groups', array('dbx_do' => 'row_delete', 'rid' => $id)), 'Gruppe loeschen');
547 return $html;
548 }
549
550 private function handle_group_action(&$message = '') {
551 $db = dbx()->get_system_obj('dbxDB');
552 $do = dbx()->get_modul_var('dbx_do', '', 'parameter');
553 if (!$do) {
554 $do = dbx()->get_modul_var('dbx_run3', '', 'parameter');
555 }
556 $rid = dbx()->get_modul_var('rid', 0, 'int');
557
558 if ($do === 'row_edit' && $rid) {
559 return $this->edit_group($rid);
560 }
561 if ($do && $rid && !$this->check_action_token($message)) {
562 return '';
563 }
564 if ($do === 'row_delete' && $rid) {
565 $ok = $db->delete($this->ddGroup, $rid);
566 $message = $ok ? 'Gruppe geloescht.' : 'Gruppe konnte nicht geloescht werden.';
567 }
568 if ($do === 'group_activate' && $rid) {
569 $ok = $db->update($this->ddGroup, array('active' => 1), $rid);
570 $message = $ok ? 'Gruppe aktiviert.' : 'Gruppe konnte nicht aktiviert werden.';
571 }
572 if ($do === 'group_deactivate' && $rid) {
573 $ok = $db->update($this->ddGroup, array('active' => 0), $rid);
574 $message = $ok ? 'Gruppe deaktiviert.' : 'Gruppe konnte nicht deaktiviert werden.';
575 }
576
577 return '';
578 }
579
580 private function decorate_groups($rows) {
581 $users = dbx()->get_system_obj('dbxDB')->select($this->ddUser, '', array('roles'), 'id', 'ASC', '', 0, 0, 0);
582 $out = array();
583 foreach ((array)$rows as $row) {
584 $name = (string)($row['name'] ?? '');
585 $count = 0;
586 foreach ((array)$users as $user) {
587 $roles = array_filter(array_map('trim', explode(',', (string)($user['roles'] ?? ''))));
588 if (in_array($name, $roles, true)) {
589 $count++;
590 }
591 }
592 $row['active_view'] = ((string)($row['active'] ?? '') === '1') ? $this->badge('aktiv', 'success') : $this->badge('inaktiv', 'secondary');
593 $row['users'] = (string)$count;
594 $row['ops'] = $this->group_actions($row);
595 $out[] = $row;
596 }
597 return $out;
598 }
599
600 private function report_groups() {
601 $message = '';
602 $content = $this->handle_group_action($message);
603 if ($content !== '') {
604 return $content;
605 }
606
607 $db = dbx()->get_system_obj('dbxDB');
608 $oReport = new dbxReport_AdminUser;
609 $oReport->init('report-admin-groups', 'report-admin-groups');
610 $oReport->add_rep('frame_use_form', '0');
611 $oReport->add_rep('report_shell_class', 'dbx-admin-groups');
612 $oReport->add_rep('report_shell_attrs', 'data-dbx="lib=report|form=0"');
613 $oReport->_dd = $this->ddGroup;
614 $oReport->_action = $this->url('list_groups');
615 $oReport->_pages = true;
616 $oReport->_create_row_select = true;
617 $oReport->_create_row_edit = false;
618 $oReport->_create_row_delete = false;
619 $oReport->_create_sel_flds = true;
620 $oReport->_but_pagination = 7;
621 $oReport->_fld_id = 'id';
622 $oReport->_data = array('dbx_rrows' => 25, 'dbx_rsort' => 'name', 'dbx_rdesc' => 'ASC');
623 $oReport->_msg_info = '';
624 $oReport->_rpt_format = array(
625 'id' => 'html-chars',
626 'name' => 'html-chars',
627 'description' => 'html-chars',
628 'active_view' => 'html',
629 'ops' => 'html',
630 );
631 $newGroupBtn = $this->modal_button(
632 $this->url('edit_group', array('rid' => 'new')),
633 'bi bi-plus-circle',
634 'Neue Gruppe',
635 'btn-success',
636 'Neue Gruppe',
637 ''
638 );
639 $oReport->add_obj('new_group', 'obj-value', $newGroupBtn);
640 $oReport->add_obj('bar_actions', 'obj-value', $newGroupBtn);
641 $oReport->add_obj('tabs', 'obj-value', $this->nav_html('groups'));
642 $oReport->add_obj('rows_delete', 'obj-value', '');
643 $oReport->create_selection_fields('dbxAdmin|rpt-admin-groups-selection');
644 if ($message !== '') {
645 if ($this->actionError !== '') {
646 $oReport->_msg_error = $message;
647 } else {
648 $oReport->_msg_success = $message;
649 }
650 }
651
652 $search = $oReport->get_fld_val('dbx_rwhere', '', 'sqlsearch|max=64');
653 $rrows = $oReport->get_fld_val('dbx_rrows', 25, 'int');
654 $rpos = $oReport->get_fld_val('dbx_rpos', 0, 'int');
655 $rsort = $oReport->get_fld_val('dbx_rsort', 'name', 'parameter');
656 $rdesc = $oReport->get_fld_val('dbx_rdesc', 'ASC', 'parameter');
657 $where = '';
658 if ($search !== '') {
659 $where = array('search' => array('value' => $search, 'like' => array('name', 'description'), 'mode' => 'contains'));
660 }
661
662 $flds = array(
663 'id' => 'ID',
664 'name' => 'Gruppe',
665 'description' => 'Beschreibung',
666 'active_view' => 'Status',
667 'users' => 'Benutzer',
668 'ops' => 'Aktionen',
669 );
670
671 $oReport->_rflds = $flds;
672 $oReport->_rrows = $rrows;
673 $oReport->_rpos = $rpos;
674 $oReport->_count_all = $db->count($this->ddGroup);
675 $oReport->_rcount = $db->count($this->ddGroup, $where);
676 $rows = $db->select($this->ddGroup, $where, array('id', 'name', 'description', 'active'), $rsort, $rdesc, '', $rrows, $rpos, 0);
677 $oReport->_rdata = $this->decorate_groups($rows);
678
679 return $oReport->run();
680 }
681
682 private function edit_group($rid = 'new') {
683 $db = dbx()->get_system_obj('dbxDB');
684 $isNew = ($rid === 'new' || !$rid);
685 $data = array('active' => 1);
686 if (!$isNew) {
687 $record = $db->select1($this->ddGroup, (int)$rid, '*', 0);
688 if (is_array($record)) {
689 $data = array_merge($data, $record);
690 }
691 }
692
693 $oForm = dbx()->get_system_obj('dbxForm');
694 $oForm->init('form-admin-group');
695 $oForm->add_rep('bar_title', $isNew ? 'Neue Gruppe' : 'Gruppe bearbeiten');
696 $oForm->add_rep('bar_subtitle', 'Rollen und Modulrechte');
697 $actionUrl = $this->url('edit_group', array('rid' => ($isNew ? 'new' : (int)$rid)));
698 $oForm->add_module_bar_form_actions(array(
699 'save' => true,
700 'reload' => true,
701 'reload_url' => $actionUrl,
702 'delete' => !$isNew,
703 'delete_url' => $isNew ? '' : $this->action_url('list_groups', array('dbx_do' => 'row_delete', 'rid' => (int)$rid)),
704 'delete_title' => 'Gruppe loeschen',
705 ));
706 $oForm->add_obj('bar_actions', 'obj-value',
707 '<a class="btn btn-outline-secondary btn-sm" href="' . dbx()->esc($this->url('list_groups')) . '" title="Zur Gruppenliste"><i class="bi bi-list-ul"></i></a>'
708 );
709 $oForm->_dd = $this->ddGroup;
710 $oForm->_fld_id = 'id';
711 $oForm->_data = $data;
712 $oForm->_msg_info = $isNew ? 'Neue Rolle / Gruppe anlegen.' : 'Rolle / Gruppe bearbeiten.';
713 $oForm->_action = $this->url('edit_group', array('rid' => ($isNew ? 'new' : (int)$rid)));
714
715 $oForm->add_fld('name', 'text-label', 'Gruppe', 'parameter|min=2|max=255');
716 $oForm->add_fld('description', 'textarea-label', 'Beschreibung', 'parameter|max=1000', data: array('rows' => 5));
717 $oForm->add_fld('active', 'select-single-label', 'Aktiv', 'int', options: array('1' => 'Aktiv', '0' => 'Inaktiv'));
718
719 if ($oForm->submit()) {
720 if (!$oForm->errors()) {
721 $values = array(
722 'name' => $oForm->get_post('name', '', 'parameter|max=255'),
723 'description' => $oForm->get_post('description', '', 'parameter|max=1000'),
724 'active' => $oForm->get_post('active', 0, 'int'),
725 );
726 $ok = $db->save($this->ddGroup, $values, $isNew ? 0 : (int)$rid);
727 $oForm->_msg_success = $ok ? 'Gruppe gespeichert.' : 'Gruppe konnte nicht gespeichert werden.';
728 } else {
729 $oForm->_msg_error = 'Pruefen sie bitte ihre Eingaben.';
730 }
731 }
732
733 return $oForm->run();
734 }
735
736 public function run($action = '') {
737 $run = dbx()->get_modul_var('dbx_run2', 'list_user', 'parameter');
738
739 switch ($run) {
740 case '':
741 case 'list_user':
742 return $this->report_users();
743
744 case 'edit_user':
745 return $this->edit_user(dbx()->get_modul_var('rid', 'new', 'parameter'));
746
747 case 'list_groups':
748 case 'groups':
749 return $this->report_groups();
750
751 case 'edit_group':
752 return $this->edit_group(dbx()->get_modul_var('rid', 'new', 'parameter'));
753 }
754
755 $oTPL = dbx()->get_system_obj('dbxTPL');
756 return $oTPL->get_tpl('dbx|alert-warning', array('msg' => 'User Admin Work (' . dbx()->esc($run) . ') ist undefiniert.'));
757 }
758}
759?>
init($fid, $tpl='', $first_page_lines=-1, $next_page_lines=-1, $current_line=-1)
DBX schema administration.
$_SERVER['REQUEST_URI']