Giter VIP home page Giter VIP logo

dsgvo's Introduction

Inhaltsübersicht

Screenshot

Einleitung

Screenshot

Über das Addon

Dieses Addon bietet Unterstützung bei der DSGVO-konformen Umsetzung von ein oder mehreren REDAXO-Websites.

Das Addon kann eine anwaltliche Beratung und sorgfältige Prüfung des Einzelfalls nicht ersetzen. Für die DSGVO-konforme Umsetzung ist die ganzheitliche Betrachtung der auf einer Website anfallenden Daten und deren Nutzung unerlässlich.

zurück zur Übersicht

Features

Die Client-Funktion ist für die Darstellung und die ggf. automatische Aktualisierung von Datenschutz-Textbausteinen und der Verwaltung von Tracking-Codes gedacht.

  • Verwaltung von Textbausteinen für die Datenschutz-Erklärung inkl. Quellen-Nennung
  • Umfangreiches Setup, das einen bei einem Teil der DSGVO geforderten Auflagen unterstützt und Teile der REDAXO-Seite prüft
  • Vorlage für die Ausgabe der Datenschutz-Erklärung, welche ein Opt-Out-Cookie des Nutzers setzen können.
  • Vorlage für die Ausgabe der Cookie-Einverständnis-Meldung
  • Vorlage für die Ausgabe von Tracking-Codes und externen Inhalten, welche ein Opt-Out-Cookie des Nutzers berücksichtigen.
  • Cronjob zum automatischen Abruf von Texten (experimentell)
  • Cronjob zum automatischen Löschen alter Datensätze (experimentell)
  • Cronjob zum Löschen alter Backups (in Arbeit)
  • Cronjob zum Löschen alter PHP-Mailer-Logs (in Arbeit)

zurück zur Übersicht

Bug-Meldungen, Hilfe und Links

zurück zur Übersicht

Installation

Voraussetzung für die aktuelle Version des DSGVO-Addons: REDAXO 5.3, Cronjob-Addon, MarkItUp-Addon Beim Installieren und Aktivieren des Addons werden die Tabellen für den Client und ggf. den Server angelegt. Nach erfolgreicher Installation gibt es im Backend unter AddOns einen Eintrag "DSGVO".

zurück zur Übersicht

Setup

Übersicht

Unter dem Reiter Setup wird in mehreren Schritten die aktuelle Installation sowie deren Konfiguration überprüft. Die DSGVO-konforme Umsetzung erfordert ggf. ein händisches eingreifen.

  • Übersicht
  • Datenschutz-Erklärung einbinden
  • SQL-Backups
  • PHP-Mailer Logs
  • Kontaktformular
  • automatisiertes Löschen
  • Externe Dienste

zurück zur Übersicht

Datenschutz-Erklärung

Übersicht

Unter dem Reiter Datenschutz-Erklärung werden Text-Bausteine der Datenschutz-Erklärung sowie deren Codes verwaltet. Diese können

  • manuell hinzugefügt werden, oder
  • via Cronjob seitens des Servers am Client aktualisiert werden (in Arbeit)

Die einzelnen Felder sind:

  • Website (Domain aus dem System oder Domain des YRewrite-Projekts, z.B. domain.de)
  • Sprache (ISO-Sprachcode, z.B. de)
  • Kategorie (in Arbeit)
  • Schlüssel (ein eindeutiger Schlüssel für den Dienst, der ggf. auch im Opt-Out als Cookie hinterlegt wird, z.B. google_analytics oder facebook_pixel)
  • Überschrift
  • Status (anzeigen / verbergen)
  • Datenschutz-Text
  • Quelle (ggf. notwendig für Nutzungsrechte externer Dienste, bspw. dem Datenschutz-Generator von eRecht24)
  • Link zur Quelle (URL zur Quelle)

zurück zur Übersicht

Einrichtung der Datenschutz-Erklärung (Modul)

Dem Addon liegt ein generisches Modul bei, das automatisch in Abhängigkeit der gewählten REDAXO-Sprache und der gewählten Domain einen Code erzeugt. Es erzeugt ebenfalls bei den passenden Diensten einen Opt-Out-Code.

Moduleingabe (benötigt aktuell MForm)

<?php // dsgvo_module_input - Diese Zeile nicht löschen 

