Automatisieren von Anfragen zum Recht auf Löschung

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

Die Allgemeine Datenschutzverordnung (DSGVO) ist eine europäische Verordnung zum Datenschutz und zur Privatsphäre. Sie gewährt Einzelpersonen das Recht, die Löschung ihrer personenbezogenen Daten zu verlangen, bekannt als das Recht auf Löschung. Wenn Sie personenbezogene Daten (PII) Ihrer Benutzer speichern, wie z. B. deren Benutzer-IDs, müssen Sie die Anforderungen der DSGVO einhalten, indem Sie diese Informationen nach Erhalt einer Anfrage des Benutzers löschen.

Anstatt Anfragen manuell zu bearbeiten, können Sie einen Webhook einrichten und einen Bot innerhalb einer Messaging-Anwendung eines Drittanbieters verwenden, um den Prozess zu automatisieren. Da Datenspeicher die gängigste Möglichkeit sind, PII-Daten zu speichern, bietet dieses Tutorial ein Beispiel dafür, wie man einen Bot in Discord erstellt, der die Open Cloud API für Datenspeicher verwendet, um PII-Daten als Lösung zur Automatisierung zu löschen.

Workflow

Nach Abschluss dieses Tutorials sollten Sie in der Lage sein, ein lokal laufendes benutzerdefiniertes Programm zu erstellen, das die Bearbeitung von Anfragen zum Recht auf Löschung von Benutzern automatisiert. Der Workflow für diesen Prozess ist wie folgt:

  1. Der Roblox-Support erhält eine Anfrage zum Recht auf Löschung von einem Benutzer.
  2. Der Roblox-Webhook wird ausgelöst, enthält die Benutzer-ID und eine Liste von Start-Ort-IDs für die Spiele, an denen sie im Payload teilgenommen haben.
  3. Ihr Bot hört auf diese Webhook-Benachrichtigungen, überprüft deren Authentizität und nutzt die Open Cloud API für Datenspeicher, um die in den Datenspeichern gespeicherten PII-Daten zu löschen.
  4. Der Bot antwortet auf die Webhook-Nachricht in Discord mit dem Löschstatus.

Konfigurieren Sie einen Webhook mit Integration von Drittanbietern

Bevor Sie einen Bot erstellen, richten Sie einen Server mit Webhook-Integration in der Messaging-Anwendung eines Drittanbieters ein. Verwenden Sie dann den Server, um einen Webhook im Creator-Dashboard zu konfigurieren.

Richten Sie einen Server ein

Die folgenden Schritte zeigen, wie Sie den Server mit Discord einrichten.

  1. Erstellen Sie einen neuen Discord-Server. Wenn Sie mit dem Prozess nicht vertraut sind, siehe Discord-Support.

  2. Der Server erstellt automatisch einen Kanal #general als Ihren Standardkanal. Klicken Sie auf das Kanal bearbeiten-Symbol des #general-Kanals.

  3. Setzen Sie unter Berechtigungen den Kanal auf privat.

  4. Erstellen Sie eine Webhook-Integration mit dem neuen Server und benennen Sie sie in GDPR Hook. Wenn Sie mit dem Prozess nicht vertraut sind, siehe Discord-Support.

  5. Kopieren Sie die Webhook-URL und bewahren Sie sie an einem sicheren Ort auf. Nur vertrauenswürdigen Teammitgliedern sollte der Zugriff gewährt werden, da das Leaking der URL es böswilligen Akteuren ermöglichen kann, gefälschte Nachrichten zu senden und möglicherweise Ihre Benutzerdaten zu löschen.

Konfigurieren Sie einen Webhook in Roblox

Nachdem Sie die URL des Drittanbieterservers erhalten haben, verwenden Sie sie, um einen Webhook zu konfigurieren im Creator-Dashboard. Stellen Sie sicher, dass Sie die folgenden Einstellungen vornehmen:

  • Fügen Sie die Discord-Server-URL als Webhook-URL hinzu.
  • Fügen Sie ein benutzerdefiniertes Secret hinzu. Obwohl ein Secret optional ist, um die Konfiguration abzuschließen, sollten Sie eines hinzufügen, um zu verhindern, dass böswillige Akteure sich als Roblox ausgeben und Ihre Daten löschen. Weitere Informationen zur Verwendung eines Secrets finden Sie unter Webhook-Sicherheit überprüfen.
  • Wählen Sie Anfrage zum Recht auf Löschung unter Trigger aus.

Sie können den Webhook mit der Testantwort-Schaltfläche testen, um zu sehen, ob Sie eine Benachrichtigung im #general-Kanal Ihres Servers von Roblox erhalten. Wenn Sie die Benachrichtigung nicht erhalten, versuchen Sie es erneut oder überprüfen Sie Ihre Servereinstellungen zur Fehlersuche.

