Silme İsteklerine Otomatik Haklar

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Genel Veri Koruma Yönetmeliği (GDPR) Avrupa'daki veri koruma ve gizlilik yönetmeliğidir. İnsanlar, kişisel verilerinin silinmesini talep etme hakkını kullanır, kişisel verilerinin bilinen ticari olmayan adına erişim olarak bilinir. Eğer kullanıcı

İstekleri manuel olarak işlemek yerine, bir webhook oluşturabilirsiniz ve bir üçüncü parti mesajlaşma uygulamasında botu kullanarak işlemi otomatikleştirebilirsiniz. Veri depolarının en yaygın yolunu oluşturmak için, bu öğretici, Guilded veya Discord'

İş akışı

Bu öğreticiyi tamamladıktan sonra, kullanıcıların silme isteklerinin işlenmesini otomatikleştiren yerel bir özelleştirilmiş program oluşturabilmelisiniz. Bu işlem için iş akış şu şekilde olmalıdır:

  1. Roblox Destek, bir kullanıcının silme isteğini yerine getirme hakkına sahiptir.
  2. Roblox webhook'i tetiklenir, kullanıcı kimliğini ve yüklenenlerin katıldığı deneyimler için bir Start Place ID listesini içerir.
  3. Bot'unuz bu webhook bildirimlerine kulak veriyor, onların gizliliğini doğruluyor ve Open Cloud API for data stores kullanıyor çöp kaynaklarında depolanan PII verilerini silmek için.
  4. Bot, Discord'ta veya Guilded'de silme durumuyla webhook mesajına yanıt verir.

Üçüncü Taraf Bir Webhook'u Yapılandırma

Bir bot oluşturmadan önce, webhook entegrasyonlu bir sunucu üzerinde üçüncü parti mesajlaşma uygulamasında bir sunucu kurun. Sonra, yaratıcı dashboard'ında bir webhook'ı yapılandırmak için sunucuyu kullanın.

Bir Sunucu Kurulması

Aşağıdaki adımlar, Guilded veya Discord'u kullanarak sunucuyu nasıl ayarlanacağını gösterir.

  1. Yeni bir Guilded sunucusu oluşturun. Eğer işleme aşina değilseniz, bakın Guilded Destek.
  2. Gizlilik ayarları altında, sunucuyu özel olarak ayarlayın. Sunucu, varsayılan kanalınız olarak otomatik olarak özel bir <a href="/reference/privacy-and-security"># general</a> kanalı oluşturur.
  3. Yeni sunucuyla bir webhook entegrasyonu oluşturun ve kolayca anlayabileceğiniz bir isim verin, örneğin GDPR Hook. Eğer işlemle ilgili değilseniz, bakın Lonca Desteği.
  4. Webhook URL'sini kopyalayın ve güvenli bir dünyasaklayın. Sadece güvenilir takım üyelerinin erişmesine izin verin, çünkü URL'yi açığa çıkarmak kötü aktörlerin gönderdiği sahte mesajları potansiyel olarak kullanıcı verilerinizi silmesine izin verebilir.

Roblox'ta bir Webhook'u yapılandırma

Üçüncü parti sunucu URL'sini aldıktan sonra, Creator Dashboard'ta bir webhook'u yapılandırmak için kullanın. aşağıdaki ayarları yapın:

  • Guilded veya Discord sunucu URL'sini Webhook URL olarak ekler.
  • Yapılandırmanın tamamlanması için gizli bir Gizli dahil edin. Gizli, Roblox'u tamamlamak için zorunlu değil, ancak kötü aktörlerin Roblox'u kimlik avcısı olmasını önlemek için birini dahil etmelisiniz. Gizli kullanımı hakkında daha fazla bilgi için, Verifying Webhook Security bakın.
  • Select Silme İsteği Hakkında Tetikler altında.

Roblox'un Test Cevabı düğmesini kullanarak webhook'u test edebilirsiniz, böylece sunucunuzun genel kanalından bir bildirimi alıp almadığınızı görebilirsiniz. Eğer bildirimi almazsanız, yeniden deneyin veya sunucu ayarlarınızı kontrol ederek hatayı giderebilirsiniz.

Example notification on Guilded

Bir Bot'u Yapılandırma