if(rex_addon::get('mform')->isAvailable()) {
    $mform = new MForm();

    if(rex_addon::get('yrewrite')->isAvailable()) {
        $domains = [];
        foreach(rex_yrewrite::getDomains(true) as $domain => $object) {
            $domains[$domain] = $domain;
        } 

        $mform->addSelectField("1", $domains, array('label'=>'Domain')); // use string for x.0 json values
    } else {
        $mform->addSelectField("1", [rex::getServer()], array('label'=>'Domain')); // use string for x.0 json values
    }

    $langs = [];

    foreach(rex_clang::getAll(true) as $lang) {
        $langs[$lang->getCode()] = $lang->getCode();
    }
    $mform->addSelectField("2", $langs, array('label'=>'Sprachen')); // use string for x.0 json values
    echo $mform->show();
} else {
    // Input-Felder ohne MForm. TODO   
}
?>

Modulausgabe

<?php // dsgvo_module_output - Diese Zeile nicht löschen ?>
<section class="modul modul-privacy">
<?php
    $lang = rex_clang::getCurrent()->getCode();
    $dsgvo_pool = array_filter(rex_sql::factory()->setDebug(0)->getArray('SELECT * FROM rex_dsgvo_client WHERE status = 1 AND domain = :domain AND lang = :lang ORDER by prio',[':domain'=> "REX_VALUE[1]", ':lang'=> "REX_VALUE[2]"]));

foreach($dsgvo_pool AS $key => $dsgvo_item) {
    $dsgvo_pool[$key]['text'] = markitup::parseOutput ('textile', $dsgvo_item['text']);
}

    $output = new rex_fragment();
    // ggf. Sprache anpassen
    $output->setVar("dsgvo_pool", $dsgvo_pool);
    $output->setVar("lang", $lang);
    $output->setVar("domain", $domain);
    $output->setVar("consent", "Einwilligen");
    $output->setVar("revoke", "Widerrufen");
    $output->setVar("source", "Quelle:");
    echo $output->parse('dsgvo-page.fragment.inc.php');
?>
</section>

Achtung: Um die Funktionalität zu überprüfen, bitte auf der Live-Seite in den Entwickler-Einstellungen des Browsers das korrekte Setzen des Cookies überprüfen. Der Cookie lautet: dsgvo_[schlüssel] = -1 - der entsprechende Dienst darf dann nicht im Tracking-Code auftauchen.

zurück zur Übersicht

Einrichtung der Tracking-Codes

Dem Addon liegt eine generische Umsetzung bei, die die hinterlegten Tracking-Codes in Abhängigkeit des vom Nutzer gewählten Opt-Outs ausgibt oder die Ausgabe verhindert. Diese Code-Zeilen zwischen den <head>-Tag schreiben:

<!-- DSGVO -->
<script language="javascript" type="text/javascript" src="/assets/js/cookie.js"></script>
<?php
	$lang = rex_clang::getCurrent()->getCode();
	$dsgvo_pool = rex_sql::factory()->setDebug(0)->getArray('SELECT * FROM rex_dsgvo_client WHERE status = 1 AND lang = :lang ORDER by prio',[':lang'=>$lang]);

	$output = new rex_fragment();
	$output->setVar("dsgvo_pool", $dsgvo_pool);
	$output->setVar("lang", $lang);
	$output->setVar("domain", $domain);

	echo html_entity_decode($output->parse('dsgvo-tracking.fragment.inc.php'), ENT_HTML5 | ENT_QUOTES);
?>

Achtung: Um die Funktionalität zu überprüfen, bitte auf der Live-Seite in den Entwickler-Einstellungen des Browsers das korrekte Setzen des Cookies überprüfen. Der Cookie lautet: dsgvo_[schlüssel] = -1 - der entsprechende Dienst darf dann nicht im Tracking-Code auftauchen.

zurück zur Übersicht

Einrichtung des Cookie-Einverständnis-Banners

Dem Addon liegt eine generischer Code bei, der ein minimalistisches Cookie-Einverständnis-Banner ("Cookie Consent") erzeugt. Das CSS kann im Reiter Cookie-Einverständnis angepasst werden.

$output = new rex_fragment();

// ggf. Sprache anpassen
$output->setVar("info", "Um unsere Webseite für Sie optimal zu gestalten und fortlaufend verbessern zu können, verwenden wir Cookies. Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu. Weitere Informationen zu Cookies erhalten Sie in unserer");
$output->setVar("learn_more", "Datenschutzerklärung");
$output->setVar("dismiss", "OK");
$output->setVar("url", "/datenschutz/");

echo $output->parse('dsgvo-consent-custom.fragment.inc.php');

Achtung: Der Banner darf wichtige Elemente wie bspw. den Link zum Impressum, zur Datenschutz-Seite oder Bildquellen nicht verdecken! Für die korrekte Einbindung ist der Entwickler bzw. der Betreiber verantwortlich.

zurück zur Übersicht

Server-PlugIn

Features

Die Server-Funktion ist für das zentrale Verwalten und Bereitstellen der Datenschutz-Erklärung und Tracking-Codes für ein oder mehrere Projekte gedacht.

  • Verwaltung von Textbausteinen für die Datenschutz-Erklärung inkl. Quellen-Nennung für mehrere Projekte
  • Standalone-Client zum Einfügen in ältere Projekte (REDAXO 4, andere CMS)
  • Projekte-Verwaltung für die unterschiedliche Zusammenstellung der Texte
  • Muster-Verwaltung unter der Domain "default"
  • Cronjob zum manuellen Anstoßen der Clients
  • Logfiles zur Nachverfolgung, welche Projekte wann Texte abgerufen haben (in Arbeit)

zurück zur Übersicht

Server

Unter dem Reiter Server werden Domains verwaltet.

Die einzelnen Felder sind:

  • Website (Domain aus dem System oder Domain des YRewrite-Projekts, z.B. domain.de)
  • Sprache (ISO-Sprachcode, z.B. de)

Außerdem werden in Logs die Verbindungen festgehalten.

Texteverwaltung

Mit einem Klick auf Texte verwalten werden Text-Bausteine der Datenschutz-Erklärung sowie deren Codes in Abhängigkeit eines Projekts verwaltet. Diese können via Cronjob seitens des Servers am Client aktualisiert werden. (in Arbeit)

Die einzelnen Felder sind:

  • Website (Domain aus dem System oder Domain des YRewrite-Projekts, z.B. domain.de)
  • Sprache (ISO-Sprachcode, z.B. de)
  • Schlüssel (ein eindeutiger Schlüssel für den Dienst, der ggf. auch im Opt-Out als Cookie hinterlegt wird, z.B. google_analytics oder facebook_pixel)
  • Überschrift
  • Status (anzeigen / verbergen)
  • Datenschutz-Text
  • Code
  • Quelle (ggf. notwendig für Nutzungsrechte externer Dienste, bspw. dem Datenschutz-Generator von E-Recht 24)
  • Link zur Quelle (URL zur Quelle)

zurück zur Übersicht

Sync-Cronjob

Der Sync-Cronjob kann sich mit externen REDAXO-Installationen (und Standalone-Versionen) verbinden und deren Datenschutz-Texte aktualisieren. Der Abruf der Texte vom Client wird über einen API-Call umgesetzt. (in Arbeit)

zurück zur Übersicht

Standalone-Version

Dem DSGVO-Server-Plugin liegt ein Standalone-Client bei, um beim Server verwaltete Texte auch am Client zu aktualisieren. Es befindet sich unter /redaxo/src/addons/dsgvo/plugins/server/standalone

Weiterführende Informationen und Links zur DSGVO

Auftragsverarbeitungs-Verträge

(AV-Vertrag, vormals Auftragsdatenverarbeitungs-Vertrag ADV-Vertrag) / Data-processing-agreements (DPA-contract)

Liste internationaler Datenverarbeiter und ihrer AVV/DPAs www.tollwerk.github.io/data-processing-agreements/ www.github.com/tollwerk/data-processing-agreements

zurück zur Übersicht

dsgvo's People

Contributors

alxndr-w avatar christophboecker avatar crydotsnake avatar helpy avatar interweave-media avatar joachimdoerr avatar madiko avatar nandes2062 avatar schuer avatar ynamite avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dsgvo's Issues

generische Zweiklick-Lösung

Ich stelle mir vor, dass zukünftig eingebettete Inhalte (Twitter, Google Maps, Youtube, etc.) über eine Zweiklicklösung mit einem Hinweis zur Datenschutz-Seite nachgeladen werden können. Diese sollte vom dsgvo-Addon bereitgestellt werden und ebenfalls mehrsprachig und mehrdomainfähig sein, da hier je nach Sprache / Domain auf unterschiedliche Artikel verwiesen werden muss.

Fehler bei der Installation vom Plugin "Server"

PlugIn server konnte aus folgendem Grund nicht installiert werden:SQL error: Error while executing statement "INSERT IGNORE INTO `rex_dsgvo_project` (`domain`) VALUES ('default')"! SQLSTATE[42S02]: Base table or view not found: 1146 Table 'utebelser.rex_dsgvo_project' doesn't exist

