diff --git a/locales/de.yml b/locales/de.yml index 6ca20a6..e6a1ac3 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -108,3 +108,33 @@ delete_my_data: "Meine Daten löschen" delete_confirmation: "Sind Sie sicher, dass Sie alle Ihre persönlichen Daten löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden und Sie verlieren Ihren gesamten Spielfortschritt." data_deletion_success_title: "Daten erfolgreich gelöscht" data_deletion_success_body: "Alle Ihre persönlichen Daten wurden erfolgreich von unseren Servern entfernt. Ihr Sitzungs-Cookie wurde ebenfalls zerstört." + +# Camera demonstration page +cam_title: "Gesichtserkennung" +cam_title2: "@ Ars Electronica Festival 2025" +cam_subtitle: "Bildungsdemonstrationen allgegenwärtiger Überwachungstechnologie" +cam_description: "Erleben Sie hautnah, wie Gesichtserkennungssysteme Ihre biometrischen Daten in vernetzten Umgebungen verfolgen und verarbeiten." +cam_project_by: "Ein Forschungs- und Sensibilisierungsprojekt vom " +cam_institute: "Institut für Netzwerke und Sicherheit, Johannes Kepler Universität" +cam_mission_quote: "Das Ziel dieses Projekts ist es, die Öffentlichkeit über allgegenwärtige Gesichtserkennungstechnologien und deren Auswirkungen auf die Privatsphäre zu informieren, indem Festivalbesucher*innen persönlich erfahren können, wie solche Systeme funktionieren und welche Daten verarbeitet werden." +cam_mission_attribution: "Projekt Mission Statement" +cam_project_description: "Dieses zeitlich begrenzte Forschungs- und Sensibilisierungsprojekt konzentriert sich auf die Verarbeitung biometrischer Daten zu Forschungs-, Bewusstseins- und künstlerischen Zwecken und hilft Besucher*innen, die allgegenwärtige Natur der Gesichtserkennung in unserem täglichen Leben zu verstehen." +cam_how_it_works: "Wie es funktioniert" +cam_tech_setup_title: "Technische Ausstattung" +cam_tech_setup_p1: "Das System besteht aus einer Hauptkamera und bis zu 10 kleineren Sensorstationen, die an verschiedenen Festivalstandorten positioniert sind. Diese Kameras erfassen Bilder und nutzen Gesichtserkennung, um Besucher*innen zu identifizieren und zu verfolgen, während sie sich zwischen den Stationen bewegen." +cam_tech_setup_p2: "Das System verarbeitet biometrische Merkmale (gespeichert als \"Embeddings\"), Zeitstempel, Standortdaten und optional benutzerzugewiesene Pseudonyme, um zu demonstrieren, wie moderne Überwachungssysteme funktionieren." +cam_tech_setup_footer: "Mehrere Standorte im gesamten Festivalgelände" +cam_data_processing_title: "Datenverarbeitung" +cam_data_processing_p1: "Wichtig ist, dass die tatsächlichen Bilder nicht gespeichert werden - nur die extrahierten biometrischen Daten und zugehörigen Metadaten werden verarbeitet und vorübergehend auf einem sicheren Server an der JKU gespeichert." +cam_data_processing_footer: "Sicherer Server am JKU Institut für Netzwerke und Sicherheit" +cam_festival_details: "Festival-Details" +cam_when_where_title: "Wann & Wo" +cam_festival_info: "Ars Electronica Festival 2025" +cam_festival_dates: "3. bis 7. September 2025" +cam_festival_location: "Verschiedene Standorte im gesamten Festivalgelände" +cam_legal_compliance: "Rechtliche Konformität" +cam_legal_description: "Wir haben bei der österreichischen Datenschutzbehörde die Genehmigung für diesen experimentellen Aufbau beantragt und die Genehmigung wurde am 28. Juli 2025 erteilt." +cam_legal_request: "Genehmigter Antrag" +cam_legal_decision: "Behördenbescheid" +cam_legal_request_title: "Genehmigungsantrag ansehen" +cam_legal_decision_title: "Behördenbescheid ansehen" diff --git a/locales/en.yml b/locales/en.yml index 51820ee..e636db2 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -109,3 +109,31 @@ delete_my_data: "Delete My Data" delete_confirmation: "Are you sure you want to delete all your personal data? This action cannot be undone and you will lose all your game progress." data_deletion_success_title: "Data Successfully Deleted" data_deletion_success_body: "All your personal data has been successfully removed from our servers. Your session cookie has also been destroyed." + +# Camera demonstration page +cam_title: "Face Recognition" +cam_title2: "@ Ars Electronica Festival 2025" +cam_subtitle: "Educational Demonstration of Omnipresent Surveillance Technology" +cam_description: "Experience firsthand how facial recognition systems track and process your biometric data across interconnected environments." +cam_project_by: "A research and sensitization project by the " +cam_institute: "Institute for Networks and Security, Johannes Kepler University" +cam_mission_quote: "The goal of this project is to educate the public about omnipresent facial recognition technologies and their impact on privacy by allowing festival-goers to personally experience how such systems function and what data is processed." +cam_mission_attribution: "Project Mission Statement" +cam_project_description: "This time-limited research and sensitization project focuses on biometric data processing for research, awareness, and artistic purposes, helping visitors understand the pervasive nature of facial recognition in our daily lives." +cam_how_it_works: "How It Works" +cam_tech_setup_title: "Technology Setup" +cam_tech_setup_p1: "The system consists of a main camera and up to 10 smaller sensor-stations positioned at different festival locations. These cameras capture images and use facial recognition to identify and track visitors as they move between stations." +cam_tech_setup_p2: "The system processes biometric features (stored as \"Embeddings\"), timestamps, location data, and optionally, user-assigned pseudonyms to demonstrate how modern surveillance systems function." +cam_data_processing_title: "Data Processing" +cam_data_processing_p1: "Importantly, the actual images are not stored - only the extracted biometric data and associated metadata are processed and temporarily stored on a secure server at JKU." +cam_festival_details: "Festival Details" +cam_when_where_title: "When & Where" +cam_festival_info: "Ars Electronica Festival 2025" +cam_festival_dates: "September 3rd to 7th, 2025" +cam_festival_location: "Various locations throughout the festival grounds" +cam_legal_compliance: "Legal Compliance" +cam_legal_description: "We requested approval for this experimental setup from the Austrian Data Protection Authority and the request was approved on July 28, 2025." +cam_legal_request: "Approved Request (Antrag)" +cam_legal_decision: "Authority Decision (Bescheid)" +cam_legal_request_title: "View approval request" +cam_legal_decision_title: "View authority decision" diff --git a/src/index.rs b/src/index.rs index 9dde1ce..a3a6aa1 100644 --- a/src/index.rs +++ b/src/index.rs @@ -58,6 +58,73 @@ pub(super) async fn index(cookies: CookieJar, headers: HeaderMap) -> Markup { }) } +pub(super) async fn cam(cookies: CookieJar, headers: HeaderMap) -> Markup { + let lang = language(&cookies, &headers); + rust_i18n::set_locale(lang.to_locale()); + + let page = Page::new(lang); + page.content(html! { + hgroup { + h1 { (PreEscaped(t!("cam_title"))) } + p { (t!("cam_title2")) } + } + hgroup { + h2 { (t!("cam_subtitle")) } + p { (t!("cam_description")) } + } + p { + (t!("cam_project_by")) + span.highlight { (t!("cam_institute")) } + } + blockquote { + (t!("cam_mission_quote")) + footer { + cite { (t!("cam_mission_attribution")) } + } + } + p { (t!("cam_project_description")) } + + h2 { (t!("cam_how_it_works")) } + + div.grid.gap-lg { + article { + header { (t!("cam_tech_setup_title")) } + + p { (t!("cam_tech_setup_p1")) } + + p { (t!("cam_tech_setup_p2")) } + } + article { + header { (PreEscaped(t!("cam_data_processing_title"))) } + + p { (PreEscaped(t!("cam_data_processing_p1"))) } + } + } + + h2 { (t!("cam_festival_details")) } + + div.info-box { + h3 { (t!("cam_when_where_title")) } + p { + (t!("cam_festival_info")) br; + (t!("cam_festival_dates")) br; + (t!("cam_festival_location")) + } + } + + h2 { (t!("cam_legal_compliance")) } + + p { (t!("cam_legal_description")) } + + div.legal-docs { + a href="/static/dsb-request.pdf" target="_blank" title=(t!("cam_legal_request_title")) { (t!("cam_legal_request")) } + " | " + a href="/static/dsb-accept.pdf" target="_blank" title=(t!("cam_legal_decision_title")) { (t!("cam_legal_decision")) } + } +}) + +} + #[derive(Deserialize)] pub(super) struct PrivacyQuery { deleted: Option, diff --git a/src/main.rs b/src/main.rs index 24031f9..eefe154 100644 --- a/src/main.rs +++ b/src/main.rs @@ -309,7 +309,7 @@ impl Config { .take(15) .map(char::from) .collect(); - + Self { key: Key::generate().master().to_vec(), admin_password, @@ -323,19 +323,19 @@ fn load_or_create_config() -> Result<(Key, Config), Box> // Try to read existing config if Path::new(config_path).exists() { let content = fs::read_to_string(config_path)?; - + // Try to parse as complete config first if let Ok(config) = toml::from_str::(&content) { let key = Key::from(&config.key); return Ok((key, config)); } - + // If that fails, try to parse just the key and generate new admin password #[derive(Deserialize)] struct PartialConfig { key: Vec, } - + if let Ok(partial_config) = toml::from_str::(&content) { use rand::{distributions::Alphanumeric, thread_rng, Rng}; let admin_password: String = thread_rng() @@ -343,16 +343,16 @@ fn load_or_create_config() -> Result<(Key, Config), Box> .take(15) .map(char::from) .collect(); - + let config = Config { key: partial_config.key, admin_password, }; - + // Write the updated config back let toml_string = toml::to_string(&config)?; fs::write(config_path, toml_string)?; - + let key = Key::from(&config.key); return Ok((key, config)); } @@ -409,10 +409,10 @@ async fn main() { .unwrap(); let (key, config) = load_or_create_config().unwrap(); - + // Print admin password for convenience tracing::info!("Admin password: {}", config.admin_password); - + let state = AppState { backend: Arc::new(Backend::Sqlite(db)), key, @@ -422,6 +422,7 @@ async fn main() { let app = Router::new() .route("/", get(index::index)) .route("/privacy", get(index::data)) + .route("/cam", get(index::cam)) .route("/delete-data", post(delete_personal_data)) .nest_service("/static", ServeDir::new("./static/serve")) .merge(game::routes()) diff --git a/static/serve/dsb-accept.pdf b/static/serve/dsb-accept.pdf new file mode 100644 index 0000000..772f4c5 Binary files /dev/null and b/static/serve/dsb-accept.pdf differ diff --git a/static/serve/dsb-request.pdf b/static/serve/dsb-request.pdf new file mode 100644 index 0000000..0605090 Binary files /dev/null and b/static/serve/dsb-request.pdf differ