Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0c3113fd4 | |||
|
|
84a56678e0 |
8 changed files with 195 additions and 450 deletions
44
.cargo/snapchat-dpo-mail.txt
Normal file
44
.cargo/snapchat-dpo-mail.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Dear Snap Data Protection Officer,
|
||||
|
||||
I am writing to exercise my right to erasure under Article 17 of the GDPR in relation to two Snapchat accounts that belong to me:
|
||||
|
||||
alexemmet
|
||||
|
||||
alex_emmet
|
||||
|
||||
I previously contacted Snapchat Support through X, formerly Twitter, because I was unable to identify a functioning general support email address or reach a human support representative through the available support channels.
|
||||
|
||||
In my message through X, I explained that I am requesting deletion of both accounts and the personal data associated with them.
|
||||
|
||||
I still have access to the login credentials for alexemmet and can verify ownership of that account through the normal account-access process.
|
||||
|
||||
For alex_emmet, I no longer have access to the old device, email address, or phone number that may have been associated with the account. The account was created when I was under 18.
|
||||
|
||||
Snapchat Support responded through X that it could not take action where a user does not know, or no longer has access to, the email address or phone number associated with an account.
|
||||
|
||||
I would like to clarify that I am not requesting account recovery, a password reset, or restored access to alex_emmet. I am making a data-subject request for erasure of my personal data.
|
||||
|
||||
I understand that Snap is entitled to verify my identity before acting on this request. Under Article 12(6) GDPR, where there are reasonable doubts concerning the identity of the person making a request, the controller may request additional information necessary to confirm the person's identity.
|
||||
|
||||
I am therefore asking Snap to provide an alternative means of verifying that I am the data subject associated with alex_emmet, given that I no longer have access to the original device, email address, or phone number. I am willing to provide reasonable information necessary for verification through a secure channel.
|
||||
|
||||
My request covers:
|
||||
|
||||
deletion of the Snapchat account alexemmet;
|
||||
|
||||
deletion of the Snapchat account alex_emmet;
|
||||
|
||||
erasure of personal data associated with both accounts;
|
||||
|
||||
erasure of personal data contained in previous support correspondence, support tickets, attachments, account-recovery records, and associated metadata concerning me.
|
||||
|
||||
If Snap considers that any of this data must be retained, please identify the categories of data being retained, the legal basis for retention, and the applicable retention period.
|
||||
|
||||
If Snap considers that it cannot comply with the erasure request for alex_emmet, please provide the specific reason for that decision and explain why no alternative method of verifying my identity is available.
|
||||
|
||||
I would also appreciate confirmation that this request is being handled as a GDPR data-subject request rather than as an account-recovery request.
|
||||
|
||||
I can provide screenshots of my correspondence with Snapchat Support through X if required.
|
||||
|
||||
Kind regards,
|
||||
Alex
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -27,6 +27,7 @@ target
|
|||
# Added by cargo
|
||||
|
||||
/target
|
||||
/certs
|
||||
|
||||
*.mk
|
||||
*.mpkb
|
||||
|
|
|
|||
552
Cargo.lock
generated
552
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,7 @@ rustls = { version = "0.23.42", default-features = false, features = [
|
|||
"aws-lc-rs",
|
||||
"prefer-post-quantum",
|
||||
] }
|
||||
sqlx = { version = "0.8.6", features = ["mysql", "runtime-tokio", "migrate"] }
|
||||
sqlx = { version = "0.9.0", features = ["mysql", "runtime-tokio", "migrate"] }
|
||||
tokio = { version = "*", features = ["full"] }
|
||||
tokio-util = { version = "0.7.19", features = ["rt"] }
|
||||
uuid = { version = "1.24.0", features = ["v4", "v7"] }
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@
|
|||
bindAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "IP address to bind the HTTP/API server to.";
|
||||
description = "IP address to bind the MTP/QUIC server to.";
|
||||
};
|
||||
|
||||
openFirewall = lib.mkOption {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit a297dcce60bc6e84696c6a16f5fd510beb2ca643
|
||||
Subproject commit 486541b9483356ff49ff3ec7016f87d3ecbeaa0e
|
||||
|
|
@ -15,7 +15,7 @@ use mtp::{
|
|||
webserver::{MTPWebServer, WebMtpReceiver, WebMtpSender},
|
||||
};
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
net::IpAddr,
|
||||
sync::{
|
||||
Arc, Mutex as StdMutex,
|
||||
atomic::{AtomicU32, AtomicUsize, Ordering},
|
||||
|
|
@ -30,11 +30,19 @@ use tokio_util::{sync::CancellationToken, task::TaskTracker};
|
|||
|
||||
const CLEANUP_INTERVAL: Duration = Duration::from_secs(30);
|
||||
const MAX_WAITING_AGE: Duration = Duration::from_secs(60);
|
||||
const DEFAULT_BIND_ADDRESS: &str = "0.0.0.0";
|
||||
static ACTIVE_CONNECTIONS: AtomicUsize = AtomicUsize::new(0);
|
||||
static NEXT_CORRELATION_ID: AtomicU32 = AtomicU32::new(1);
|
||||
static ACTIVE_CONNECTIONS_BY_IP: once_cell::sync::Lazy<DashMap<IpAddr, usize>> =
|
||||
once_cell::sync::Lazy::new(DashMap::new);
|
||||
|
||||
fn parse_bind_address(value: Option<&str>) -> Result<IpAddr, std::net::AddrParseError> {
|
||||
value
|
||||
.unwrap_or(DEFAULT_BIND_ADDRESS)
|
||||
.trim()
|
||||
.parse::<IpAddr>()
|
||||
}
|
||||
|
||||
struct ConnectionLimitGuard(Option<IpAddr>);
|
||||
impl Drop for ConnectionLimitGuard {
|
||||
fn drop(&mut self) {
|
||||
|
|
@ -666,7 +674,7 @@ pub async fn start(port: u16, state: Arc<OmegaState>) -> Result<(), Box<dyn std:
|
|||
let web_config = server::web::build_web_config(state.identity.clone())?
|
||||
.serve_tcp_https(true)
|
||||
.max_tcp_connections(256);
|
||||
let ip = IpAddr::from(Ipv4Addr::new(0, 0, 0, 0));
|
||||
let ip = parse_bind_address(std::env::var("BIND_ADDRESS").ok().as_deref())?;
|
||||
let host_config = HostConfig::new(ip, port, cert_pem, key_pem)
|
||||
.with_policy(Policy {
|
||||
send_mode: SendMode::SingleStreamPerMessage,
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ fn format_data_container(data: Vec<(DataTypeId, DataValue)>, version: Version) -
|
|||
let key_str = key.to_string();
|
||||
|
||||
match value {
|
||||
DataValue::Str(s) => format!("{}=\"{}\"", key_str, s),
|
||||
DataValue::Str(s) => format!("{}=\"{}\"", key_str, abbreviate_string(&s)),
|
||||
|
||||
DataValue::Container(inner) => {
|
||||
let inner_formatted = format_data_container(inner, version.clone());
|
||||
|
|
@ -304,7 +304,7 @@ fn format_array(arr: Vec<DataValue>, version: Version) -> String {
|
|||
let parts: Vec<String> = arr
|
||||
.into_iter()
|
||||
.map(|value| match value {
|
||||
DataValue::Str(s) => format!("\"{}\"", s),
|
||||
DataValue::Str(s) => format!("\"{}\"", abbreviate_string(&s)),
|
||||
|
||||
DataValue::Container(inner) => {
|
||||
let inner_formatted = format_data_container(inner, version.clone());
|
||||
|
|
@ -329,6 +329,32 @@ fn format_array(arr: Vec<DataValue>, version: Version) -> String {
|
|||
|
||||
parts.join(", ")
|
||||
}
|
||||
|
||||
fn abbreviate_string(value: &str) -> String {
|
||||
const EDGE_LENGTH: usize = 4;
|
||||
|
||||
let chars: Vec<char> = value.chars().collect();
|
||||
if chars.len() <= EDGE_LENGTH * 2 {
|
||||
return value.to_string();
|
||||
}
|
||||
|
||||
let prefix: String = chars.iter().take(EDGE_LENGTH).collect();
|
||||
let suffix: String = chars.iter().rev().take(EDGE_LENGTH).rev().collect();
|
||||
format!("{prefix}...{suffix}")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::abbreviate_string;
|
||||
|
||||
#[test]
|
||||
fn abbreviates_only_strings_longer_than_eight_characters() {
|
||||
assert_eq!(abbreviate_string("12345678"), "12345678");
|
||||
assert_eq!(abbreviate_string("123456789"), "1234...6789");
|
||||
assert_eq!(abbreviate_string("YWJjZGVmZ2hpag=="), "YWJj...ag==");
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_cv {
|
||||
($kind:expr, $cv:expr) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue