Compare commits
3 Commits
0327892f02
...
de01d2507f
Author | SHA1 | Date | |
---|---|---|---|
de01d2507f | |||
2583544779 | |||
ff72f7c9fa |
@@ -29,7 +29,7 @@ location_linz: "Wo: überall in Linz"
|
|||||||
game_title: "Wer findet die meisten Kameras?"
|
game_title: "Wer findet die meisten Kameras?"
|
||||||
game_explanation_todo: "Willkommen zu unserem Überwachungsbewusstseinsspiel! Als Teil unserer Digital Shadows Ausstellung beim Ars Electronica Festival haben wir QR-Codes bei Überwachungskameras in ganz Linz platziert. Deine Mission: Entdecke die Kameras, scanne unsere Codes und finde heraus, wie allgegenwärtig öffentliche Überwachung wirklich ist. Wir sind aber nur Menschen – wir haben nur einen kleinen Teil aller Kameras erfasst, die unsere Stadt beobachten. Wer beobachtet wen in unseren öffentlichen Räumen? Die Jagd beginnt jetzt! 🕵️"
|
game_explanation_todo: "Willkommen zu unserem Überwachungsbewusstseinsspiel! Als Teil unserer Digital Shadows Ausstellung beim Ars Electronica Festival haben wir QR-Codes bei Überwachungskameras in ganz Linz platziert. Deine Mission: Entdecke die Kameras, scanne unsere Codes und finde heraus, wie allgegenwärtig öffentliche Überwachung wirklich ist. Wir sind aber nur Menschen – wir haben nur einen kleinen Teil aller Kameras erfasst, die unsere Stadt beobachten. Wer beobachtet wen in unseren öffentlichen Räumen? Die Jagd beginnt jetzt! 🕵️"
|
||||||
save_button: "Speichern"
|
save_button: "Speichern"
|
||||||
amount_participants: "In total there are %{amount} participants so far."
|
amount_participants: "Aktuell gibt es insgesamt %{amount} Teilnehmer."
|
||||||
cameras_found: "Du hast %{found}/%{total} Kameras gefunden:"
|
cameras_found: "Du hast %{found}/%{total} Kameras gefunden:"
|
||||||
highscore_title: "Bestenliste"
|
highscore_title: "Bestenliste"
|
||||||
not_found_title: "ups"
|
not_found_title: "ups"
|
||||||
@@ -53,3 +53,40 @@ footer_text: "Footer "
|
|||||||
footer_todo: "noch zu vervollständigen"
|
footer_todo: "noch zu vervollständigen"
|
||||||
footer_links: "mit Links"
|
footer_links: "mit Links"
|
||||||
impressum: "Impressum"
|
impressum: "Impressum"
|
||||||
|
|
||||||
|
# Privacy Policy
|
||||||
|
privacy_policy: "Datenschutz"
|
||||||
|
privacy_policy_title: "Datenschutzerklärung"
|
||||||
|
data_controller: "Datenverantwortlicher"
|
||||||
|
see_impressum: "Siehe Impressum"
|
||||||
|
overview: "Überblick"
|
||||||
|
privacy_overview: "Diese Datenschutzerklärung erklärt, wie Daten auf dieser Website gesammelt und verarbeitet werden. Diese Website ist Teil der <a href='https://www.jku.at/ars-electronica-2025-panic-yes-no/digital-shadows/' target='_blank'>Digital Shadows Ausstellung vom Ars Electronica Festival 2025</a>."
|
||||||
|
data_we_collect: "Daten, die wir sammeln"
|
||||||
|
cookies: "Cookies"
|
||||||
|
cookies_description: "Wir verwenden nur zwei Cookies auf dieser Website:"
|
||||||
|
cookie_client_id: "(notwendig): Ein automatisch generierter eindeutiger Identifikator, der benötigt wird, um zu verfolgen, welche Kameras Sie gefunden haben. Dieser Cookie ist für die Spielfunktionalität notwendig."
|
||||||
|
cookie_lang: "(optional): Speichert Ihre Spracheinstellung, wenn Sie eine Sprache auswählen. Dieser Cookie wird nur gesetzt, wenn Sie aktiv eine Spracheinstellung wählen."
|
||||||
|
game_data: "Spieldaten"
|
||||||
|
game_data_description: "Wenn Sie an unserem Überwachungsbewusstseinsspiel teilnehmen, sammeln wir:"
|
||||||
|
chosen_name: "Ihren gewählten Namen (optional): Der Anzeigename, den Sie eingeben, um in der Bestenliste angezeigt zu werden"
|
||||||
|
game_progress: "Spielfortschritt: Welche Kameras Sie entdeckt haben und wann Sie sie gefunden haben"
|
||||||
|
random_client_id: "Die zufällig generierte <em>client_id</em> um Ihre Spielsitzungen zu verknüpfen"
|
||||||
|
purpose_legal_basis: "Zweck und Rechtsgrundlage"
|
||||||
|
game_functionality: "Spielfunktionalität: Wir verarbeiten Ihre Daten, um das Kamera-Entdeckungsspiel zu betreiben (berechtigtes Interesse nach Art. 6(1)(f) DSGVO)"
|
||||||
|
language_preference: "Spracheinstellung: Wir speichern Ihre Sprachwahl basierend auf Ihrer Einwilligung (Art. 6(1)(a) DSGVO)"
|
||||||
|
data_retention: "Datenspeicherung"
|
||||||
|
data_retention_description: "Ihre Spieldaten werden in unserer Datenbank bis zum Ende der Ars Electronica Festival Ausstellungszeit gespeichert. Die Cookies verfallen nach einem Monat oder wenn Sie Ihre Cookies löschen. Es gibt keine langfristige Speicherung von Daten."
|
||||||
|
data_sharing: "Datenweitergabe"
|
||||||
|
data_sharing_description: "Wir teilen, verkaufen oder übertragen Ihre Daten nicht an Dritte. Daten werden ausschließlich für den Betrieb des Kamera-Entdeckungsspiels verwendet."
|
||||||
|
your_rights_gdpr: "Ihre Rechte unter der DSGVO"
|
||||||
|
rights_description: "Sie haben das Recht auf:"
|
||||||
|
right_access: "Zugang: Anfrage, welche Daten wir über Sie haben"
|
||||||
|
right_rectification: "Berichtigung: Korrektur ungenauer Daten"
|
||||||
|
right_erasure: "Löschung: Anfrage zur Löschung Ihrer Daten"
|
||||||
|
right_restriction: "Einschränkung: Beschränkung der Verarbeitung Ihrer Daten"
|
||||||
|
right_portability: "Datenübertragbarkeit: Erhalt Ihrer Daten in einem strukturierten Format"
|
||||||
|
right_object: "Widerspruch: Widerspruch gegen die Verarbeitung auf Basis berechtigter Interessen"
|
||||||
|
right_withdraw_consent: "Einwilligung zurückziehen: Für den Spracheinstellungs-Cookie"
|
||||||
|
how_to_exercise_rights: "Wie Sie Ihre Rechte ausüben können"
|
||||||
|
clear_cookies: "Browser-Cookies löschen, um gespeicherte Identifikatoren zu entfernen"
|
||||||
|
contact_us: "Kontaktieren Sie uns an unserem Postcity Linz Stand oder <a href='https://digidow.eu/impressum' target='_blank'>per E-Mail</a>"
|
||||||
|
@@ -29,7 +29,7 @@ location_linz: "Where: all over Linz"
|
|||||||
game_title: "Who finds the most cameras?"
|
game_title: "Who finds the most cameras?"
|
||||||
game_explanation_todo: "Welcome to our public surveillance awareness game! As part of our Digital Shadows exhibition at Ars Electronica Festival, we've placed QR codes near surveillance cameras throughout Linz. Your mission: spot the cameras, scan our codes, and discover how pervasive public monitoring really is. We're only human though – we've mapped just a small subset of all the cameras watching our city. Who's watching whom in our public spaces? The hunt begins now! 🕵️"
|
game_explanation_todo: "Welcome to our public surveillance awareness game! As part of our Digital Shadows exhibition at Ars Electronica Festival, we've placed QR codes near surveillance cameras throughout Linz. Your mission: spot the cameras, scan our codes, and discover how pervasive public monitoring really is. We're only human though – we've mapped just a small subset of all the cameras watching our city. Who's watching whom in our public spaces? The hunt begins now! 🕵️"
|
||||||
save_button: "Save"
|
save_button: "Save"
|
||||||
amount_participants: "Aktuell gibt es insgesamt %{amount} Teilnehmer."
|
amount_participants: "In total there are %{amount} participants so far."
|
||||||
cameras_found: "You have found %{found}/%{total} cameras:"
|
cameras_found: "You have found %{found}/%{total} cameras:"
|
||||||
highscore_title: "Highscore"
|
highscore_title: "Highscore"
|
||||||
not_found_title: "uups"
|
not_found_title: "uups"
|
||||||
@@ -53,3 +53,40 @@ footer_text: "Footer "
|
|||||||
footer_todo: "to be completed"
|
footer_todo: "to be completed"
|
||||||
footer_links: "with links"
|
footer_links: "with links"
|
||||||
impressum: "Impressum"
|
impressum: "Impressum"
|
||||||
|
|
||||||
|
# Privacy Policy
|
||||||
|
privacy_policy: "Privacy Policy"
|
||||||
|
privacy_policy_title: "Privacy Policy"
|
||||||
|
data_controller: "Data controller"
|
||||||
|
see_impressum: "See the impressum"
|
||||||
|
overview: "Overview"
|
||||||
|
privacy_overview: "This privacy policy explains how we collect and process data on this website, which is part of the <a href='https://www.jku.at/ars-electronica-2025-panic-yes-no/digital-shadows/' target='_blank'>Digital Shadows exhibition of the Ars Electronica Festival 2025</a>."
|
||||||
|
data_we_collect: "Data we collect"
|
||||||
|
cookies: "Cookies"
|
||||||
|
cookies_description: "We use only two cookies on this website:"
|
||||||
|
cookie_client_id: "(essential): An automatically generated unique identifier that allows us to tracks which cameras you've found. This cookie is necessary for the game functionality."
|
||||||
|
cookie_lang: "(optional): Stores your language preference when you select a language. This cookie is only set if you actively choose a language setting."
|
||||||
|
game_data: "Game data"
|
||||||
|
game_data_description: "When you participate in our surveillance awareness game, we collect:"
|
||||||
|
chosen_name: "Your chosen name (optional): The display name you enter to display in the highscore list"
|
||||||
|
game_progress: "Game progress: Which cameras you've discovered and when you found them"
|
||||||
|
random_client_id: "The randomly generated <em>client_id</em> to link your game sessions"
|
||||||
|
purpose_legal_basis: "Purpose and legal basis"
|
||||||
|
game_functionality: "Game functionality: We process your data to operate the camera discovery game (legitimate interest under Art. 6(1)(f) GDPR)"
|
||||||
|
language_preference: "Language preference: We store your language choice based on your consent (Art. 6(1)(a) GDPR)"
|
||||||
|
data_retention: "Data retention"
|
||||||
|
data_retention_description: "Your game data is stored in our database until the end of the Ars Electronica Festival exhibition period. The cookies expire after a month or when you clear your cookies. There is no long-term storage of any data."
|
||||||
|
data_sharing: "Data sharing"
|
||||||
|
data_sharing_description: "We do not share, sell, or transfer your data to third parties. Data is used exclusively for operating the camera discovery game."
|
||||||
|
your_rights_gdpr: "Your rights under GDPR"
|
||||||
|
rights_description: "You have the right to:"
|
||||||
|
right_access: "Access: Request what data we have about you"
|
||||||
|
right_rectification: "Rectification: Correct inaccurate data"
|
||||||
|
right_erasure: "Erasure: Request deletion of your data"
|
||||||
|
right_restriction: "Restriction: Limit how we process your data"
|
||||||
|
right_portability: "Data portability: Receive your data in a structured format"
|
||||||
|
right_object: "Object: Object to processing based on legitimate interests"
|
||||||
|
right_withdraw_consent: "Withdraw consent: For the language preference cookie"
|
||||||
|
how_to_exercise_rights: "How to exercise your rights"
|
||||||
|
clear_cookies: "Clear browser cookies to remove stored identifiers"
|
||||||
|
contact_us: "Contact us at our Postcity Linz booth or <a href='https://digidow.eu/impressum' target='_blank'>via mail</a>"
|
||||||
|
@@ -50,7 +50,7 @@ async fn retu(
|
|||||||
h1 { (t!("game_title")) }
|
h1 { (t!("game_title")) }
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
mark { (t!("game_explanation_todo")) }
|
(t!("game_explanation_todo"))
|
||||||
}
|
}
|
||||||
|
|
||||||
div.mb-sm { (t!("ask_to_change_name", name = client.get_display_name())) }
|
div.mb-sm { (t!("ask_to_change_name", name = client.get_display_name())) }
|
||||||
|
82
src/index.rs
82
src/index.rs
@@ -1,7 +1,7 @@
|
|||||||
use crate::{language::language, page::Page};
|
use crate::{language::language, page::Page};
|
||||||
use axum::http::HeaderMap;
|
use axum::http::HeaderMap;
|
||||||
use axum_extra::extract::CookieJar;
|
use axum_extra::extract::CookieJar;
|
||||||
use maud::{Markup, PreEscaped, html};
|
use maud::{html, Markup, PreEscaped};
|
||||||
|
|
||||||
pub(super) async fn index(cookies: CookieJar, headers: HeaderMap) -> Markup {
|
pub(super) async fn index(cookies: CookieJar, headers: HeaderMap) -> Markup {
|
||||||
let lang = language(&cookies, &headers);
|
let lang = language(&cookies, &headers);
|
||||||
@@ -53,3 +53,83 @@ pub(super) async fn index(cookies: CookieJar, headers: HeaderMap) -> Markup {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) async fn data(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! {
|
||||||
|
h1 { (t!("privacy_policy_title")) }
|
||||||
|
h2 { (t!("data_controller")) }
|
||||||
|
p {
|
||||||
|
a href="https://www.digidow.eu/impressum/" target="_blank" { (t!("see_impressum")) }
|
||||||
|
}
|
||||||
|
h2 { (t!("overview")) }
|
||||||
|
p {
|
||||||
|
(PreEscaped(t!("privacy_overview")))
|
||||||
|
}
|
||||||
|
h2 { (t!("data_we_collect")) }
|
||||||
|
h3 { (t!("cookies")) }
|
||||||
|
p {
|
||||||
|
(t!("cookies_description"))
|
||||||
|
ol {
|
||||||
|
li {
|
||||||
|
kbd { "client_id" }
|
||||||
|
" "
|
||||||
|
(t!("cookie_client_id"))
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
kbd { "lang" }
|
||||||
|
" "
|
||||||
|
(t!("cookie_lang"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h3 { (t!("game_data")) }
|
||||||
|
p {
|
||||||
|
(t!("game_data_description"))
|
||||||
|
ul {
|
||||||
|
li { (t!("chosen_name")) }
|
||||||
|
li { (t!("game_progress")) }
|
||||||
|
li {
|
||||||
|
(PreEscaped(t!("random_client_id")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
h2 { (t!("purpose_legal_basis")) }
|
||||||
|
ul {
|
||||||
|
li { (t!("game_functionality")) }
|
||||||
|
li { (t!("language_preference")) }
|
||||||
|
}
|
||||||
|
h2 { (t!("data_retention")) }
|
||||||
|
p {
|
||||||
|
(t!("data_retention_description"))
|
||||||
|
}
|
||||||
|
h2 { (t!("data_sharing")) }
|
||||||
|
p {
|
||||||
|
(t!("data_sharing_description"))
|
||||||
|
}
|
||||||
|
h2 { (t!("your_rights_gdpr")) }
|
||||||
|
p {
|
||||||
|
(t!("rights_description"))
|
||||||
|
ul {
|
||||||
|
li { (t!("right_access")) }
|
||||||
|
li { (t!("right_rectification")) }
|
||||||
|
li { (t!("right_erasure")) }
|
||||||
|
li { (t!("right_restriction")) }
|
||||||
|
li { (t!("right_portability")) }
|
||||||
|
li { (t!("right_object")) }
|
||||||
|
li { (t!("right_withdraw_consent")) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h3 { (t!("how_to_exercise_rights")) }
|
||||||
|
ul {
|
||||||
|
li { (t!("clear_cookies")) }
|
||||||
|
li {
|
||||||
|
(PreEscaped(t!("contact_us")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
use crate::model::client::Client;
|
use crate::model::client::Client;
|
||||||
use axum::{Router, http::HeaderMap, routing::get};
|
use axum::{http::HeaderMap, routing::get, Router};
|
||||||
use axum_extra::extract::{
|
use axum_extra::extract::{
|
||||||
CookieJar, PrivateCookieJar,
|
|
||||||
cookie::{Cookie, Expiration, Key},
|
cookie::{Cookie, Expiration, Key},
|
||||||
|
CookieJar, PrivateCookieJar,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{SqlitePool, pool::PoolOptions, sqlite::SqliteConnectOptions};
|
use sqlx::{pool::PoolOptions, sqlite::SqliteConnectOptions, SqlitePool};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
@@ -16,7 +16,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use time::{Duration, OffsetDateTime};
|
use time::{Duration, OffsetDateTime};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -278,6 +278,7 @@ async fn main() {
|
|||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(index::index))
|
.route("/", get(index::index))
|
||||||
|
.route("/privacy", get(index::data))
|
||||||
.nest_service("/static", ServeDir::new("./static/serve"))
|
.nest_service("/static", ServeDir::new("./static/serve"))
|
||||||
.merge(game::routes())
|
.merge(game::routes())
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use crate::Language;
|
use crate::Language;
|
||||||
use maud::{DOCTYPE, Markup, html};
|
use maud::{html, Markup, DOCTYPE};
|
||||||
|
|
||||||
pub(crate) struct Page {
|
pub(crate) struct Page {
|
||||||
lang: Language,
|
lang: Language,
|
||||||
@@ -104,9 +104,7 @@ impl Page {
|
|||||||
|
|
||||||
footer.container {
|
footer.container {
|
||||||
small {
|
small {
|
||||||
(t!("footer_text"))
|
a href="/privacy" { (t!("privacy_policy")) }
|
||||||
mark { (t!("footer_todo")) }
|
|
||||||
a href="#" { (t!("footer_links")) }
|
|
||||||
" • "
|
" • "
|
||||||
a target="_blank" href="https://www.digidow.eu/impressum/" {
|
a target="_blank" href="https://www.digidow.eu/impressum/" {
|
||||||
(t!("impressum"))
|
(t!("impressum"))
|
||||||
|
Reference in New Issue
Block a user