Cookie-Einverständnis-Banner vervollständigen

  • In der Basis-Funktionalität sollte der Banner ein CSS mitliefern.
  • Link und Text sollen verändert werden können (kompatibel zu Sprog, YRewrite Multidomains).
  • Das Fragment sollte im data-Ordner überschrieben werden können.
  • Eine Prüfung im Setup, ob der Code zumindest technisch im Frontend ausgegeben wird, sollte stattfinden.

Setup: Codecheck finalisieren

  • Auf Keywords wie facebook, analytics, tracking in Templates und Modulen oder in der finalen Ausgabe der Startseite reagieren
  • Meldung in die Logs aufnehmen und ggf. an Server melden

Server: API finalisieren

Funktionsweise:

  • ohne Domain: Einfach nur Texte abrufen
  • mit Domain: API-Key Zugeschnittene Codes und Reihenfolge berücksichtigen.

Verzögerung des gesamten Seitenaufbaus

Wenn bei mir die aktuelle Entwicklungs-Version 0.2.1 installiert ist, verzögern sich alle HTTP-Requests um ca. 1 - 1.5 Sekunden. Zum Beispiel benötigt ein beliebiges Media-Manager-Bild bei aktiviertem DSGVO-Addon ca. 1.7 Sekunden zum Laden (davon 1.55 Warten) und bei deaktiviertem Addon nur 0.2 Sekunden (davon 0.07s Warten). Ähnliche Verzögerung auch im Backend. Da ist irgendwas resourcen-fressend eingebunden...

PHP Cookie consent mit Logger

Auf Nachfrage von Thomas bei Slack zeig ich hier mal unseren bisherigen Ansatz.
Ihr könnt gerne was rauspicken, umbenennen, ändern oder einfach das ganze komplett ignorieren.
Ich habe davon auch eine REX4 Version für php 5.3.

In Aktion könnt ihr das Ganze hier sehen:
https://www.phillip-moeller.de/cookieconsent/

Ideen

  • Die Texte samt Übersetzungen sollten in ein lang Datei ausgelagert werden
  • Opt-out Funktion sollte integriert werden ( Recht simpel durch Änderung des Initialwertes von rex_session('mc_use_cookies','bool',0) von 0 auf 1 ). Vllt. sind noch paar kleinere Anpassungen nötig

Nachfolgend versuch ich das Ganze mal zu erklären, hab noch nie irgendwo ein Issue geschrieben geschweige denn ein Skript vorgestellt also entschuldigt bitte etwaige Formfehler. Die Klassen sind nur teilweise von mir kommentiert ich Versuch den Code immer "selbsterklärend" zu schreiben aber falls Fragen auftreten stehe ich zur Verfügung!

McCookieConsent
Die Klasse arbeitet SESSION abhängig. Das heißt bei jeder neuen SESSION wird erneut nach der Zustimmung gefragt. Hintergrund dazu ist die Überlegung, das an einem PC mehrere User den gleichen Browser nutzen können und es am Ende heißt "Ja meine Frau hat vllt. zugestimmt aber ich doch nicht".

McVisitorLogger
Die Klasse kann für einen Wunschpfad einen Ordner erstellen. In diesem Ordner wird eine .htaccess gesetzt und für jeden Aufruf von $McVisitorLogger->writeToDirectory($directory) in eine Textdatei die IP samt Zeitstempel geschrieben. Um Proxies auch zu Loggen werden folgende Werte genutzt:

  • REMOTE_ADDR
  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR

Die Textdatei ist nach dem aktuellen Datum benannt. Am nächsten Tag wird eine neue erstellt.
Mit dem Logger können beliebiege Formulare geloggt werden und beliebige eigene Werte z.B. die Daten des Formulars welches den Logger auslöst oder andere Daten die man beziehen kann z.B. lang-code, browser etc.

Nutzung des Skriptes:
Das nachfolgende Snippet kann z.B. in der boot.php des Projects- / oder Themeaddons gesetzt, oder einfach in einem entsprechenden Template.