Webhook'ı ekledikten sonra, aşağıdaki adımları kullanarak bot'u yapılandırın:

  1. Simgesine tıklayarak Tüm sunucuları aç listesini aç veya kısayol kullan:

    • CtrlS Windows'ta.
    • S Mac'te.
  2. Erişim bildirimleri almak için sunucunuzu seçin.

  3. Expand the list under Sunucunun evine and select Bot yönetimi .

  4. Sunucu, varsayılan kanalınız olarak özel bir # general kanalı otomatik olarak oluşturur.

  5. Bot oluşturma düğmesine tıklayın ve bir bot ismi ekleyin. Guilded'i giriş sayfasına yönlendirir.

  6. Bot yapılandırma sayfasındaki API bölümünü seçin.

  7. Jetonlar bölümünde, Jeton Oluştur düğmesine tıklayın.

  8. Oluşturulan jetonu güvenli bir dünyasaklayın ve saklayın.

Bir Açık Bulut API Anahtarı Oluşturulması

Üçüncü parti botunuzun kullanıcıların Kişisel Tanıtıcı Bilgilerverilerini depolamak için veri depolarınıza erişmesine izin vermek için, bir Open Cloud API anahtarı oluştur ki kullanıcıların deneyimlerine erişebilir ve veri depolarının silme izinini ekleyebil

Deneyimlerin ve Yerlerin Kimliklerini Alın

Botun kullanıcılar tarafından silinmesini istediği PII verilerini bulması için, botu kullanmak için niyettiğiniz tüm deneyimlerinizin aşağıdaki kimliklerini alın:

  • Deneyiminizin benzersiz kimliği olan Evren ID'si ,
  • Etkinliğin başlangıç yerinin benzersiz kimliği olan Başlangıç Yeri ID 'dir.

Bu kimlikleri almak için, Yaratıcı Dashboard sayfasını açın. Ardından bir deneyim seçin ve Evren ID ve 2>Yer Başlangıcı ID2> kopyalayın.

Copy Universe ID and Copy Start Place ID options from Creator Dashboard

Script'leri Ekleme