Konfigurieren Sie einen Bot

Nachdem Sie den Webhook hinzugefügt haben, verwenden Sie ihn, um den Bot mit den folgenden Schritten zu konfigurieren. Für weitere Informationen siehe die Discord-Dokumentation.

  1. Navigieren Sie zur Anwendungsseite.
  2. Erstellen Sie eine neue Anwendung und benennen Sie sie in GDPR Bot.
  3. Das System leitet Sie zu den Einstellungen für Allgemeine Informationen des Bots weiter. Kopieren Sie die Anwendungs-ID und bewahren Sie sie an einem sicheren Ort auf.
  4. Wählen Sie im Einstellungsmenü OAuth2 aus.
  5. Navigieren Sie zu den OAuth2-Einstellungen.
    1. Aktivieren Sie den Bot-Scope. Eine Liste zusätzlicher Bot-Berechtigungen wird angezeigt.
    2. Fügen Sie die Berechtigung Administrator hinzu. Speichern Sie Ihre Änderungen.
    3. Speichern Sie die generierte URL.
  6. Kopieren Sie die generierte URL. Lassen Sie die Anwendungsseiteneinstellungen offen.
  7. Navigieren Sie zur generierten URL. Wählen Sie den Zielserver aus. Klicken Sie auf die Schaltfläche Weiter und dann auf die Schaltfläche Autorisieren.
  8. Navigieren Sie zurück zur Anwendungsseiteneinstellungen und dann zu den Bot-Einstellungen.
  9. Aktivieren Sie im Abschnitt Privileged Gateway Intents die Message Content Intent.
  10. Speichern Sie im Bot-Einstellungen > Build-A-Bot-Abschnitt das Bot-Token an einem sicheren Ort für spätere Schritte. Wenn Sie das Token nicht sehen, klicken Sie auf die Schaltfläche Token zurücksetzen, um ein neues zu generieren.

Erstellen Sie einen Open Cloud API-Schlüssel

Um Ihrem Bot von Drittanbietern den Zugriff auf Ihre Datenspeicher zur Speicherung von PII-Daten der Benutzer zu ermöglichen, erstellen Sie einen Open Cloud API-Schlüssel, der auf Ihre Spiele zugreifen kann, und fügen Sie die Berechtigung Eintrag löschen der Datenspeicher für die Datenlöschung hinzu. Wenn Sie geordnete Datenspeicher zur Speicherung von PII verwenden, müssen Sie auch die Berechtigung Schreiben der geordneten Datenspeicher hinzufügen. Nach Abschluss kopieren und speichern Sie den API-Schlüssel an einem sicheren Ort, um ihn in späteren Schritten zu verwenden.

Beschaffen Sie die Identifikatoren von Spielen und Orten

Damit der Bot die PII-Daten lokalisieren kann, die von Benutzern zur Löschung angefordert werden, beschaffen Sie die folgenden Identifikatoren aller Spiele, die Sie mit dem Bot verwenden möchten:

  • Die Universums-ID, die eindeutige Kennung Ihres Spiels.
  • Die Start-Ort-ID, die eindeutige Kennung des Startorts eines Spiels.

Um diese Identifikatoren zu erhalten:

  1. Navigieren Sie zum Creator-Dashboard.

  2. Fahren Sie mit der Maus über das Miniaturbild eines Spiels, klicken Sie auf die Schaltfläche und wählen Sie Universums-ID kopieren und Start-Ort-ID kopieren aus.

Fügen Sie Skripte hinzu