<?php

    $McCookieConsent = new McCookieConsent;
    $McCookieConsent->setProperty("privacy_page_id",Redaxo Artikel ID zur Datenschutzseite);
    
    //ermöglicht eigene Daten mit zu loggen z.b. $_SERVER['HTTP_USER_AGENT']
    $McCookieConsent->setLogData("Key / Titel im log", "WERT");
    // -> Beispiel:
    $McCookieConsent->setLogData("HTTP_USER_AGENT",$_SERVER['HTTP_USER_AGENT']);
    
    //ermöglicht eigene Texte und Übersetzungen hinzuzufügen
    // de / en sind bereits definiert können aber ebenso überschrieben werden
    $McCookieConsent->setText("de",
        array(
            "message" => "Für eine uneingeschränkte Nutzung dieser Webseite werden Cookies benötigt. Einige dieser Cookies erfordern ausdrücklich Ihre Zustimmung. Bitte stimmen Sie der Verwendung zu, um alle Funktionen der Webseite nutzen zu können. Detaillierte Informationen finden Sie in unserer Datenschutzerklärung. An dieser Stelle können Sie diese Abfrage für die Speicherung von Cookies wieder reaktivieren.",
            "dismiss_text" => "Ablehnen",
            "allow_text" => "Akzeptieren",
            "privacy_link_text" => "Zur Datenschutzerklärung"
        )
    );
    
    // initialisiert das Objekt mit den Einstellungen
    // -> danach können die Funktion zur Ausgabe etc. genutzt werden
    $McCookieConsent->initialize();

?>

Ausgabe der verschiedenen Elemente:

<?php
    // Gibt einen Button aus der je nach aktuellem Status die Cookies aktiviert oder deaktiviert
    echo $McCookieConsent->getCookiesUsageToggle("Cookies deaktivieren","Cookies aktivieren");
    
    // Gibt einen Button aus der das erneute Öffnen des Cookie Fensters ermöglicht
    echo $McCookieConsent->getRevokeButton("revoke");

    // Gibt das Cookie Fenster aus (Nur wenn in der aktuellen Session weder abgelehnt noch zugestimmt wurde)
    echo $McCookieConsent->getCookieUsageWindow();

    // Gibt die bei Zustimmung die relevanten Skripte aus
    echo $McCookieConsent->returnIfAccepted('<script>/* CONSENT RELEVANT */</script>');
    /* die Skripte können z.B. aus dem "Globale Einstellungen" AddOn direkt in der obigen Funktion ausgegeben werden */

    // Gibt diverse Informationen als JS console.log aus
    $McCookieConsent->debug();

?>

Zusätzlich muss die cookie-consent.css eingebunden werden:

/* window */
#mc-cookie-consent-window{
    font-family: Verdana,helvetica, arial, sans-serif;
    color:#555;
    font-size: 1em;
    position: fixed;
    bottom:1em;
    right:1em;
    z-index:9999999999;
    width:450px;
    max-height:100vh;
    overflow-y:auto ;
    padding:2em;
    background:#ffffff;
    text-align: justify;
    -webkit-box-shadow: 0 0 3px rgba(0,0,0,0.3);
    -moz-box-shadow: 0 0 3px rgba(0,0,0,0.3);
    box-shadow: 0 0 3px rgba(0,0,0,0.3);
    animation-delay: 1s;
}

#mc-cookie-consent-window:after{
    content: "";
    clear: both;
}

#mc-cookie-consent-window p{font-size:0.7em;line-height: 1.8em;margin-bottom:2em;color:inherit;}
#mc-cookie-consent-window a{color:#f05f5d;white-space:nowrap;text-decoration: underline;}

#mc-cookie-consent-window button{
    cursor:pointer;
    font-family: Verdana,helvetica, arial, sans-serif;
    font-size:0.8em;
    padding:0.75em 0;
    display: block;
    float:left;
    width:50%;
    text-align: center;
    background:none;
    font-weight: bold;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    -webkit-border-radius: 0px;
    -moz-border-radius: 0px;
    border-radius: 0px;
    -webkit-transition: 0.3s;
    -moz-transition: 0.3s;
    -ms-transition: 0.3s;
    -o-transition: 0.3s;
    transition: 0.3s;
}

#mc-cookie-consent-window button.dismiss{border:2px solid transparent;color:inherit;}
#mc-cookie-consent-window button.allow{border:2px solid #f05f5d;color:#f05f5d;}

/* mediaquerries */
@media(max-width:768px){
    #mc-cookie-consent-window{
        right:0;
        bottom:0;
        left:0;
        width: 100vw;
    }
}

/* animation */
.animated.bounceIn {
    -webkit-animation-duration:0.75s;
    animation-duration:0.75s
}

