diff options
Diffstat (limited to 'app/controllers/admin/user.php')
| -rw-r--r-- | app/controllers/admin/user.php | 1716 |
1 files changed, 1716 insertions, 0 deletions
diff --git a/app/controllers/admin/user.php b/app/controllers/admin/user.php new file mode 100644 index 0000000..6ca339e --- /dev/null +++ b/app/controllers/admin/user.php @@ -0,0 +1,1716 @@ +<?php +/** + * user.php - controller class for the user-administration + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * @author Nico Müller <nico.mueller@uni-oldenburg.de> + * @author Michael Riehemann <michael.riehemann@uni-oldenburg.de> + * @author David Siegfried <david.siegfried@uni-vechta.de> + * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 + * @category Stud.IP + * @package admin + * @since 2.1 + */ +require_once 'vendor/email_message/blackhole_message.php'; +require_once 'lib/statusgruppe.inc.php'; + +/** + * + * controller class for the user-administration + * + */ +class Admin_UserController extends AuthenticatedController +{ + /** + * Common tasks for all actions. + */ + public function before_filter(&$action, &$args) + { + global $perm; + parent::before_filter($action, $args); + + // user must have root permission if restricted user management is disabled + $perm->check(Config::get()->RESTRICTED_USER_MANAGEMENT ? 'root' : 'admin'); + + // set navigation + Navigation::activateItem('/admin/user/index'); + + //PageLayout + PageLayout::setHelpKeyword("Admins.Benutzerkonten"); + PageLayout::setTitle(_("Personenverwaltung")); + + $this->action = $action; + $this->args = $args; + + NotificationCenter::addObserver($this, 'addSidebar', 'SidebarWillRender'); + } + + /** + * Display searchbox and all searched users (if any). + * + * @param bool $advanced open or close the advanced searchfields + */ + public function index_action($advanced = false) + { + global $perm; + + $this->perm = $perm; + $request = ''; + //Daten annehmen + if (Request::submitted('reset')) { + unset($_SESSION['admin']['user']); + } elseif (Request::submitted('search')) { + $request = $_SESSION['admin']['user'] = iterator_to_array(Request::getInstance()); + } + + //Suchparameter und Ergebnisse vorhanden + if (isset($_SESSION['admin']['user']) && $_SESSION['admin']['user']['results']) { + $request = $_SESSION['admin']['user']; + } + + if (!empty($request)) { + // Inaktivität für die suche anpassen + $inaktiv = [$request['inaktiv'], $request['inaktiv_tage']]; + if (empty($request['inaktiv_tage']) && $request['inaktiv'] != 'nie') { + $inaktiv = null; + } + } + + //Datafields + $this->datafields = []; + $datafields = DataField::getDataFields("user"); + foreach ($datafields as $datafield) { + if ($datafield->accessAllowed()) { + $this->datafields[] = $datafield; + } + } + + // roles + $this->roles = array_filter(RolePersistence::getAllRoles(), function($role) { + return !$role->systemtype; + }); + + //wenn suche durchgeführt + if (!empty($request)) { + //suche mit datafields + foreach ($this->datafields as $datafield) { + if (mb_strlen($request[$datafield->id]) > 0 + && !(in_array($datafield->type, words('selectbox radio')) && $request[$datafield->id] === '---ignore---') + ) { + $search_datafields[$datafield->id] = $request[$datafield->id]; + } + } + + //Suchparameter + $this->sortby = Request::option('sortby', 'username'); + $this->order = Request::option('order', 'asc'); + if (Request::int('toggle')) { + $this->order = $this->order == 'desc' ? 'asc' : 'desc'; + } + + $request['vorname'] = $request['vorname'] ?: null; + $request['nachname'] = $request['nachname'] ?: null; + $request['inaktiv'] = $inaktiv; + $request['datafields'] = $search_datafields; + $request['sort'] = $this->sortby; + $request['order'] = $this->order; + $empty_search = $request['perm'] === 'alle'; + + $values = [ + 'username', + 'vorname', + 'nachname', + 'email', + 'inaktiv', + 'locked', + 'show_only_not_lectures', + 'datafields', + 'inaktiv_tage', + 'institute', + 'studycourse', + 'degree', + 'fachsem', + 'userdomains', + 'auth_plugins', + ]; + foreach ($values as $value) { + if (!empty($request[$value])) { + $empty_search = false; + break; + } + } + //Daten abrufen + $this->request = $request; + $this->users = $empty_search ? false : User::search($request); + + // Fehler abfangen + if ($this->users === false) { + PageLayout::postInfo(_('Sie haben keine Suchkriterien ausgewählt!')); + } elseif (count($this->users) < 1 && Request::submitted('search')) { + PageLayout::postInfo(_('Es wurden keine Personen mit diesen Suchkriterien gefunden.')); + } else { + $_SESSION['admin']['user']['results'] = true; + PageLayout::postInfo(sprintf(_('Es wurden %s Personen mit diesen Suchkriterien gefunden.'), count($this->users))); + } + if (is_array($this->users) && Request::submitted('export')) { + $tmpname = md5(uniqid('tmp')); + $captions = ['username', + 'vorname', + 'nachname', + 'email', + 'status', + 'authentifizierung', + 'domänen', + 'registriert seit', + 'inaktiv seit']; + $mapper = function ($u) { + $userdomains = array_map(function ($ud) { + return $ud->name; + }, UserDomain::getUserDomainsForUser($u->id)); + return [ + $u['username'], + $u['Vorname'], + $u['Nachname'], + $u['Email'], + $u['perms'], + $u['auth_plugin'], + join(';', $userdomains), + $u['mkdate'] ? strftime('%x', $u['mkdate']) : '', + $u->online->last_lifesign ? strftime('%x', $u->online->last_lifesign) : '' + ]; + }; + if (array_to_csv(array_map($mapper, $this->users), $GLOBALS['TMP_PATH'] . '/' . $tmpname, $captions)) { + $this->redirect( + FileManager::getDownloadURLForTemporaryFile( + $tmpname, + 'nutzer-export.csv' + ) + ); + } + } + } + + $this->degrees = Abschluss::findBySQL('1 order by name'); + $this->studycourses = Fach::findBySQL('1 order by name'); + $this->userdomains = UserDomain::getUserDomains(); + $this->institutes = Institute::getInstitutes(); + foreach ($GLOBALS['STUDIP_AUTH_PLUGIN'] as $ap) { + $this->available_auth_plugins[mb_strtolower($ap)] = $ap; + } + + //show datafields search + if ($advanced + || !empty($search_datafields) + || (!empty($request) + && ($request['auth_plugins'] || $request['userdomains'] || $request['degree'] || $request['institute'] || $request['studycourse'] || $request['show_only_not_lectures'] || !empty($request['roles'])) + ) + ) { + $this->advanced = true; + } + } + + /** + * Bulk action (delete users or send message to all) + */ + public function bulk_action($user_id = null) + { + $action = Request::option('method'); + + if ($action === 'delete') { + PageLayout::setTitle(_('Folgende Nutzer löschen')); + if ($user_id) { + $this->users = [User::find($user_id)]; + } else { + $this->users = User::findMany(Request::getArray('user_ids')); + } + $this->render_template('admin/user/_delete.php'); + return; + } elseif ($action === 'send_message') { + $users = User::findMany(Request::getArray('user_ids')); + + if ($users) { + $users = new SimpleCollection($users); + $users = $users->pluck('username'); + } + + $_SESSION['sms_data'] = []; + $_SESSION['sms_data']['p_rec'] = array_filter($users); + $this->redirect(URLHelper::getURL('dispatch.php/messages/write', ['default_subject' => '', 'tmpsavesnd' => 1])); + return; + } + $this->relocate('admin/user'); + } + + /** + * Deleting one or more users + * + * @param md5 $user_id + * @param string $parent redirect to this page after deleting users + */ + public function delete_action($user_id = null, $parent = '') + { + $delete_documents = (bool) Request::int('documents'); + $delete_content_from_course = (bool) Request::int('coursecontent'); + $delete_personal_documents = (bool) Request::int('personaldocuments'); + $delete_personal_content = (bool) Request::int('personalcontent'); + $delete_names = (bool) Request::int('personalnames'); + $delete_memberships = (bool) Request::int('memberships'); + + //deleting one user + if (!is_null($user_id)) { + $user = User::find($user_id); + + //check user + if (!count($user)) { + PageLayout::postError(_('Fehler! Zu löschende Person ist nicht vorhanden.')); + //antwort ja + } elseif (!empty($user) && Request::submitted('delete')) { + CSRFProtection::verifyUnsafeRequest(); + + //if deleting user, go back to mainpage + $parent = ''; + + //deactivate message + if (!Request::int('mail')) { + $dev_null = new blackhole_message_class(); + $default_mailer = StudipMail::getDefaultTransporter(); + StudipMail::setDefaultTransporter($dev_null); + } + //preparing delete + $umanager = new UserManagement(); + $umanager->getFromDatabase($user_id); + + //delete + if ($umanager->deleteUser($delete_documents, $delete_content_from_course, $delete_personal_documents, $delete_personal_content, $delete_names, $delete_memberships)) { + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($umanager->msg, 0, -1))); + PageLayout::postSuccess(htmlReady(sprintf(_('"%s (%s)" wurde erfolgreich gelöscht.'), $user->getFullName(), $user->username)), $details); + } else { + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($umanager->msg, 0, -1))); + PageLayout::postError(htmlReady(sprintf(_('Fehler! "%s (%s)" konnte nicht gelöscht werden.'), $user->getFullName(), $user->username)), $details); + } + + //reavtivate messages + if (!Request::int('mail')) { + StudipMail::setDefaultTransporter($default_mailer); + } + + //sicherheitsabfrage + } elseif (!empty($user) && !Request::submitted('back')) { + + $this->flash['delete'] = [ + 'question' => sprintf(_('Wollen Sie "%s (%s)" wirklich löschen?'), $user->getFullName(), $user->username), + 'action' => ($parent != '') ? $this->url_for('admin/user/delete/' . $user_id . '/' . $parent) : $this->url_for('admin/user/delete/' . $user_id), + ]; + } + + //deleting more users + } else { + $user_ids = Request::getArray('user_ids'); + + if (count($user_ids) == 0) { + PageLayout::postError(_('Bitte wählen Sie mindestens eine Person zum Löschen aus.')); + $this->redirect('admin/user/' . $parent); + return; + } + + if (Request::submitted('delete')) { + CSRFProtection::verifyUnsafeRequest(); + + //deactivate message + if (!Request::int('mail')) { + $dev_null = new blackhole_message_class(); + $default_mailer = StudipMail::getDefaultTransporter(); + StudipMail::setDefaultTransporter($dev_null); + } + + foreach ($user_ids as $i => $user_id) { + $users[$i] = User::find($user_id); + //preparing delete + $umanager = new UserManagement(); + $umanager->getFromDatabase($user_id); + + //delete + if ($umanager->deleteUser($delete_documents, $delete_content_from_course, $delete_personal_documents, $delete_personal_content, $delete_names, $delete_memberships)) { + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($umanager->msg, 0, -1))); + PageLayout::postSuccess(htmlReady(sprintf(_('"%s (%s)" wurde erfolgreich gelöscht'), $users[$i]->getFullName(), $users[$i]->username)), $details); + } else { + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($umanager->msg, 0, -1))); + PageLayout::postError(htmlReady(sprintf(_('Fehler! "%s (%s)" konnte nicht gelöscht werden'), $users[$i]->getFullName(), $users[$i]->username)), $details); + } + } + + //reactivate messages + if (!Request::int('mail')) { + StudipMail::setDefaultTransporter($default_mailer); + } + + } + } + + //liste wieder anzeigen + if ($parent == 'edit') { + $this->redirect('admin/user/edit/' . $user_id); + } else { + $this->redirect('admin/user/' . $parent); + } + } + + + + /** + * Display all information according to the selected user. All details can + * be changed and deleted. + * + * @param md5 $user_id + */ + public function edit_action($user_id = null) + { + //check submitted user_id + if ($user_id === null) { + if (Request::option('user')) { + $user_id = Request::option('user'); + } else { + PageLayout::postInfo(_('Sie haben niemanden ausgewählt!')); + //liste wieder anzeigen + $this->redirect('admin/user/'); + return; + } + } + + //get user + $this->user = User::find($user_id); + + // Änderungen speichern + if (Request::submitted('edit')) { + if (Request::get('auth_plugin') == 'preliminary') { + Request::set('auth_plugin', null); + } + $editPerms = Request::getArray('perms'); + $um = new UserManagement($user_id); + + //new user data + $editUser = []; + if (count($editPerms)) { + $editUser['auth_user_md5.perms'] = $editPerms[0]; + } + foreach (words('Vorname Nachname auth_plugin visible') as $param) { + if (Request::get($param)) $editUser['auth_user_md5.' . $param] = Request::get($param); + } + foreach (words('title_front title_rear geschlecht preferred_language') as $param) { + if (Request::get($param) !== null) $editUser['user_info.' . $param] = Request::get($param); + } + //change username + if (Request::get('username') && $this->user['username'] != Request::get('username')) { + $editUser['auth_user_md5.username'] = Request::get('username'); + } + //change email + if (Request::get('Email') && $this->user['Email'] != Request::get('Email')) { + //disable mailbox validation + if (Request::get('disable_mail_host_check')) { + $GLOBALS['MAIL_VALIDATE_BOX'] = false; + } + $editUser['auth_user_md5.Email'] = Request::get('Email'); + } + + //change password + if (($GLOBALS['perm']->have_perm('root') && Config::get()->ALLOW_ADMIN_USERACCESS) && (Request::get('pass_1') != '' || Request::get('pass_2') != '')) { + if (Request::get('pass_1') == Request::get('pass_2')) { + if (mb_strlen(Request::get('pass_1')) < 4) { + $details[] = _('Das Passwort ist zu kurz. Es sollte mindestens 8 Zeichen lang sein.'); + } else { + $um->changePassword(Request::get('pass_1')); + } + } else { + $details[] = _("Bei der Wiederholung des Passwortes ist ein Fehler aufgetreten! Bitte geben Sie das exakte Passwort ein!"); + } + } + + //deleting validation-key + if (Request::get('delete_val_key') == "1") { + $editUser['auth_user_md5.validation_key'] = ''; + $details[] = _('Der Validation-Key wurde entfernt.'); + } + + //changing studiendaten + if (in_array($editPerms[0], ['autor', 'tutor', 'dozent']) && Request::option('new_studiengang', 'none') != 'none' && Request::option('new_abschluss', 'none') != 'none') { + //change studycourses + if (Request::option('new_studiengang', 'none') == 'none' || Request::option('new_abschluss', 'none') == 'none') { + $details[] = _('<b>Der Studiengang wurde nicht hinzugefügt.</b> Bitte geben Sie Fach und Abschluss ein.'); + } else { + $user_stc = UserStudyCourse::find([ + $user_id, + Request::option('new_studiengang'), + Request::option('new_abschluss'), + ]); + if (!$user_stc) { + UserStudyCourse::create([ + 'user_id' => $user_id, + 'fach_id' => Request::option('new_studiengang'), + 'semester' => Request::int('fachsem'), + 'abschluss_id' => Request::option('new_abschluss'), + ]); + $details[] = _('Der Studiengang wurde hinzugefügt.'); + } else { + $user_stc->semester = Request::int('fachsem'); + if ($user_stc->store()) { + $details[] = _('Der Studiengang wurde geändert.'); + } else { + $details[] = _('Der Studiengang wurde nicht geändert.'); + } + } + } + } + + // change version of studiengang if module management is enabled + if (in_array($editPerms[0], ['autor', 'tutor', 'dozent'])) { + $change_versions = Request::getArray('change_version'); + foreach ($change_versions as $fach_id => $abschluesse) { + foreach ($abschluesse as $abschluss_id => $version_id) { + $version = StgteilVersion::findByFachAbschluss( + $fach_id, $abschluss_id, $version_id + ); + $version = reset($version); + if ($version && $version->hasPublicStatus('genehmigt')) { + $user_stc = UserStudyCourse::find([ + $user_id, + $fach_id, + $abschluss_id]); + if ($user_stc) { + $user_stc->version_id = $version->getId(); + $any_change = $user_stc->store() != false; + } + } + } + } + if ($any_change) { + $details[] = _('Die Versionen der Studiengänge wurden geändert.'); + } + } + $new_institutes = Request::getArray('new_inst'); + + //change institute for studiendaten + if (in_array($editPerms[0], ['autor', 'tutor', 'dozent']) + && Request::option('new_student_inst') + && empty($new_institutes) + && $GLOBALS['perm']->have_studip_perm("admin", Request::option('new_student_inst')) + ) { + StudipLog::log('INST_USER_ADD', Request::option('new_student_inst'), $user_id, 'user'); + $db = DBManager::get()->prepare("INSERT IGNORE INTO user_inst (user_id, Institut_id, inst_perms) " + . "VALUES (?,?,'user')"); + $db->execute([$user_id, Request::option('new_student_inst')]); + NotificationCenter::postNotification('UserInstitutionDidCreate', Request::option('new_student_inst'), $user_id); + $details[] = _('Die Einrichtung wurde hinzugefügt.'); + } + + //change institute + if (!empty($new_institutes)) { + foreach ($new_institutes as $institute_id) { + if ($editPerms[0] != 'root' + && $GLOBALS['perm']->have_studip_perm("admin", $institute_id) + && !Request::option('new_student_inst') + ) { + $membership = InstituteMember::build( + ['user_id' => $user_id, 'Institut_id' => $institute_id, 'inst_perms' => $editPerms[0]] + ); + + if ($membership->store()) { + StudipLog::log('INST_USER_ADD', $institute_id, $user_id, $editPerms[0]); + NotificationCenter::postNotification('UserInstitutionDidUpdate', $institute_id, $user_id); + InstituteMember::ensureDefaultInstituteForUser($user_id); + $details[] = sprintf(_('%s wurde hinzugefügt.'), htmlReady($membership->institute->getFullname())); + } + } elseif ($institute_id != '' && Request::option('new_student_inst') == $institute_id && $editPerms[0] != 'root') { + $details[] = sprintf( + _('<b>%s wurde nicht hinzugefügt.</b> Sie können keine Person gleichzeitig als Studierende/-r und als Mitarbeiter/-in einer Einrichtung hinzufügen.'), + htmlReady(Institute::find($institute_id)->getFullname()) + ); + } + } + } + + //change userdomain + if (Request::get('new_userdomain', 'none') != 'none' && $editPerms[0] != 'root') { + UserDomain::find(Request::get('new_userdomain'))->addUser($user_id); + $result = AutoInsert::instance()->saveUser($user_id); + + $details[] = _('Die Nutzerdomäne wurde hinzugefügt.'); + foreach ($result['added'] as $item) { + $details[] = sprintf(_("Das automatische Eintragen in die Veranstaltung <em>%s</em> wurde durchgeführt."), $item); + } + foreach ($result['removed'] as $item) { + $details[] = sprintf(_("Das automatische Austragen aus der Veranstaltung <em>%s</em> wurde durchgeführt."), $item); + } + } + + //change datafields + $datafields = Request::getArray('datafields'); + foreach (DataFieldEntry::getDataFieldEntries($user_id) as $id => $entry) { + if (isset($datafields[$id])) { + $entry->setValueFromSubmit($datafields[$id]); + if ($entry->isValid()) { + $entry->store(); + } + } + } + + //change ablaufdatum + if (Request::get('expiration_date_delete') == 1) { + UserConfig::get($user_id)->delete("EXPIRATION_DATE"); + } elseif (Request::get('expiration_date')) { + $a = explode(".", stripslashes(trim(Request::get('expiration_date')))); + if ($timestamp = @mktime(0, 0, 0, $a[1], $a[0], $a[2])) { + UserConfig::get($user_id)->store("EXPIRATION_DATE", $timestamp); + $details[] = _("Das Ablaufdatum wurde geändert."); + } else { + $details[] = _("Das Ablaufdatum wurde in einem falschen Format angegeben."); + } + } + + if ($GLOBALS['perm']->have_perm('root') && Request::get('lock_rule')) { + $st = DBManager::get()->prepare("UPDATE user_info SET lock_rule=? WHERE user_id=?"); + $st->execute([(Request::option('lock_rule') == 'none' ? '' : Request::option('lock_rule')), $user_id]); + if ($st->rowCount()) { + $details[] = _("Die Sperrebene wurde geändert."); + } + } + + if (!Request::int('u_edit_send_mail')) { + $dev_null = new blackhole_message_class(); + $default_mailer = StudipMail::getDefaultTransporter(); + StudipMail::setDefaultTransporter($dev_null); + $GLOBALS['MAIL_VALIDATE_BOX'] = false; + $GLOBALS['MAIL_VALIDATE_HOST'] = false; + } + //save action and messages + $um->changeUser($editUser); + if (!Request::int('u_edit_send_mail')) { + StudipMail::setDefaultTransporter($default_mailer); + } + //get message + $umdetails = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($um->msg, 0, -1))); + $details = array_reverse(array_merge((array)$details, (array)$umdetails)); + PageLayout::postInfo(_('Hinweise:'), $details); + + $this->redirect('admin/user/edit/' . $user_id); + } + + $this->prelim = $this->user->auth_plugin === null; + if ($this->prelim) { + $this->available_auth_plugins['preliminary'] = _('vorläufig'); + } + foreach ($GLOBALS['STUDIP_AUTH_PLUGIN'] as $ap) { + $this->available_auth_plugins[mb_strtolower($ap)] = $ap; + } + + if (count($this->user->institute_memberships)) { + $this->student_institutes = $this->user->institute_memberships->filter(function ($a) { + return $a->inst_perms === 'user'; + }); + $this->institutes = $this->user->institute_memberships->filter(function ($a) { + return $a->inst_perms !== 'user'; + }); + } + + $this->available_institutes = Institute::getMyInstitutes(); + $this->userfields = DataFieldEntry::getDataFieldEntries($user_id, 'user'); + $this->userdomains = UserDomain::getUserDomainsForUser($user_id); + if (LockRules::CheckLockRulePermission($user_id) && LockRules::getObjectRule($user_id)->description) { + PageLayout::postInfo(formatLinks(LockRules::getObjectRule($user_id)->description)); + } + + $user_domains = UserDomain::getUserDomainsForUser($this->user->user_id); + $all_domains = UserDomain::getUserDomains(); + $this->domains = array_diff($all_domains, $user_domains); + $this->faecher = Fach::findBySQL('1 ORDER BY name'); + $this->abschluesse = Abschluss::findBySQL('1 ORDER BY name'); + } + + /** + * Adding a new user to Stud.IP + * @param bool $prelim + */ + public function new_action($prelim = false) + { + global $perm, $auth; + + $this->perm = $perm; + $this->prelim = $prelim; + + //check auth_plugins + if (!in_array("Standard", $GLOBALS['STUDIP_AUTH_PLUGIN']) && !$prelim) { + PageLayout::postInfo(_('Die Standard-Authentifizierung ist ausgeschaltet. Das Anlegen von neuen Benutzern ist nicht möglich!')); + $this->redirect('admin/user'); + return; + } + + //get formdata + $this->user = [ + 'username' => Request::get('username'), + 'perm' => Request::option('perm'), + 'visible' => Request::get('visible'), + 'Vorname' => Request::get('Vorname'), + 'Nachname' => Request::get('Nachname'), + 'geschlecht' => Request::int('geschlecht'), + 'title_front' => Request::get('title_front'), + 'title_rear' => Request::get('title_rear'), + 'Email' => Request::get('Email'), + 'auth_plugin' => Request::get('auth_plugin'), + 'institute' => Request::option('institute'), + 'preferred_language' => Request::get('preferred_language') + ]; + + //save new user + if (Request::submitted('speichern')) { + + //disable mailbox validation + if (Request::get('disable_mail_host_check')) { + $GLOBALS['MAIL_VALIDATE_BOX'] = false; + } + + //messagebox details + $details = []; + + //new user data + $newuser = [ + 'auth_user_md5.username' => $this->user['username'], + 'auth_user_md5.Vorname' => $this->user['Vorname'], + 'auth_user_md5.Nachname' => $this->user['Nachname'], + 'auth_user_md5.Email' => $this->user['Email'], + 'auth_user_md5.perms' => $this->user['perm'], + 'auth_user_md5.auth_plugin' => $this->user['auth_plugin'], + 'auth_user_md5.visible' => $this->user['visible'], + 'user_info.title_front' => $this->user['title_front'], + 'user_info.title_rear' => $this->user['title_rear'], + 'user_info.geschlecht' => $this->user['geschlecht'], + 'user_info.preferred_language' => $this->user['preferred_language'], + ]; + + //create new user + $UserManagement = new UserManagement(); + if (!$prelim) { + $created = $UserManagement->createNewUser($newuser); + } else { + $created = $UserManagement->createPreliminaryUser($newuser); + } + if ($created) { + + //get user_id + $user_id = $UserManagement->user_data['auth_user_md5.user_id']; + $institutes = Request::getArray('institutes'); + + if (!empty($institutes)) { + $institutes = Institute::findMany($institutes); + foreach ($institutes as $institute) { + //new user is added to an institute + if ($GLOBALS['perm']->have_studip_perm('admin', $institute->id) + && $UserManagement->user_data['auth_user_md5.perms'] != 'root' + && ($UserManagement->user_data['auth_user_md5.perms'] != 'admin' + || ($GLOBALS['perm']->is_fak_admin() && !$institute->isFaculty()) + || $GLOBALS['perm']->have_perm('root')) + ) { + //log + StudipLog::log( + 'INST_USER_ADD', + $institute->id, + $user_id, + $UserManagement->user_data['auth_user_md5.perms']); + + $inst_user = InstituteMember::build([ + 'user_id' => $user_id, + 'Institut_id' => $institute->id, + 'inst_perms' => $UserManagement->user_data['auth_user_md5.perms'] + ])->store(); + NotificationCenter::postNotification('UserInstitutionDidCreate', $institute->id, $user_id); + InstituteMember::ensureDefaultInstituteForUser($user_id); + + //send email, if new user is an admin + if ($inst_user) { + //check recipients + if (Request::get('enable_mail_admin') === 'admin' && Request::get('enable_mail_dozent') === 'dozent') { + $in = words('admin dozent'); + $wem = "Admins und Lehrende"; + } elseif (Request::get('enable_mail_admin') === 'admin') { + $in = 'admin'; + $wem = "Admins"; + } elseif (Request::get('enable_mail_dozent') === 'dozent') { + $in = 'dozent'; + $wem = "Lehrende"; + } + + if (!empty($in) && Request::get('perm') == 'admin') { + $i = 0; + $notin = []; + + //get admins + $sql = "SELECT user_id, b.Vorname, b.Nachname, b.Email + FROM user_inst AS a + INNER JOIN auth_user_md5 AS b USING (user_id) + WHERE a.Institut_id = ? AND a.inst_perms IN (?) AND a.user_id != ?"; + + $statement = DBManager::get()->prepare($sql); + $statement->execute([ + $institute->id, + $in, + $user_id, + ]); + $users = $statement->fetchAll(PDO::FETCH_ASSOC); + + foreach ($users as $admin) { + $subject = _("Neuer Administrator in Ihrer Einrichtung angelegt"); + $mailbody = sprintf(_("Liebe(r) %s %s,\n\n" + . "in der Einrichtung '%s' wurde %s %s als Administrator eingetragen " + . " und steht Ihnen als neuer Ansprechpartner bei Fragen oder Problemen " + . "in Stud.IP zur Verfügung. "), + $admin['Vorname'], $admin['Nachname'], + $institute->getFullname(), $this->user['Vorname'], $this->user['Nachname']); + + StudipMail::sendMessage($admin['Email'], $subject, $mailbody); + $notin[] = $admin['user_id']; + $i++; + } + + //Noch ein paar Mails für die Fakultätsadmins + if ($in != 'dozent') { + $notin[] = $user_id; + //get admins + $sql = "SELECT a.user_id, b.Vorname, b.Nachname, b.Email + FROM user_inst AS a + INNER JOIN auth_user_md5 AS b USING (user_id) + WHERE a.user_id NOT IN (?) AND a.Institut_id IN ( + SELECT fakultaets_id + FROM Institute + WHERE Institut_id = ? AND fakultaets_id != Institut_id + ) AND a.inst_perms = 'admin'"; + $statement = DBManager::get()->prepare($sql); + $statement->execute([ + $notin, + $institute->id, + ]); + $fak_admins = $statement->fetchAll(PDO::FETCH_ASSOC); + + foreach ($fak_admins as $admin) { + $subject = _("Neuer Administrator in Ihrer Einrichtung angelegt"); + $mailbody = sprintf(_("Liebe(r) %s %s,\n\n" + . "in der Einrichtung '%s' wurde %s %s als Administrator eingetragen " + . " und steht Ihnen als neuer Ansprechpartner bei Fragen oder Problemen " + . "in Stud.IP zur Verfügung. "), + $admin['Vorname'], $admin['Nachname'], + $institute->getFullname(), $this->user['Vorname'], $this->user['Nachname']); + + StudipMail::sendMessage($admin['Email'], $subject, $mailbody); + $i++; + } + } + $details[] = sprintf( + _('Es wurden ingesamt %s Mails an die %s der Einrichtung "%s" geschickt.'), + $i, + $wem, + htmlReady($institute->getFullname()) + ); + } + + $details[] = sprintf( + _('Person wurde erfolgreich in die Einrichtung "%s" mit dem Status "%s" eingetragen.'), + htmlReady($institute->getFullname()), + $UserManagement->user_data['auth_user_md5.perms'] + ); + } else { + $details[] = sprintf( + _('Person konnte nicht in die Einrichtung "%s" eingetragen werden.'), + htmlReady($institute->getFullname()) + ); + } + } + } + } + + //adding userdomain + if (Request::get('select_dom_id')) { + $domain = new UserDomain(Request::get('select_dom_id')); + if ($perm->have_perm('root') || in_array($domain, UserDomain::getUserDomainsForUser($GLOBALS['user']->id))) { + $domain->addUser($user_id); + $details[] = sprintf(_('Person wurde in Nutzerdomäne "%s" eingetragen.'), htmlReady($domain->name)); + } else { + $details[] = _('Person konnte nicht in die Nutzerdomäne eingetragen werden.'); + } + $result = AutoInsert::instance()->saveUser($user_id); + + foreach ($result['added'] as $item) { + $details[] = sprintf(_('Das automatische Eintragen in die Veranstaltung <em>%s</em> wurde durchgeführt.'), $item); + } + foreach ($result['removed'] as $item) { + $details[] = sprintf(_('Das automatische Austragen aus der Veranstaltung <em>%s</em> wurde durchgeführt.'), $item); + } + } + + //get message + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($UserManagement->msg, 0, -1))); + PageLayout::postSuccess(_('Person wurde angelegt.'), $details); + $this->redirect('admin/user/edit/' . $user_id); + return; + } else { + //get message + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($UserManagement->msg, 0, -1))); + PageLayout::postError(_('Person konnte nicht angelegt werden.'), $details); + } + } + + if ($this->perm->have_perm('root')) { + $sql + = "SELECT Institut_id, Name, 1 AS is_fak + FROM Institute + WHERE Institut_id=fakultaets_id + ORDER BY Name"; + $faks = DBManager::get()->query($sql)->fetchAll(PDO::FETCH_ASSOC); + $domains = UserDomain::getUserDomains(); + } else { + $sql + = "SELECT a.Institut_id, Name, b.Institut_id = b.fakultaets_id AS is_fak + FROM user_inst a + LEFT JOIN Institute b USING (Institut_id) + WHERE a.user_id = ? AND a.inst_perms = 'admin' + ORDER BY is_fak, Name"; + $statement = DBManager::get()->prepare($sql); + $statement->execute([$auth->auth['uid']]); + $faks = $statement->fetchAll(PDO::FETCH_ASSOC); + $domains = UserDomain::getUserDomainsForUser($auth->auth["uid"]); + } + + $query + = "SELECT Institut_id, Name + FROM Institute + WHERE fakultaets_id = ? AND institut_id != fakultaets_id + ORDER BY Name"; + $statement = DBManager::get()->prepare($query); + + foreach ($faks as $index => $fak) { + if ($fak['is_fak']) { + $statement->execute([$fak['Institut_id']]); + $faks[$index]['institutes'] = $statement->fetchAll(PDO::FETCH_ASSOC); + $statement->closeCursor(); + } + } + + $this->domains = $domains; + $this->faks = $faks; + $this->perms = $perm; + } + + /** + * Migrate 2 users to 1 account. This is a part of the old numit-plugin + */ + public function migrate_action($user_id = null) + { + //check submitted form + if (Request::submitted('umwandeln')) { + $old_id = Request::option('old_id'); + $new_id = Request::option('new_id'); + + //check existing users + if (User::exists($old_id) && User::exists($new_id)) { + $identity = Request:: get('convert_ident'); + $details = User::convert($old_id, $new_id, $identity); + + //delete old user + if (Request::get('delete_old')) { + //no messaging + $dev_null = new blackhole_message_class(); + $default_mailer = StudipMail::getDefaultTransporter(); + StudipMail::setDefaultTransporter($dev_null); + + //preparing delete + $umanager = new UserManagement(); + $umanager->getFromDatabase($old_id); + + //delete + $umanager->deleteUser(); + $details = array_merge($details, explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($umanager->msg, 0, -1)))); + + //reactivate messaging + StudipMail::setDefaultTransporter($default_mailer); + } + + PageLayout::postSuccess(_('Die Personen wurden migriert.'), $details); + $this->redirect('admin/user/edit/' . $new_id); + } else { + PageLayout::postError(_('Bitte wählen Sie zwei gültige Personen aus.')); + } + } + $this->user = $user_id ? User::find($user_id) : null; + } + + /** + * Set the password of an user to a new random password, without security-query + * + * @param md5 $user_id + */ + public function change_password_action($user_id) + { + // mail address did not change, so skip this check + $GLOBALS['MAIL_VALIDATE_BOX'] = false; + $UserManagement = new UserManagement($user_id); + if ($UserManagement->setPassword()) { + PageLayout::postSuccess(_('Es wurde eine Mail mit einem Link zum Neusetzen ' + . 'des Passworts verschickt, das bestehende Passwort wurde nicht verändert.')); + } else { + $details = explode('§', str_replace(['msg§', 'info§', 'error§'], '', mb_substr($UserManagement->msg, 0, -1))); + PageLayout::postError(_('Die Änderungen konnten nicht gespeichert werden.'), $details); + } + if (Request::int('from_index')) { + $this->redirect('admin/user'); + } else { + $this->redirect('admin/user/edit/' . $user_id); + } + } + + /** + * Add lock-comment for locked user + * @param $user_id + */ + public function lock_comment_action($user_id) + { + $this->user = User::find($user_id); + PageLayout::setTitle(sprintf(_('%s sperren'), $this->user->getFullname())); + + $this->params = []; + if (Request::int('from_index')) { + $this->params['from_index'] = 1; + } + } + + /** + * Lock user + * @param $user_id + */ + public function lock_action($user_id) + { + CSRFProtection::verifyUnsafeRequest(); + $user = User::find($user_id); + + $user->locked = 1; + $user->lock_comment = Request::get('lock_comment'); + $user->locked_by = $GLOBALS['user']->id; + + if ($user->store()) { + PageLayout::postSuccess(sprintf( + _('%s wurde gesperrt.'), + htmlReady($user->getFullname()) + )); + } + + if (Request::int('from_index')) { + $this->redirect('admin/user'); + } else { + $this->redirect('admin/user/edit/' . $user_id); + } + } + + /** + * Unlock an user, without security-query + * + * @param md5 $user_id + */ + public function unlock_action($user_id) + { + $user = User::find($user_id); + + $user->locked = 0; + $user->lock_comment = null; + $user->locked_by = null; + + if ($user->store()) { + PageLayout::postSuccess(sprintf( + _('%s wurde entsperrt.'), + htmlReady($user->getFullname()) + )); + } else { + PageLayout::postError(sprintf( + _('%s konnte nicht entsperrt werden.'), + htmlReady($user->getFullname()) + )); + } + + if (Request::int('from_index')) { + $this->redirect('admin/user'); + } else { + $this->redirect('admin/user/edit/' . $user_id); + } + } + + + /** + * Display institute informations of an user and save changes to it. + * + * @param md5 $user_id + * @param md5 $institute_id + */ + public function edit_institute_action($user_id, $institute_id) + { + $this->user = User::find($user_id); + if (count($this->user->institute_memberships)) { + $institute = null; + $this->user->institute_memberships->filter(function ($a) use ($institute_id, &$institute) { + if ($a->institut_id === $institute_id) { + $institute = $a; + } + }); + } + + $this->institute = $institute; + $this->faecher = StudyCourse::findBySQL('1 ORDER BY name'); + $this->abschluesse = Abschluss::findBySQL('1 ORDER by name'); + $this->perms = $this->user->getInstitutePerms(); + $this->datafields = DataFieldEntry::getDataFieldEntries([$user_id, $institute_id], 'userinstrole'); + } + + /** + * Set user institute information + * @param $user_id + * @param $institute_id + */ + public function store_user_institute_action($user_id, $institute_id) + { + CSRFProtection::verifyRequest(); + + $inst_membership = InstituteMember::findOneBySQL('user_id = ? AND institut_id = ?', [$user_id, $institute_id]); + + //change datafields + $datafields = Request::getArray('datafields'); + foreach ($datafields as $id => $data) { + $datafield = DataField::find($id); + $entry = DataFieldEntry::createDataFieldEntry($datafield, [$user_id, $institute_id]); + $entry->setValueFromSubmit($data); + if ($entry->isValid()) { + $entry->store(); + } + } + + if ($inst_membership->inst_perms != Request::get('inst_perms')) { + StudipLog::log('INST_USER_STATUS', $institute_id, $user_id, $inst_membership->inst_perms . ' -> ' . Request::get('inst_perms')); + NotificationCenter::postNotification('UserInstitutionPermDidUpdate', $institute_id, $user_id); + } + + $inst_membership->inst_perms = Request::get('inst_perms', ''); + $inst_membership->visible = Request::int('visible', 0); + $inst_membership->sprechzeiten = Request::get('sprechzeiten', ''); + $inst_membership->telefon = Request::get('telefon', ''); + $inst_membership->fax = Request::get('fax', ''); + $inst_membership->externdefault = Request::int('externdefault', 0); + $inst_membership->raum = Request::get('raum', ''); + $inst_membership->store(); + + //output + PageLayout::postSuccess(_('Die Einrichtungsdaten der Person wurden geändert.')); + $this->relocate('admin/user/edit/' . $user_id); + return; + } + + /** + * Delete an studycourse of an user , without a security-query + * + * @param md5 $user_id + * @param md5 $fach_id + * @param md5 $abschluss_id + */ + public function delete_studycourse_action($user_id, $fach_id, $abschlus_id) + { + $user_stc = UserStudyCourse::find([$user_id, $fach_id, $abschlus_id]); + $deleted = false; + if ($user_stc) { + $deleted = $user_stc->delete(); + } + if ($deleted) { + PageLayout::postSuccess(_('Die Zuordnung zum Studiengang wurde gelöscht.')); + } else { + PageLayout::postError(_('Die Zuordnung zum Studiengang konnte nicht gelöscht werden.')); + } + $this->redirect('admin/user/edit/' . $user_id); + } + + /** + * Delete an institute of an user , without a security-query + * + * @param md5 $user_id + * @param md5 $institut_id + */ + public function delete_institute_action($user_id, $institut_id) + { + if ($GLOBALS['perm']->have_studip_perm("admin", $institut_id)) { + $groups = GetAllStatusgruppen($institut_id); + $group_list = GetRoleNames($groups, 0, '', true); + if (is_array($group_list) && count($group_list) > 0) { + $query = "DELETE FROM statusgruppe_user + WHERE statusgruppe_id IN (?) AND user_id = ?"; + $statement = DBManager::get()->prepare($query); + $statement->execute([array_keys($group_list), $user_id]); + } + + $db = DBManager::get()->prepare("DELETE FROM user_inst WHERE user_id = ? AND Institut_id = ?"); + $db->execute([$user_id, $institut_id]); + if ($db->rowCount() == 1) { + StudipLog::log('INST_USER_DEL', $institut_id, $user_id); + NotificationCenter::postNotification('UserInstitutionDidDelete', $institut_id, $user_id); + InstituteMember::ensureDefaultInstituteForUser($user_id); + if (UserConfig::get($user_id)->MY_INSTITUTES_DEFAULT == $institut_id) { + UserConfig::get($user_id)->delete('MY_INSTITUTES_DEFAULT'); + } + PageLayout::postSuccess(_('Die Zuordnung zur Einrichtung wurde gelöscht.')); + } else { + PageLayout::postError(_('Die Zuordnung zur Einrichtung konnte nicht gelöscht werden.')); + } + } else { + PageLayout::postError(_('Die Zuordnung zur Einrichtung konnte nicht gelöscht werden.')); + } + $this->redirect('admin/user/edit/' . $user_id); + } + + /** + * Delete an assignment of an user to an userdomain, without a security-query + * + * @param md5 $user_id + */ + public function delete_userdomain_action($user_id) + { + $domain_id = Request::get('domain_id'); + UserDomain::find($domain_id)->removeUser($user_id); + $result = AutoInsert::instance()->saveUser($user_id); + + $details = []; + + foreach ($result['added'] as $item) { + $details[] = sprintf(_('Das automatische Eintragen in die Veranstaltung <em>%s</em> wurde durchgeführt.'), $item); + } + foreach ($result['removed'] as $item) { + $details[] = sprintf(_('Das automatische Austragen aus der Veranstaltung <em>%s</em> wurde durchgeführt.'), $item); + } + + PageLayout::postSuccess(_('Die Zuordnung zur Nutzerdomäne wurde erfolgreich gelöscht.'), $details); + $this->redirect('admin/user/edit/' . $user_id); + } + + /** + * Reset notfication for user + * @param $user_id + */ + public function reset_notification_action($user_id) + { + $resetted = CourseMemberNotification::deleteBySQL("user_id = ?", [$user_id]); + PageLayout::postSuccess(sprintf(_('Die Benachrichtigungseinstellungen für %s Veranstaltungen wurden zurück gesetzt.'), $resetted)); + $this->redirect('admin/user/edit/' . $user_id); + } + + /** + * Reset two factor authentication for user + * @param $user_id + */ + public function reset_tfa_action($user_id) + { + if (TFASecret::deleteByUser_id($user_id)) { + PageLayout::postSuccess(_('Die Zwei-Faktor-Authentifizierung wurde für diese Person deaktiviert.')); + } + $this->redirect('admin/user/edit/' . $user_id); + } + + /** + * Show user activities + * @param $user_id + * @throws Exception + */ + public function activities_action($user_id) + { + $this->user = User::find($user_id); + $this->fullname = $this->user->getFullname(); + $this->params = []; + + if (Request::int('from_index')) { + $this->params['from_index'] = 1; + } + if (is_null($this->user)) { + throw new Exception(_('Nutzer nicht gefunden')); + } + PageLayout::setTitle(sprintf(_('Datei- und Aktivitätsübersicht für %s'), $this->fullname)); + + + $this->queries = $this->getActivities($user_id); + + $memberships = DBManager::get()->fetchAll("SELECT seminar_user.*, seminare.Name as course_name + FROM seminar_user + LEFT JOIN seminare USING (seminar_id) + WHERE user_id = ? ORDER BY seminare.start_time DESC, seminare.Name", + [$user_id], + 'CourseMember::buildExisting'); + + $courses = []; + $course_files = []; + $closed_courses = []; + $this->sections = []; + + foreach ($memberships as $membership) { + if (!Request::get('view') || Request::get('view') === 'files') { + // count files for course + + $top_folder = Folder::findTopFolder($membership->seminar_id); + $top_folder = $top_folder->getTypedFolder(); + $count = FileManager::countFilesInFolder($top_folder, true, $user_id); + + + if ($count) { + if (!isset($course_files[$membership->seminar_id])) { + $course_files[$membership->course->start_semester->name][$membership->course->id]['course'] = $membership->course; + } + $course_files[$membership->course->start_semester->name][$membership->course->id]['files'] = $count; + } + } + if (in_array(Request::get('view'), words('courses closed_courses'))) { + // check for closed courses + $closed_course + = $closed_course = DBManager::get()->fetchColumn('SELECT COUNT(sc.seminar_id) FROM seminar_courseset sc + INNER JOIN courseset_rule cr ON cr.set_id=sc.set_id AND cr.type="ParticipantRestrictedAdmission" + WHERE sc.seminar_id =?', [$membership->seminar_id]); + + if ((int)$closed_course) { + $closed_courses[$membership->course->start_semester->name][$membership->course->id] = $membership; + } else { + $courses[$membership->course->start_semester->name][$membership->course->id] = $membership; + } + } + } + + if (!Request::get('view') || Request::get('view') === 'files') { + $institutes = Institute::getMyInstitutes($user_id); + if (!empty($institutes)) { + foreach ($institutes as $index => $institute) { + $top_folder = Folder::findTopFolder($institute['Institut_id']); + + $top_folder = $top_folder->getTypedFolder(); + + $count = FileManager::countFilesInFolder($top_folder, true, $user_id); + + if ($count) { + $institutes[$index]['files'] = $count; + } else { + unset($institutes[$index]); + } + } + } + } + + if (Request::get('view') === 'seminar_wait') { + // waiting list + $seminar_wait = AdmissionApplication::findByUser($user_id); + } elseif (Request::get('view') === 'priorities') { + // priorities + $priorities = DBManager::get()->fetchAll('SELECT * FROM `priorities` WHERE `user_id` = ?', [$user_id]); + } + + if (!empty($course_files)) { + $this->sections['course_files'] = $course_files; + } + if (!empty($institutes)) { + $this->sections['institutes'] = $institutes; + } + if (!empty($courses)) { + $this->sections['courses'] = $courses; + } + if (!empty($courses)) { + $this->sections['closed_courses'] = $closed_courses; + } + + if (is_array($seminar_wait) && count($seminar_wait)) { + $this->sections['seminar_wait'] = $seminar_wait; + } + + if (!empty($priorities)) { + $this->sections['priorities'] = $priorities; + } + } + + /** + * List files for course or institute + * @param $user_id + * @param $course_id + */ + public function list_files_action($user_id, $range_id) + { + $this->user = User::find($user_id); + $folder = Folder::findTopFolder($range_id); + if($folder) { + $folder = $folder->getTypedFolder(); + } + + if($folder) { + //Folder exists: We can collect all subfolders in the folder. + $this->folders = FileManager::getFolderFilesRecursive($folder, $this->user->id)['folders']; + } else { + //Folder does not exist: We can't collect any subfolders. + $this->folders = []; + } + + $this->range = Course::find($range_id); + if (is_null($this->range)) { + $this->range = Institute::find($range_id); + } + PageLayout::setTitle(sprintf(_('Dateiübersicht für %s'), $this->range->getFullname())); + } + + /** + * Create array + * @param $user_id + * @return array + */ + private function getActivities($user_id) + { + $queries[] = [ + 'desc' => _('Eingetragen in Veranstaltungen (dozent / tutor / autor / user)'), + 'query' => "SELECT CONCAT_WS(' / ', SUM(status = 'dozent'), SUM(status = 'tutor'), + SUM(status = 'autor'), SUM(status = 'user')) + FROM seminar_user + WHERE user_id = ? + GROUP BY user_id", + 'details' => "courses", + ]; + $queries[] = [ + 'desc' => _('Eingetragen in geschlossenen Veranstaltungen (dozent / tutor / autor / user)'), + 'query' => "SELECT CONCAT_WS(' / ', SUM(su.status = 'dozent'), SUM(su.status = 'tutor'), + SUM(su.status = 'autor'), SUM(su.status = 'user')) + FROM seminar_user AS su + INNER JOIN seminar_courseset sc USING (seminar_id) + INNER JOIN courseset_rule cr ON cr.set_id=sc.set_id AND cr.type='ParticipantRestrictedAdmission' + WHERE user_id = ? + GROUP BY user_id", + 'details' => "closed_courses", + ]; + $queries[] = [ + 'desc' => _("Eingetragen in Wartelisten (wartend / vorläufig akzeptiert)"), + 'query' => "SELECT CONCAT_WS(' / ', SUM(status = 'awaiting'), SUM(status = 'accepted')) + FROM admission_seminar_user + WHERE user_id = ? + GROUP BY user_id", + 'details' => "seminar_wait", + ]; + $queries[] = [ + 'desc' => _("Eingetragen in Anmeldelisten"), + 'query' => "SELECT COUNT(*) + FROM priorities + WHERE user_id = ? + GROUP BY user_id", + 'details' => "priorities", + ]; + $queries[] = [ + 'desc' => _("Eingetragen in Einrichtungen (admin / dozent / tutor / autor)"), + 'query' => "SELECT CONCAT_WS(' / ', SUM(inst_perms = 'admin'), SUM(inst_perms = 'dozent'), + SUM(inst_perms = 'tutor'), SUM(inst_perms = 'autor')) + FROM user_inst + WHERE user_id = ? + GROUP BY user_id", + ]; + $queries[] = [ + 'desc' => _("Anzahl der Ankündigungen"), + 'query' => "SELECT COUNT(*) FROM news WHERE user_id = ? GROUP BY user_id", + ]; + $queries[] = [ + 'desc' => _("Anzahl der Wikiseiten"), + 'query' => "SELECT COUNT(*) FROM wiki WHERE user_id = ? GROUP BY user_id", + ]; + $queries[] = [ + 'desc' => _("Anzahl der Umfragen"), + 'query' => "SELECT COUNT(*) FROM questionnaires WHERE user_id = ? GROUP BY user_id", + ]; + $queries[] = [ + 'desc' => _("Anzahl der Evaluationen"), + 'query' => "SELECT COUNT(*) FROM eval WHERE author_id = ? GROUP BY author_id", + ]; + $queries[] = [ + 'desc' => _("Anzahl der Dateien in Veranstaltungen und Einrichtungen"), + 'query' => "SELECT COUNT(file_refs.id) + FROM (file_refs INNER JOIN files ON file_refs.file_id = files.id) + INNER JOIN folders ON file_refs.folder_id = folders.id + WHERE (file_refs.user_id = ?) + AND ( + (folders.range_type = 'course') + OR (folders.range_type = 'institute') + ) + GROUP BY file_refs.user_id", + 'details' => "files", + ]; + $queries[] = [ + 'desc' => _("Gesamtgröße der hochgeladenen Dateien in Veranstaltungen und Einrichtungen (in Megabytes)"), + 'query' => "SELECT FORMAT(SUM(files.size)/1000000,2) + FROM (file_refs INNER JOIN files ON file_refs.file_id = files.id) + INNER JOIN folders ON file_refs.folder_id = folders.id + WHERE (file_refs.user_id = ?) + AND (files.filetype = 'StandardFile') + AND ( + (folders.range_type = 'course') + OR (folders.range_type = 'institute') + ) + GROUP BY file_refs.user_id", + 'details' => "files", + ]; + + foreach (PluginEngine::getPlugins('ForumModule') as $plugin) { + $table = $plugin->getEntryTableInfo(); + $queries[] = [ + 'desc' => $plugin->getPluginName() . ' - ' . _("Anzahl der Postings"), + 'query' => 'SELECT COUNT(*) FROM `' . $table['table'] . '` + WHERE `' . $table['user_id'] . '` = ? + GROUP BY `' . $table['user_id'] . '`', + ]; + } + + // Evaluate queries + foreach ($queries as $index => $query) { + $statement = DBManager::get()->prepare($query['query']); + $statement->execute([$user_id]); + $queries[$index]['value'] = $statement->fetchColumn() ?: 0; + } + + return $queries; + } + + + /** + * Download documents + * @param string $user_id + * @param string $range_id + */ + public function download_user_files_action($user_id, $range_id = null) + { + global $TMP_PATH; + + Seminar_Perm::get()->check('root'); + + if ($range_id === null) { + $file_refs = FileRef::findBySQL("INNER JOIN folders ON folders.id = file_refs.folder_id WHERE folders.range_type IN ('course','institute') AND file_refs.user_id = ? GROUP BY file_id ORDER BY NULL", [$user_id]); + } else { + $file_refs = FileRef::findBySQL("INNER JOIN folders ON folders.id = file_refs.folder_id WHERE folders.range_id = ? AND file_refs.user_id = ? GROUP BY file_id ORDER BY NULL", [$range_id, $user_id]); + } + + $user = User::find($user_id); + + $archive_file_name = $user->username . '_files_' . date('Ymd-Hi') . '.zip'; + + $archive_path = $TMP_PATH . '/' . $archive_file_name; + + $result = FileArchiveManager::createArchiveFromFileRefs( + $file_refs, + User::findCurrent(), + $archive_path, + false + ); + + + $archive_download_link = FileManager::getDownloadURLForTemporaryFile( + $archive_path, + $archive_file_name + ); + + $this->redirect($archive_download_link); + } + + /** + * Init sidebar + */ + public function addSidebar() + { + $sidebar = Sidebar::Get(); + + $actions = $sidebar->addWidget(new ActionsWidget()); + + if (in_array('Standard', $GLOBALS['STUDIP_AUTH_PLUGIN'])) { + $actions->addLink( + _('Neues Konto anlegen'), + $this->url_for('admin/user/new'), + Icon::create('person+add') + )->asDialog(); + } + $actions->addLink( + _('Vorläufiges Konto anlegen'), + $this->url_for('admin/user/new/prelim'), + Icon::create('date+add') + )->asDialog(); + $actions->addLink( + _('Konten zusammenführen'), + $this->url_for('admin/user/migrate/' . (($this->user && is_array($this->user)) ? $this->user['user_id'] : '')), + Icon::create('persons+new') + ); + + $search = $sidebar->addWidget(new SearchWidget()); + $search->addNeedle(_('Person suchen'), + 'user_id', + true, + new StandardSearch('user_id'), + 'function (value) { document.location = STUDIP.URLHelper.getURL("dispatch.php/admin/user/edit/" + value); }' + ); + + if ($this->action === 'index' && !empty($this->users)) { + $export = $sidebar->addWidget(new ExportWidget()); + $export->addLink(_('Suchergebnis exportieren'), + $this->url_for('admin/user?export=1'), + Icon::create('persons+move_right') + ); + } + + if (!is_object($this->user)) { + return; + } + + $user_actions = new ActionsWidget(); + $user_actions->setTitle(sprintf(_('Aktionen für "%s"'), $this->user->username)); + + $user_actions->addLink( + _('Nachricht an Person verschicken'), + URLHelper::getURL('dispatch.php/messages/write', ['rec_uname' => $this->user->username]), + Icon::create('mail') + )->asDialog(); + + if ($this->user->locked) { + $user_actions->addLink( + _('Personenaccount entsperren'), + $this->url_for("admin/user/unlock/{$this->user->id}"), + Icon::create('lock-unlocked') + ); + } else { + $user_actions->addLink( + _('Personenaccount sperren'), + $this->url_for("admin/user/lock_comment/{$this->user->id}"), + Icon::create('lock-locked') + )->asDialog('size=auto'); + } + + if ($this->user->auth_plugin !== null && ($GLOBALS['perm']->have_perm('root') || $GLOBALS['perm']->is_fak_admin() || !in_array($this->user->perms, words('root admin')))) { + if (!StudipAuthAbstract::CheckField('auth_user_md5.password', $this->user->auth_plugin)) { + $user_actions->addLink( + _('Passwortlink zusenden'), + $this->url_for("admin/user/change_password/{$this->user->id}"), + Icon::create('key') + ); + } + $user_actions->addLink( + _('Person löschen'), + $this->url_for("admin/user/bulk/{$this->user->id}", ['method' => 'delete']), + Icon::create('trash') + )->asDialog('size=auto'); + } + if (Config::get()->MAIL_NOTIFICATION_ENABLE && CourseMemberNotification::findOneBySQL("user_id = ?", [$this->user->user_id])) { + $user_actions->addLink( + _('Benachrichtigungen zurücksetzen'), + $this->url_for("admin/user/reset_notification/{$this->user->id}"), + Icon::create('refresh') + ); + } + + if ($this->action === 'activities') { + $user_actions->addLink( + _('Alle Dateien des Nutzers aus Veranstaltungen und Einrichtungen als ZIP herunterladen'), + $this->url_for("admin/user/download_user_files/{$this->user->user_id}"), + Icon::create('folder-full') + ); + } + + if ($this->user->id !== $GLOBALS['user']->id && TFASecret::exists($this->user->id)) { + $user_actions->addLink( + _('Zwei-Faktor-Authentifizierung deaktivieren'), + $this->url_for("admin/user/reset_tfa/{$this->user->id}"), + Icon::create('code-qr') + ); + } + + $sidebar->insertWidget($user_actions, 'actions', 'user_actions'); + + // Privacy options + if (Privacy::isVisible($this->user->user_id)) { + $privacy = $sidebar->addWidget(new LinksWidget()); + $privacy->setTitle(_('Datenschutz')); + + $privacy->addLink( + _('Anzeige Personendaten'), + $this->url_for("privacy/landing/{$this->user->id}"), + Icon::create('log') + )->asDialog('size=medium'); + + $privacy->addLink( + _('Personendaten drucken'), + $this->url_for("privacy/print/{$this->user->id}"), + Icon::create('print'), + ['class' => 'print_action', 'target' => '_blank'] + ); + + $privacy->addLink( + _('Export Personendaten als CSV'), + $this->url_for("privacy/export/{$this->user->id}"), + Icon::create('file-text') + ); + + $privacy->addLink( + _('Export Personendaten als XML'), + $this->url_for("privacy/xml/{$this->user->id}"), + Icon::create('file-text') + ); + + $privacy->addLink( + _('Export persönlicher Dateien als ZIP'), + $this->url_for("privacy/filesexport/{$this->user->id}"), + Icon::create('file-archive') + ); + } + + $views = new ViewsWidget(); + $views->addLink( + _('Zurück zur Übersicht'), + $this->url_for('admin/user') + )->setActive(false); + $views->addLink( + _('Person verwalten'), + $this->url_for("admin/user/edit/{$this->user->id}") + )->setActive($this->action === 'edit'); + $views->addLink( + _('Zum Profil'), + URLHelper::getURL('dispatch.php/profile', ['username' => $this->user->username]), + Icon::create('person') + ); + + if ($GLOBALS['perm']->have_perm('root') && count($this->user)) { + $views->addLink( + _('Datei- und Aktivitätsübersicht'), + $this->url_for("admin/user/activities/{$this->user->id}"), + Icon::create('vcard') + )->setActive($this->action === 'activities'); + + + if (Config::get()->LOG_ENABLE) { + $views->addLink( + _('Personeneinträge im Log'), + URLHelper::getURL('dispatch.php/event_log/show?search=' . $this->user->username . '&type=user&object_id=' . $this->user->user_id), + Icon::create('log') + ); + } + + // Create link to role administration for this user + $extra = ''; + $roles = $this->user->getRoles(); + $roles_attributes = []; + if ($roles) { + $extra = ' (' . count($roles) . ')'; + $title = '• ' . implode("\n• ", array_map(function ($role) { + return $role->rolename; + }, $roles)); + $roles_attributes['data-tooltip'] = json_encode([ + 'html' => htmlReady($title, true, true), + ]); + } + + $views->addLink( + _('Zur Rollenverwaltung') . $extra, + $this->url_for("admin/role/assign_role/{$this->user->id}"), + Icon::create('roles2'), + $roles_attributes + ); + } + $sidebar->insertWidget($views, 'user_actions', 'views'); + } +} |