Nachdem Sie den Webhook, den Bot und den API-Schlüssel für Datenspeicher eingerichtet haben, fügen Sie diese in die Skripte ein, die die Automatisierungslogik des Bots implementieren. Das folgende Beispiel verwendet Python 3.

  1. Installieren Sie die Python-Bibliotheken mit den folgenden Befehlen:

    Bibliotheken installieren

    pip3 install discord
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Kopieren und speichern Sie die folgenden Skripte, die verschiedenen Teilen der Bot-Logik entsprechen, im selben Verzeichnis:

    bot_config.py

    BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Wörterbuch der Start-Ort-ID an
    # (Universums-ID, Liste von (Name der Datenspeicher, Scope und Einstiegsschlüssel)) für
    # Standard-Datenspeicher
    # Benutzerdaten, die unter diesen Einträgen gespeichert sind, werden gelöscht
    STANDARD_DATA_STORE_ENTRIES = {
    # Start-Ort-ID
    111111111: (
    # Universums-ID
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Wörterbuch der Start-Ort-ID an
    # (Universums-ID, Liste von (Name der Datenspeicher, Scope und Einstiegsschlüssel)) für
    # Geordnete Datenspeicher
    # Benutzerdaten, die unter diesen Einträgen gespeichert sind, werden gelöscht
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py

    import requests
    import bot_config
    from collections import defaultdict
    """
    Ruft die Data Stores Open Cloud API auf, um alle Einträge für eine benutzer_id zu löschen, die in
    STANDARD_DATA_STORE_ENTRIES konfiguriert ist. Gibt eine Liste erfolgreicher Löschungen und fehlgeschlagener Löschungen zurück.
    """
    def delete_standard_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.STANDARD_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.STANDARD_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/datastores/v1/universes/{universe_id}/standard-datastores/datastore/entries/entry",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY},
    params={
    "datastoreName": data_store_name,
    "scope": scope,
    "entryKey": entry_key
    }
    )
    if response.status_code in [200, 204]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    """
    Ruft die Ordered Data Stores Open Cloud API auf, um alle Einträge für eine benutzer_id zu löschen, die in
    ORDERED_DATA_STORE_ENTRIES konfiguriert ist. Gibt eine Liste erfolgreicher Löschungen und fehlgeschlagener Löschungen zurück.
    """
    def delete_ordered_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.ORDERED_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.ORDERED_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/ordered-data-stores/v1/universes/{universe_id}/orderedDatastores/{data_store_name}/scopes/{scope}/entries/{entry_key}",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY}
    )
    if response.status_code in [200, 204, 404]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    message_parser.py

    import time
    import hmac
    import hashlib
    import re
    import base64
    import bot_config
    """
    Analysiert die empfangene Nachricht nach der Roblox-Signatur und dem Zeitstempel, der Footer wird nur gesetzt, wenn Sie
    das Webhook-Secret konfiguriert haben.
    """
    def parse_footer(message):
    if not message.embeds[0].footer or \
    not message.embeds[0].footer.text:
    return "", 0
    footer_match = re.match(
    r"Roblox-Signature: (.*), Timestamp: (.*)",
    message.embeds[0].footer.text
    )
    if not footer_match:
    return "", 0
    else:
    signature = footer_match.group(1)
    timestamp = int(footer_match.group(2))
    return signature, timestamp
    """
    Überprüft die Roblox-Signatur mit dem konfigurierten Secret auf ihre Gültigkeit.
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # Verhindert Wiederholungsangriffe im 300 Sekundenfenster
    request_timestamp_ms = timestamp * 1000
    window_time_ms = 300 * 1000
    oldest_timestamp_allowed = round(time.time() * 1000) - window_time_ms
    if request_timestamp_ms < oldest_timestamp_allowed:
    return False
    # Validiert die Signatur
    timestamp_message = "{}.{}".format(timestamp, message.embeds[0].description)
    digest = hmac.new(
    bot_config.ROBLOX_WEBHOOK_SECRET.encode(),
    msg=timestamp_message.encode(),
    digestmod=hashlib.sha256
    ).digest()
    validated_signature = base64.b64encode(digest).decode()
    if signature != validated_signature:
    return False
    # Gültige Signatur
    return True
    """
    Analysiert eine empfangene Webhook-Nachricht auf Discord. Extrahiert die Benutzer-ID, verhindert Wiederholungsangriffe
    auf der Grundlage des empfangenen Zeitstempels und überprüft die Roblox-Signatur mit dem konfigurierten Secret auf ihre Gültigkeit.
    """
    def parse_message(message):
    # Analysiert die empfangene Nachricht nach Benutzer-ID und Spiel-ID
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"Sie haben eine neue Benachrichtigung für das Recht auf Löschung für die Benutzer-ID: (.*) in " +
    r"den Spiel(en) mit IDs: (.*)",
    message.embeds[0].description
    )
    if not description_match:
    return "", []
    user_id = description_match.group(1)
    start_place_ids = set(int(item.strip()) for item in description_match.group(2).split(","))
    signature, timestamp = parse_footer(message)
    if validate_signature(message, signature, timestamp):
    return user_id, start_place_ids
    else:
    return "", []
    discord_bot.py

    import discord
    import bot_config
    import data_stores_api
    import message_parser
    def run():
    intents = discord.Intents.default()
    intents.message_content = True
    client = discord.Client(intents=intents)
    @client.event
    async def on_ready():
    print(f"{client.user} hört auf Nachrichten zum Recht auf Löschung")
    """
    Handler für Webhook-Nachrichten von Roblox
    """
    @client.event
    async def on_message(message):
    # Analysiert und validiert die Nachricht
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Löscht die Benutzer Daten im Standard-Datenspeicher
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Gelöschte Daten im Standard-Datenspeicher für " +
    f"Benutzer-ID: {user_id}, Daten: {dict(successes)}")
    if failures:
    await message.reply(f"Fehler beim Löschen von Daten im Standard-Datenspeicher für " +
    f"Benutzer-ID: {user_id}, Daten: {dict(failures)}")
    # Löscht die Benutzer Daten im geordneten Datenspeicher
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Gelöschte Daten im geordneten Datenspeicher für " +
    f"Benutzer-ID: {user_id}, Daten: {dict(successes)}")
    if failures:
    await message.reply(f"Fehler beim Löschen von Daten im geordneten Datenspeicher für " +
    f"Benutzer-ID: {user_id}, Daten: {dict(failures)}")
    client.run(bot_config.BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. In der Datei bot_config.py für die Hauptkonfiguration des Bots:

    1. Setzen Sie BOT_TOKEN auf das Token, das von Ihrem Bot generiert wurde.
    2. Setzen Sie OPEN_CLOUD_API_KEY auf den von Ihnen erstellten API-Schlüssel.
    3. Setzen Sie ROBLOX_WEBHOOK_SECRET auf das Secret, das Sie bei der Konfiguration des Webhooks im Creator-Dashboard festgelegt haben.
    4. In den Wörterbüchern STANDARD_DATA_STORE_ENTRIES und ORDERED_DATA_STORE_ENTRIES zum Auffinden des Datenspeichers für jeden zu löschenden Eintrag:
      1. Fügen Sie Ihre kopierten Start-Ort-IDs als Schlüssel hinzu.
      2. Fügen Sie Universums-IDs als erstes Element des Tupelwerts hinzu.
      3. Ersetzen Sie das zweite Element des Tupels durch den Namen, den Scope, den Einstiegsschlüssel und die zugehörige Benutzer-ID Ihrer Datenspeicher. Wenn Sie ein anderes Datenschema verwenden, passen Sie das entsprechend an.
  4. Führen Sie den folgenden Befehl aus, um den Bot zu starten:

    Discord Bot ausführen

    python3 discord_bot.py
  5. Der Bot beginnt dann, Roblox-Webhook-Nachrichten für Anfragen zum Recht auf Löschung zu hören und ruft den Open Cloud-Endpunkt zum Löschen des entsprechenden Datenspeichers auf.

Testen

Sie können eine Testnachricht erstellen und senden, um zu überprüfen, ob Ihr benutzerdefiniertes Programm Anfragen zum Recht auf Löschung ordnungsgemäß bearbeiten und PII-Daten löschen kann:

  1. Senden Sie eine HTTP POST-Anfrage an Ihren Discord-Webhooks-Server mit folgendem Anfragekörper:

    Beispielanfrage

    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RightToErasureRequest",
    "description":"Sie haben eine neue Benachrichtigung für das Recht auf Löschung für die Benutzer-ID: {userIds} in den Spiel(en) mit IDs: {gameIds}",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Timestamp: {timestamp}"
    }
    }]
    }'
  2. Wenn Sie ein Webhook-Secret haben:

    1. Generieren Sie eine Roblox-Signature, indem Sie HMAC-SHA256-Encoding auf Ihren Webhook-Secret-Schlüssel anwenden.
    2. Setzen Sie die aktuelle Zeit unter Verwendung des UTC-Zeitstempels in Sekunden als Timestamp.
  3. Stellen Sie den description-Text in folgendem Format zusammen:

    Format des Beschreibungsfeldes

    {Timestamp}. Sie haben eine neue Benachrichtigung für das Recht auf Löschung für die Benutzer-ID: {userId} in den Spiel(en) mit IDs: {gameIds}`.

    Zum Beispiel:

    Beispiel für das Beschreibungsfeld

    1683927229. Sie haben eine neue Benachrichtigung für das Recht auf Löschung für die Benutzer-ID: 2425654247 in den Spiel(en) mit IDs: 10539205763, 13260950955

Ihr Programm sollte in der Lage sein zu erkennen, dass Ihre Nachricht von der offiziellen Roblox-Quelle stammt, da Sie die Nachricht mit Ihrem Secret codiert haben. Es sollte dann die mit Ihrer Anfrage verbundenen PII-Daten löschen.

Beispielkörper

{
"embeds": [
{
"title": "RightToErasureRequest",
"description": "Sie haben eine neue Benachrichtigung für das Recht auf Löschung für die Benutzer-ID: 2425654247 in den Spiel(en) mit IDs: 10539205763, 13260950955",
"footer": {
"icon_url": "https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
"text": "Roblox-Signature: UIe6GJ78MHCmU/zUKBYP3LV0lAqwWRFR6UEfPt1xBFw=, Timestamp: 1683927229"
}
}
]
}
©2026 Roblox Corporation. Roblox, das Roblox-Logo und "Powering Imagination" gehören zu unseren eingetragenen und nicht eingetragenen Markenzeichen in den USA und anderen Ländern.