@-webkit-keyframes bounceIn {
    0%,20%,40%,60%,80%,to {
        -webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);
        animation-timing-function:cubic-bezier(.215,.61,.355,1)
    }
    0% {
        opacity:0;
        -webkit-transform:scale3d(.3,.3,.3);
        transform:scale3d(.3,.3,.3)
    }
    20% {
        -webkit-transform:scale3d(1.1,1.1,1.1);
        transform:scale3d(1.1,1.1,1.1)
    }
    40% {
        -webkit-transform:scale3d(.9,.9,.9);
        transform:scale3d(.9,.9,.9)
    }
    60% {
        opacity:1;
        -webkit-transform:scale3d(1.03,1.03,1.03);
        transform:scale3d(1.03,1.03,1.03)
    }
    80% {
        -webkit-transform:scale3d(.97,.97,.97);
        transform:scale3d(.97,.97,.97)
    }
    to {
        opacity:1;
        -webkit-transform:scaleX(1);
        transform:scaleX(1)
    }
}
@keyframes bounceIn {
    0%,20%,40%,60%,80%,to {
        -webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);
        animation-timing-function:cubic-bezier(.215,.61,.355,1)
    }
    0% {
        opacity:0;
        -webkit-transform:scale3d(.3,.3,.3);
        transform:scale3d(.3,.3,.3)
    }
    20% {
        -webkit-transform:scale3d(1.1,1.1,1.1);
        transform:scale3d(1.1,1.1,1.1)
    }
    40% {
        -webkit-transform:scale3d(.9,.9,.9);
        transform:scale3d(.9,.9,.9)
    }
    60% {
        opacity:1;
        -webkit-transform:scale3d(1.03,1.03,1.03);
        transform:scale3d(1.03,1.03,1.03)
    }
    80% {
        -webkit-transform:scale3d(.97,.97,.97);
        transform:scale3d(.97,.97,.97)
    }
    to {
        opacity:1;
        -webkit-transform:scaleX(1);
        transform:scaleX(1)
    }
}
.bounceIn {
    -webkit-animation-name:bounceIn;
    animation-name:bounceIn
}
.animated {
    -webkit-animation-duration:1s;
    animation-duration:1s;
    -webkit-animation-fill-mode:both;
    animation-fill-mode:both
}

Die McCookieConsent.php in den Autoload packen:

<?php

class McCookieConsent
{

    public function __construct()
    {
	    
	    if(session_status() == PHP_SESSION_NONE){
		    session_start();
		}
	    
	    $this->server = rex_server('SERVER_NAME','string','');
	    $this->mc_use_cookies_hash = md5('mc_use_cookies'.$this->server);
	    $this->mc_show_cookie_window_hash = md5('mc_show_cookie_window'.$this->server);
		
		//post action
		$this->post_action = NULL;
		
	    //privacy page
        $this->privacy_page_id = Null;
	    	    
        //array with changeable properties
        $this->public_properties_array = ["privacy_page_id","post_action"];

		//default text
		$this->text_array = array(		
			"de" => array(		
				"message" => "Für eine uneingeschränkte Nutzung dieser Webseite werden Cookies benötigt. Einige dieser Cookies erfordern ausdrücklich Ihre Zustimmung. Bitte stimmen Sie der Verwendung zu, um alle Funktionen der Webseite nutzen zu können. Detaillierte Informationen finden Sie in unserer Datenschutzerklärung. An dieser Stelle können Sie diese Abfrage für die Speicherung von Cookies wieder reaktivieren.",
				"dismiss_text" => "Ablehnen",
				"allow_text" => "Akzeptieren",
				"privacy_link_text" => "Zur Datenschutzerklärung"		
			),
			
			"en" => array(
				"message" => "For an unrestricted use of this website, cookies are required. Some of these cookies require your full consent. Please agree to the use of cookies in order to use all features of the website. You will get detailed information about the use of cookies on this website by clicking on “privacy statement”. At this point, you can reactivate your consent to the use of cookies.",
				"dismiss_text" => "dismiss",
				"allow_text" => "accept",
				"privacy_link_text" => "Privacy statement"	
			)
		);

    }
        
    public function initialize()
    {
		//if lang code isn't in text_array use "en" for $lang_code
		$current_lang_code = rex_clang::getCurrent()->getCode();
		$lang_code = (array_key_exists($current_lang_code, $this->text_array)) ? $current_lang_code : "en";

		//set all text porperties for $lang_code
        $this->message = $this->text_array[$lang_code]["message"];
        $this->dismiss_text = $this->text_array[$lang_code]["dismiss_text"];
        $this->allow_text = $this->text_array[$lang_code]["allow_text"];
        $this->privacy_link_text = $this->text_array[$lang_code]["privacy_link_text"];

        //dismissing or accepting cookies
        if(rex_post('mc_post_cookie_consent','string',NULL) != NULL) {

            $this->post_cookie_consent = rex_post('mc_post_cookie_consent','bool',NULL);

            $this->McVisitorLogger = new McVisitorLogger;
            $this->log_data_array["HTTP_HOST"] = $this->server;
            $this->log_data_array["Cookie Consent"] = ($this->post_cookie_consent === true) ? "accept" : "dismissed";
            $this->McVisitorLogger->setVisitorLogData($this->log_data_array);
            $this->McVisitorLogger->writeToDirectory("cookie_consent_log");

			//unsetting session vars
            rex_unset_session($this->mc_use_cookies_hash);
            rex_unset_session($this->mc_show_cookie_window_hash);
            
            //setting session vars
            rex_set_session($this->mc_use_cookies_hash, $this->post_cookie_consent); //cookie usage
            rex_set_session($this->mc_show_cookie_window_hash,0); //hide window

        }
       
        //revoking window
        if(rex_post('mc_post_cookie_revoke','string',NULL) != NULL) {

            rex_set_session($this->mc_show_cookie_window_hash,1);

        }

        //get needed session vars
        $this->use_cookies = rex_session($this->mc_use_cookies_hash,'bool',0);
        $this->show_window = rex_session($this->mc_show_cookie_window_hash,'bool',1);

    }
    