Dahili API'yi, bot'u ve veri depoları için webhook'u, bot'un otomasyon mantığını uygulayan kodları ekledikten sonra kodları kullanıcının kodlarına ekleyin. Aşağıdaki örnek, Python 3'i kullanır:

  1. Python kütüphanelerini şu komutları kullanarak yükle:

    Kütüphaneleri Kur

    pip3 install discord
    pip3 install guilded.py==1.8.0
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Aşağıdaki senaryoları aynı dizinin farklı bölümlerine karşılık olarak kopyalayıp kaydetin:

    bot_config.py

    DISCORD_BOT_TOKEN = ""
    GUILDED_BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Başlangıç ​​Yeri ID'si ile
    # (evren ID, liste (veri depolarının adı, alanı ve giriş anahtarı)) için
    # Standart Veri Depoları
    # Bu girdilerin altında saklanan kullanıcı verileri silinecek
    STANDARD_DATA_STORE_ENTRIES = {
    # Yer Başlangıcı ID
    111111111: (
    # Evren ID
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Başlangıç ​​Yeri ID'si ile
    # (evren ID, liste (veri depolarının adı, alanı ve giriş anahtarı)) için
    # Veri Depoları Sıralandı
    # Bu girdilerin altında saklanan kullanıcı verileri silinecek
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py

    import requests
    import bot_config
    from collections import defaultdict
    """
    Calls Data Stores Open Cloud API to delete all entries for a user_id configured in
    STANDARD_DATA_STORE_ENTRIES. Returns a list of successful deletions and failures to delete.
    """
    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
    """
    Calls Ordered Data Stores Open Cloud API to delete all entries for a user_id configured in
    ORDERED_DATA_STORE_ENTRIES. Returns a list of successful deletions and failures to delete.
    """
    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
    i̇leti_yorumlayıcı.py

    import time
    import hmac
    import hashlib
    import re
    import base64
    import bot_config
    """
    Parses received message for Roblox signature and timestamp, the footer is only set if you
    configured webhook secret
    """
    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
    """
    Verifies Roblox signature with configured secret to check for validity
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # 300 saniye içinde yeniden oynatma saldırısını önler
    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
    # İşaretleyiciyi geçerli kılar
    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
    # Geçerli imza
    return True
    """
    Parses a received webhook messaged on Discord or Guilded. Extracts user ID, prevents replay attack
    based on timestamp received, and verifies Roblox signature with configured secret to check for
    validity.
    """
    def parse_message(message):
    # Kullanıcı ID ve oyun ID için alınan mesaj
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"You have received a new notification for Right to Erasure for the User Id: (.*) in " +
    r"the game\(s\) with 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 "", []
    guilded_bot.py

    import guilded
    import json
    import bot_config
    import data_stores_api
    import message_parser
    def run():
    client = guilded.Client()
    @client.event
    async def on_ready():
    print(f"{client.user} is listening to Right to Erasure messages")
    """
    Handler for webhook messages from Roblox
    """
    @client.event
    async def on_message(message):
    # Mesajı parsleyin ve mesaj
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Standart veri depolarının kullanıcı verilerini siler
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Deleted standard data stores data for " +
    f"user ID: {user_id}, data: {dict(successes)}")
    if failures:
    await message.reply(f"Failed to delete standard data stores data for " +
    f"user ID: {user_id}, data: {dict(failures)}")
    # Sıralama verileri kullanıcı verilerini siler
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Deleted ordered data stores data for " +
    f"user ID: {user_id}, data: {dict(successes)}")
    if failures:
    await message.reply(f"Failed to delete ordered data stores data for " +
    f"user ID: {user_id}, data: {dict(failures)}")
    client.run(bot_config.GUILDED_BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. Bot'un ana yapılandırması için bot_config.py dosyasında:

    1. Botunuz tarafından oluşturulan jetona DISCORD_BOT_TOKEN veya GUILDED_BOT_TOKEN ayarlayın.
    2. Yaratmış olduğun API anahtarını OPEN_CLOUD_API_KEY olarak ayarla.
    3. Yaratıcı Dashboard'ta webhook'u yapılandırırken ayarladığınız gizli ROBLOX_WEBHOOK_SECRET olarak ayarlayın.
    4. Her kaydın yerini bulmak için STANDARD_DATA_STORE_ENTRIES ve ORDERED_DATA_STORE_ENTRIES sözlüklerindeki kaydı silmek için kaydı bulmak için yerleştirilmiş bir kaydın yerini bulmak için YERLEŞTİRİLDİĞİ YER yerleştirilmiş bir kaydın yerini bulmak için 2>YERLEŞTİRİLDİĞ
      1. Kopyalanmış Start Place ID'lerinizi anahtar olarak ekleyin.
      2. Değer dizgesinin ilk elemanı olarak Universe ID'leri ekleyin.
      3. Topluluğun ikinci elemanını, ismi, alanı, giriş anahtarı ismini ve ilişkili veri depolarınızın kullanıcı kimliğini değiştirin. Eğer farklı bir veri şeması kullanıyorsanız, kendi veri şemanızın şeklini değiştirin.
  4. Bot'u çalıştırmak için aşağıdaki komutu yürütün:

    Guilded Bot'u Çalıştır

    python3 guilded_bot.py
  5. Bot ardından Roblox webhook'larını dinleyin ve doğrulayın ve Open Cloud API'sini çağırın, ilgili veri mağazasilmek için Açık Bulut API'sini çağırın.

Test

Özelleştirilmiş programınızın doğru silme isteklerine ve silme verilerine erişim isteklerine doğru olarak işleyebileceğini doğrulamak için bir test mesajı oluşturup çalıştırabilirsiniz:

  1. Guilded veya Discord webhook sunucunuzla bir HTTP POST istek gönderin, aşağıdaki istek vücut:

    Örnek İstek

    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RightToErasureRequest",
    "description":"You have received a new notification for Right to Erasure for the User Id: {userIds} in the game(s) with Ids: {gameIds}",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Timestamp: {timestamp}"
    }
    }]
    }'
  2. Eğer bir webhook'a gizli varsa:

    1. HMAC-SHA256 kodlanmasını webhook'unuzun gizli anahtarına uygulayarak bir Roblox-Signature oluşturun.
    2. UTC saati olarak saniye başına Timestamp olarak mevcut zamanı ayarlar.
  3. açıklama adlı öğeyi şu biçimde birleştir:

    Description Field Format

    {Timestamp}. You have received a new notification for Right to Erasure for the User Id: {userId} in the game(s) with Ids: {gameIds}`.

    Örneğin:

    Example Description Field

    1683927229. You have received a new notification for Right to Erasure for the User Id: 2425654247 in the game(s) with Ids: 10539205763, 13260950955

Programınız, mesajınızı gizli olarak kodladığınızdan beri Roblox'un resmi kaynağından geldiğini tespit etmeyi sağlamalıdır. Ardından, talepilgili PII verilerini silmelidir.

Örnek Vücut

{
"embeds": [
{
"title": "RightToErasureRequest",
"description": "You have received a new notification for Right to Erasure for the User Id: 2425654247 in the game(s) with Ids: 10539205763, 13260950955",
"footer": {
"icon_url": "https://create.roblox.com/ashboard/ assets/ webhook/roblox_logo_metal.png",
"text": "Roblox-Signature: UIe6GJ78MHCmU/zUKBYP3LV0lAqwWRFR6UEfPt1xBFw=, Timestamp: 1683927229"
}
}
]
}