aboutsummaryrefslogtreecommitdiff
path: root/app/controllers/privacy.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers/privacy.php')
-rw-r--r--app/controllers/privacy.php458
1 files changed, 458 insertions, 0 deletions
diff --git a/app/controllers/privacy.php b/app/controllers/privacy.php
new file mode 100644
index 0000000..60d3c33
--- /dev/null
+++ b/app/controllers/privacy.php
@@ -0,0 +1,458 @@
+<?php
+/**
+ * PrivacyController
+ *
+ * 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 Timo Hartge <hartge@data-quest.de>
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
+ * @category Stud.IP
+ * @since 4.2
+ */
+
+class PrivacyController extends AuthenticatedController
+{
+ /**
+ * Presents the userdata of given user
+ *
+ * @param string $user_id
+ * @param string $section
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function index_action($user_id, $section = null)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ Navigation::activateItem('/profile');
+
+ $this->plugin_data = Privacy::getUserdataInformation($user_id, $section);
+ $this->user_id = $user_id;
+ $this->section = $section;
+
+ $actions = Sidebar::Get()->addWidget(new ActionsWidget());
+ $actions->setTitle(_('Datenschutz'));
+ $actions->addLink(
+ _('Anzeige Personendaten'),
+ $this->url_for("privacy/landing/{$user_id}"),
+ Icon::create('log', Icon::ROLE_CLICKABLE, tooltip2(_('Anzeige Personendaten')))
+ )->asDialog('size=medium');
+ $actions->addLink(
+ _('Personendaten drucken'),
+ $this->url_for('privacy/print/' . $user_id),
+ Icon::create('print', Icon::ROLE_CLICKABLE, tooltip2(_('Personendaten drucken'))),
+ ['class' => 'print_action', 'target' => '_blank']
+ );
+ $actions->addLink(
+ _('Export Personendaten als CSV'),
+ $this->url_for("privacy/export/{$user_id}"),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(_('Export Personendaten als CSV')))
+ );
+ $actions->addLink(
+ _('Export persönlicher Dateien als XML'),
+ $this->url_for("privacy/xml/{$user_id}"),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(_('Export Personendaten als XML')))
+ );
+ $actions->addLink(
+ _('Export persönlicher Dateien als ZIP'),
+ $this->url_for("privacy/filesexport/{$user_id}"),
+ Icon::create('file-archive', Icon::ROLE_CLICKABLE, tooltip2(_('Export persönlicher Dateien als ZIP')))
+ );
+
+
+ $exports = Sidebar::Get()->addWidget(new ExportWidget());
+ $exports->addLink(
+ _('Export angezeigter Dateien als XML'),
+ $this->url_for("privacy/xml/{$user_id}" . ($section ? "/{$section}" : '')),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(_('Export angezeigter Daten als XML')))
+ );
+
+ foreach ($this->plugin_data as $label => $tabledata) {
+ $exports->addLink(
+ htmlReady($label) . ' ' . _('CSV'),
+ $this->url_for("privacy/export2csv/{$tabledata['table_name']}/{$user_id}"),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(htmlReady($label) . ' CSV'))
+ );
+ }
+ }
+
+ /**
+ * Gives access to accumulated userdata or single categories
+ *
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function landing_action($user_id)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ Navigation::activateItem('/profile');
+
+ $this->user_id = $user_id;
+ $this->sections = $this->getViewSections();
+
+ $actions = Sidebar::Get()->addWidget(new ActionsWidget());
+ $actions->setTitle(_('Datenschutz'));
+ $actions->addLink(
+ _('Personendaten drucken'),
+ $this->url_for("privacy/print/{$user_id}"),
+ Icon::create('print', Icon::ROLE_CLICKABLE, tooltip2(_('Personendaten drucken'))),
+ ['class' => 'print_action', 'target' => '_blank']
+ );
+ $actions->addLink(
+ _('Export Personendaten als CSV'),
+ $this->url_for("privacy/export/{$user_id}"),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(_('Export Personendaten als CSV')))
+ );
+ $actions->addLink(
+ _('Export persönlicher Dateien als XML'),
+ $this->url_for("privacy/xml/{$user_id}"),
+ Icon::create('file-text', Icon::ROLE_CLICKABLE, tooltip2(_('Export Personendaten als XML')))
+ );
+ $actions->addLink(
+ _('Export persönlicher Dateien als ZIP'),
+ $this->url_for("privacy/filesexport/{$user_id}"),
+ Icon::create('file-archive', Icon::ROLE_CLICKABLE, tooltip2(_('Export persönlicher Dateien als ZIP')))
+ );
+ }
+
+ /**
+ * Create a csv file with user data from a specific table of a plugin
+ *
+ * @param string $plugin_id
+ * @param string $table
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function export2CSV_action($table, $user_id)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ $plugin_data = Privacy::getUserdataInformation($user_id);
+
+ if (!empty($plugin_data)) {
+ foreach($plugin_data as $table_label => $table_data) {
+ if ($table_data['table_name'] !== $table) {
+ continue;
+ }
+
+ $data = $table_data['table_content'];
+ $headers = array_keys($data[0]);
+ $csvdata = [];
+ foreach ($data as $row) {
+ $csvdata[] = array_values($row);
+ }
+ $this->render_csv(array_merge([$headers], $csvdata), "{$table}.csv");
+ return;
+ }
+ }
+
+ PageLayout::postError(_("Die Daten konnten nicht exportiert werden."));
+ $this->redirect('privacy/index');
+ }
+
+ /**
+ * Create a print view with user data
+ *
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function print_action($user_id)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ PageLayout::removeStylesheet('style.css');
+ PageLayout::addStylesheet('print.css');
+
+ $user = User::find($user_id);
+ $this->plugin_data = Privacy::getUserdataInformation($user_id);
+ $this->user_id = $user_id;
+ $this->user_fullname = $user->getFullName();
+ }
+
+ /**
+ * Create a zip file with user data
+ *
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function export_action($user_id)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ $user = User::find($user_id);
+ $plugin_data = Privacy::getUserdataInformation($user_id);
+ $files = [];
+ $csv = [];
+
+ foreach ($plugin_data as $label => $table) {
+ $data = $table['table_content'];
+ if ($data) {
+ $headers = array_keys($data[0]);
+ $csvdata = [];
+ foreach ($data as $row) {
+ $csvdata[] = array_values($row);
+ }
+ $tmpname = md5(uniqid($user_id.$table['table_name']));
+ $filepath = $GLOBALS['TMP_PATH'] . DIRECTORY_SEPARATOR . $tmpname;
+ if (array_to_csv($csvdata, $filepath, $headers)) {
+ $csv[$table['table_name']] = $filepath;
+ }
+ }
+ }
+
+ $tmpname = md5(uniqid('datenexport_' . $user->username));
+ $zipname = $GLOBALS['TMP_PATH'] . DIRECTORY_SEPARATOR . $tmpname;
+ $zip = new ZipArchive;
+ $zip->open($zipname, ZipArchive::CREATE);
+ foreach ($csv as $table => $file) {
+ $zip->addFile($file, $table . '.csv');
+ }
+ if ($zip->close()) {
+ foreach ($files as $plugin => $plugin_files) {
+ foreach ($plugin_files as $table => $file) {
+ unlink($file);
+ }
+ }
+ }
+
+ $this->render_temporary_file(
+ $zipname,
+ "datenexport_{$user->username}.zip",
+ 'application/zip'
+ );
+ }
+
+ /**
+ * Create a xml file with user data
+ *
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function xml_action($user_id, $section = null)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+ $user = User::find($user_id);
+
+ $plugin_data = Privacy::getUserdataInformation($user_id, $section);
+
+ $xml = new SimpleXMLElement('<xml/>');
+ foreach ($plugin_data as $label => $tabledata) {
+ if ($tabledata['table_content']) {
+ $table = $xml->addChild('table');
+ $table->addChild('tablename', $tabledata['table_name']);
+ foreach ($tabledata['table_content'] as $row) {
+ $tableentry = $table->addChild('tableentry');
+ foreach ($row as $key => $value){
+ $tableentry->addChild('field', $key);
+ $tableentry->addChild('value', htmlReady($value));
+ }
+ }
+ }
+ }
+
+ $this->set_content_type('text/xml');
+ $this->response->add_header(
+ 'Content-disposition',
+ 'attachment;' . encode_header_parameter('filename', "datenexport_{$user->username}.xml")
+ );
+ $this->render_text($xml->asXML());
+
+ }
+
+ /**
+ * Delivers a zip containing the files from plugins which feature the specific function
+ *
+ * @param string $user_id
+ * @throws AccessDeniedException if user has no privileges
+ */
+ public function filesexport_action($user_id)
+ {
+ if (!Privacy::isVisible($user_id)) {
+ throw new AccessDeniedException();
+ }
+
+ $storage = new StoredUserData($user_id);
+ $user = User::find($user_id);
+ $files = [];
+
+ $tmpname = md5(uniqid('dateiexport_' . $user_id));
+ $zipname = $GLOBALS['TMP_PATH'] . DIRECTORY_SEPARATOR . $tmpname;
+
+ $zip = new ZipArchive();
+ $zip->open($zipname, ZipArchive::CREATE);
+
+ $avatar = Avatar::getAvatar($user_id);
+ if ($avatar->is_customized()) {
+ $zip->addFile($avatar->getCustomAvatarPath('normal'), $user_id . '.png');
+ }
+
+ foreach (FileRef::findByUser_id($user_id) as $fileref) {
+ $storage->addFileRef($fileref);
+ }
+
+ foreach (PluginEngine::getPlugins('PrivacyPlugin') as $plugin) {
+ $plugin->exportUserData($storage);
+ }
+
+ // add numbering structure to zip
+ $source_files = $storage->getFileData();
+
+ $file_names = [];
+ foreach ($source_files as $k => $file_data) {
+ $file_names[$file_data['name']][] = $k;
+ }
+ $fname_checker = [];
+ do {
+ $not_clear = false;
+ foreach ($file_names as $fname => $dups) {
+ $total_dups = count($dups);
+ if ($total_dups > 1 && !in_array($fname,$fname_checker)) {
+ $name = pathinfo($fname)["filename"];
+ $ext = pathinfo($fname)["extension"];
+ for ($i = 1; $i < $total_dups; $i++) {
+ $next = $name . "[$i]." . $ext ;
+ $nodup = true;
+ do {
+ if (array_key_exists($next, $file_names)) {
+ $next_origin_new_name = pathinfo($next)["filename"] . '-origin.' . pathinfo($next)["extension"];
+ $file_names[$next_origin_new_name] = $file_names[$next];
+ unset($file_names[$next]);
+ $fname_checker[] = $next;
+ } else {
+ $nodup = false;
+ }
+ } while ($nodup);
+ $file_names[$next][] = $dups[$i];
+ $fname = $next;
+ unset($file_names[$name . '.' . $ext][$i]);
+ }
+ }
+ }
+ foreach ($file_names as $fname => $dups) {
+ $total_dups = count($dups);
+ if ($total_dups > 1) {
+ $not_clear = true;
+ } else {
+ $source_files[$dups[0]]['name'] = $fname;
+ }
+ }
+ } while ($not_clear);
+
+
+ foreach ($source_files as $file_data) {
+ if (isset($file_data['path'])) {
+ $zip->addFile($file_data['path'], $file_data['name']);
+ } else {
+ $zip->addFromString($file_data['name'], $file_data['contents']);
+ }
+ }
+
+ $zip->close();
+
+ if (!file_exists($zipname)) {
+ PageLayout::postError(_('Keine Dateien vorhanden.'));
+ $this->redirect("privacy/index/" . $user_id);
+ return;
+ }
+
+ $archive_download_link = FileManager::getDownloadURLForTemporaryFile(
+ $zipname,
+ "dateiexport_{$user->username}.zip"
+ );
+
+ $this->redirect($archive_download_link);
+ }
+
+ /**
+ * Show a message dialog to ask for user data
+ *
+ * @param string $user_id
+ */
+ public function askfor_action($user_id)
+ {
+ $mail_user = Config::get()->PRIVACY_CONTACT;
+
+ $user = User::findByUsername($mail_user);
+ if ($user) {
+ $mail_subject = _('Auskunft nach Art 15 DSGVO');
+ $mail_message = _("Sehr geehrte Damen und Herren,\n\nhiermit bitte ich Sie nach Art 15 DSGVO, mir Auskunft über die über mich gespeicherten personenbezogenen Daten zu geben.");
+ $this->redirect(URLHelper::getURL('dispatch.php/messages/write', [
+ 'rec_uname' => $mail_user,
+ 'default_subject' => $mail_subject,
+ 'default_body' => $mail_message,
+ ]));
+ } else {
+ $this->render_text(MessageBox::error(
+ _('Es wurde keine Kontaktperson bestimmt.'),
+ [_('Bitte wenden Sie sich an den in der Datenschutzerklärung angegebenen Ansprechpartner.'),]
+ ));
+ }
+ }
+
+ /**
+ * Returns a list of all the sections to be displayed.
+ * @return array of arrays (key => icon, title, description)
+ */
+ protected function getViewSections()
+ {
+ return [
+ '' => [
+ 'icon' => Icon::create('persons'),
+ 'title' => _('Alle Daten'),
+ 'description' => _('Übersicht aller Personendaten'),
+ ],
+ 'core' => [
+ 'icon' => Icon::create('person'),
+ 'title' => _('Kerndaten'),
+ 'description' => _('Angaben zur Person, Konfigurationen, Logs'),
+ ],
+ 'membership' => [
+ 'icon' => Icon::create('seminar'),
+ 'title' => _('Veranstaltungen, Einrichtungen'),
+ 'description' => _('Zuordnung zu Veranstaltungen, Einrichtungen, Fächern, Studiengängen'),
+ ],
+ 'date' => [
+ 'icon' => Icon::create('date'),
+ 'title' => _('Kalender/Termine'),
+ 'description' => _('Kalendereinträge und Termine'),
+ ],
+ 'message' => [
+ 'icon' => Icon::create('mail'),
+ 'title' => _('Nachrichten'),
+ 'description' => _('Nachrichten, Kommentare, Blubber, News'),
+ ],
+ 'content' => [
+ 'icon' => Icon::create('forum2'),
+ 'title' => _('Inhalte'),
+ 'description' => _('Dateien, Forum, Wiki, Literaturlisten'),
+ ],
+ 'quest' => [
+ 'icon' => Icon::create('vote'),
+ 'title' => _('Fragebögen, Aufgaben'),
+ 'description' => _('Fragebögen, Umfragen, Aufgaben'),
+ ],
+ 'plugins' => [
+ 'icon' => Icon::create('plugin'),
+ 'title' => _('Plugin-Inhalte'),
+ 'description' => _('Inhalte aus Plugins'),
+ ],
+ ];
+ }
+
+
+}