    private function setPostAction()
    {
	    
    }

    public function setProperty($name,$value)
    {
        //change only allowed public properties
        if(in_array($name,$this->public_properties_array)) {
            $this->$name = $value;
        }
    }
    
    public function setText($lang_code,$array)
    {
	    $this->text_array[$lang_code] = $array;
    }
    
    public function setLogData($key,$value)
    {
	    $this->log_data_array[$key] = $value;
    }

    public function getCookieUsageWindow()
    {

        if($this->show_window) {

			$post_action = ($this->post_action) ? $this->post_action : rex_getUrl("REX_ARTICLE_ID");
			$privacy_link = (is_numeric($this->privacy_page_id)) ? rex_getUrl($this->privacy_page_id) : $this->privacy_page_id ;
						
            $window =
                '<div id="mc-cookie-consent-window" class="animated bounceIn">
                    <form method="POST" action="'.$post_action.'" id="mc-cookie-consent-window-form">
                        <p>' . $this->message . ' <a href="'.$privacy_link.'">' . $this->privacy_link_text . '</a></p>
                        <button type="submit" name="mc_post_cookie_consent" value="0" tabindex="0" class="dismiss">' . $this->dismiss_text . '</button>
                        <button type="submit" name="mc_post_cookie_consent" value="1" tabindex="0" class="allow">' . $this->allow_text . '</button>
                    </form>
                </div>';

        } else {

            $window = NULL;

        }

        return $window;

    }

    public function returnIfAccepted($scripts)
    {
        if($this->use_cookies == 1){
            return "<!-- scripts enabled --> \n $scripts";
        } else {
	        return "<!-- scripts disabled -->";
        }
    }

    public function getCookiesUsageToggle($dismiss_text,$allow_text)
    {
	    $post_action = ($this->post_action) ? $this->post_action : rex_getUrl("REX_ARTICLE_ID");
        $button_dismiss = '<button type="submit" name="mc_post_cookie_consent" value="0" class="dismiss">'.$dismiss_text.'</button>';
        $button_allow = '<button type="submit" name="mc_post_cookie_consent" value="1" class="allow">'.$allow_text.'</button>';

        $toggle = '<form method="POST" action="'.$post_action.'">';
        $toggle .= ($this->use_cookies == 1) ? $button_dismiss : $button_allow;
        $toggle .= '</form>';

        return $toggle;
    }
    
    public function getRevokeButton($button_text)
    {
	    $post_action = ($this->post_action) ? $this->post_action : rex_getUrl("REX_ARTICLE_ID");    
	    $revoke = '<form method="POST" action="'.$post_action.'"><button type="submit" name="mc_post_cookie_revoke" value="1" class="revoke">'.$button_text.'</button></form>';
	    
	    return $revoke;
    }
    
    public function getLogDataString()
    {
	    if(rex_post('mc_post_cookie_consent','string',NULL) != NULL){
		    return $this->McVisitorLogger->getLogDataString();
	    } else {
		    return NULL;
	    }
	    
    }
    
    public function getCookieStatus()
    {
	    return $this->use_cookies;
    }
    
    public function debug()
    {
        echo 
        '<script>
        	console.log("#### McCookieConsent Debug ####");
        	console.log("Server: '.$this->server.'");
        	console.log("Cookie usage state: '.$this->use_cookies.' | Hash: '.$this->mc_use_cookies_hash.'");
        	console.log("Show window state: '.$this->show_window.' | Hash: '.$this->mc_show_cookie_window_hash.'");
        	console.log("SESSION ID: '.session_id().'");
        </script>';

    }

}

Die McVisitorLogger.php in den Autoload packen:

<?php

class McVisitorLogger
{

    public function __construct()
    {
        $this->directory = NULL;
    }

    public function writeToDirectory($directory)
    {
        //create directory with .htaccess if necessary
        if($directory && !rex_dir::isWritable($directory)){
            rex_dir::create($directory);
            $htaccess = fopen($directory."/.htaccess", "x");
            fwrite($htaccess, "deny from all");
            fclose($htaccess);
        }
        $log_file_name = "log_".date("d_m_Y",time());
        $log_file = fopen($directory."/$log_file_name.txt", "a");
        fwrite($log_file, $this->log_data_string.PHP_EOL);
        fclose($log_file);
    }

    public function setVisitorLogData($custom_data_array = NULL)
    {
        //custom
        if(is_array($custom_data_array)){
            foreach($custom_data_array as $key => $data){
                $custom_data_string_array[] = "$key: $data";
            }
            $custom_data_string = implode(" | ", $custom_data_string_array);
        } else {
            $custom_data_string = NULL;
        }

        //ip
        $remote_addr = (isset($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP)) ? "REMOTE_ADDR: ".$_SERVER['REMOTE_ADDR'] : "REMOTE_ADDR: invalid or undefined";
        $client_ip = (isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) ? "HTTP_CLIENT_IP: ".$_SERVER['HTTP_CLIENT_IP'] : "HTTP_CLIENT_IP: invalid or undefined";
        $x_forwarded_for = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP)) ? "HTTP_X_FORWARDED_FOR: ".$_SERVER['HTTP_X_FORWARDED_FOR'] : "HTTP_X_FORWARDED_FOR: invalid or undefined";

        //timestamp
        $time = time();
        $timestamp = date("d.m.Y",$time).' - '.date("H:i",$time).' Uhr';

        $this->log_data_array = array_filter([$remote_addr,$client_ip,$x_forwarded_for,$custom_data_string,$timestamp]);
        $this->log_data_string = implode(" | ", $this->log_data_array);

    }

    public function getLogDataString()
    {
        return $this->log_data_string;
    }

}

Link zu ADVs / DPAs ergänzen (data-processing-agreements)

Hallo Alex,

heute wurde ich von Joschi Kuphal von Tollwerk angesprochen. Sie arbeiten gerade an einer Übersicht mit diversen DPAs. Lass uns das auch verlinken. Ich übernehme das, sobald ich von Joschi das "Go" habe (sie sind auch noch Work-in-Progress).

Hier schon mal der Link für Dich:
https://github.com/tollwerk/data-processing-agreements

Würdest Du dieses Issue bitte mir zuordnen? Ich habe noch nicht so ganz verstanden, wie ich das selbst machen kann. Danke.

Viele Grüße,
Franziska

Server: Logs

  • in Projekte-Übersicht bereits zeigen
  • beim Bearbeiten eines Projekts die Texte-Übersicht-Seite mit anzeigen
  • Logs überhaupt anlegen
  • Datumsformat korrekt ausgeben
  • angeforderte Parameter loggen

Diverse Notices

Notice: Undefined variable: tracking_content in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.overview.php on line 33
Notice: Undefined variable: consent_content in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.overview.php on line 58
Notice: Undefined variable: listName in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.backup.php on line 16
Notice: Undefined variable: debug in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.backup.php on line 16
Notice: Undefined variable: files in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.phpmailer.php on line 56
Notice: Undefined variable: checkbox_pipe_title in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.contactform.php on line 16
Notice: Undefined variable: checkbox_pipe in /Users/joachimdoerr/Workingspace/utebelser/app/redaxo/src/addons/dsgvo/pages/dsgvo.setup.contactform.php on line 18

Client / Server: Änderungen pushen können, nicht pullen

Mein gewählter Ansatz hat einen Design-Fehler, nämlich, dass momentan sowohl die Standalone-Variante, als auch die R5-Variante des Clients selbst dafür verantwortlich ist, die Daten zu ziehen. z.B. via Cronjob.

Ziel wäre es, dass der Server jede Änderungen proaktiv mitteilt.

@joachimdoerr vlt. hast du da einen cleveren Ansatz.

Server: Log vom Client senden an Server senden

Ein Client-API-Aufruf

  • muss in der Lage sein, angestoßen zu werden
  • soll an den Server einen Wert über den Erfolg zurückgeben
  • Die SETUP-Prüfungen durchlaufen und rückmelden, ob aktuell Prüfungen fehlschlagen.
  • Das ganze soll auch als Standalone-Version ohne REDAXO funktionieren

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.