اعتمادًا على التكوين الخاص بك، فإن التحميلات التي هي مورد مشترك (يُشار إليها بواسطة المنشورات، وملف تعريف المستخدم، والشارات، وما إلى ذلك…) تشكل خطورة إلى حد ما عند حذفها دون بذل العناية الواجبة المناسبة.
بالإضافة إلى ذلك، يتم تنظيفها تلقائيًا بعد فترة قصيرة إذا لم تتم الإشارة إليها في أي مكان.
يتمثل الاستخدام في الإزالة الحرجة زمنيًا لعمليات التحميل كجزء من سير عمل الأتمتة البشرية في الحلقة باستخدام activepieces ومستكشف البيانات وواجهة برمجة التطبيقات (API).
الهدف هو تمكين المشرفين العاديين من الوصول إلى طريقة بسيطة لإزالة عمليات التحميل بالكامل وبثقة على الفور دون الحاجة إلى الوصول عبر SSH، وتغطية شاملة لجميع الحالات المعروفة لكسر مراجع التحميل، بالإضافة إلى مسح ذاكرة التخزين المؤقت لشبكة توصيل المحتوى (CDN) تلقائيًا لعنوان URL المحدد (وفي حالة الصورة الرمزية التي يتم تمريرها عبر وكيل، بادئة عنوان URL بناءً على اسم المستخدم).
لقد شعرت بالارتياح عند الاختبار، لرؤية أنه تتم معالجة مراجع الصور الرمزية وخلفية الملف الشخصي وخلفية البطاقة تلقائيًا عند تدمير عملية تحميل.
السيناريوهان الرئيسيان سيكونان “الأرض المحروقة” و"الإزالة الجراحية". هذا هو العمل الجاري للأرض المحروقة:
التحويل إلى قائمة تجزئة (هاش) لعمليات التحميل:
عناوين URL للصور الرمزية (استخراج اسم المستخدم باستخدام التعبير العادي) ← الحصول على تجزئة الصورة الرمزية عبر استعلام مستكشف البيانات (التجزئة ليست في عنوان URL)
عناوين URL للمواضيع/المنشورات ← جمع جميع تجزئات التحميل المستخدمة في هذا المنشور باستخدام مستكشف البيانات
عناوين URL مباشرة للتحميل الأصلي/المُحسَّن (بما في ذلك خلفية الملف الشخصي وخلفية البطاقة) ← استخراج التجزئات باستخدام التعبير العادي
ثم الاستعلام عن كل تجزئة للعثور على جميع التكرارات (استعلام واحد لمستكشف البيانات لتغطية جميع الحالات، تجزئة واحدة في كل مرة):
قائمة بأسماء المستخدمين/المعرفات، للمستخدمين الذين استخدموها كصورة رمزية
قائمة بأسماء المستخدمين/المعرفات، للمستخدمين الذين استخدموها كخلفية للملف الشخصي
قائمة بأسماء المستخدمين/المعرفات، للمستخدمين الذين استخدموها كخلفية للبطاقة
قائمة بجميع المنشورات (الخام) التي تستخدم هذا التحميل
الإجراءات:
تعليق جميع المستخدمين الذين استخدموا التحميل كصورة رمزية أو خلفية للملف الشخصي أو خلفية للبطاقة
تعليق جميع المستخدمين الذين لديهم منشورات تشير إلى التحميل المستهدف، ولكن استبعادهم إذا كان مرجعهم متداخلاً داخل اقتباس
حذف جميع المواضيع
حذف جميع المنشورات
تدمير التحميل (لا يوجد نقطة نهاية لواجهة برمجة التطبيقات)
مسح جميع عناوين URL لشبكة CDN (المُحسَّنة/غير المُحسَّنة)
مسح البادئة القياسية لعناوين URL للصور الرمزية التي يتم تمريرها عبر وكيل لكل اسم مستخدم مرتبط (لتغطية جميع الأحجام)
سيناريو الإزالة الجراحية سيكون هو نفسه تقريبًا، ولكن دون تعليق المستخدمين المرتبطين ويتطلب بعض التغييرات فيما يتعلق بجمع جميع تجزئات التحميل من عناوين URL للمنشورات/المواضيع.
من المحتمل أن يظل حذف المنشورات/المواضيع نفسها لتجنب المراجع المكسورة، ولكن إزالة تنسيق علامات التحميل الخاصة بعملية التحميل المحددة تلك (دون المساس بعمليات التحميل الأخرى) سيكون أفضل إذا كان ذلك ممكنًا. مثل هذه الأتمتة لو أنها لم تقم بإزالة جميع مراجع تحميل علامات التنسيق.
من الناحية المثالية، أود أن أكون قادرًا على حظر التجزئات أيضًا، بحيث بعد المرور بما سبق، لا يتمكن شخص ما من إنشاء حساب جديد وإعادة التحميل ببساطة.
لا أعتقد أن هذا ممكن حاليًا لمشرف عادي، مثل استخدام الكلمات المراقبة. لذا ربما يكون إجراء فحص دوري مثل المذكور أعلاه لقائمة التجزئات طريقة للتعامل مع ذلك.
نعم! لقد ذرفت تقريبًا دموع الفرح عندما رأيت الإضافة الخاصة بك في وقت سابق من هذا الشهر ههه. شكرًا جزيلاً لك على صنعها ومشاركتها.
بعض السيناريوهات التي لم أجد طريقة لتغطيتها بها:
استخدام البادئة البحثية للتحميل: لم يبدُ أنه من الممكن العثور على خلفيات الملف الشخصي أو خلفيات البطاقات (إلا إذا قام شخص ما بربط تلك الصور مباشرة في منشور أيضًا).
الحذف الصارم للصور في هذا السيناريو (صورة بدون ارتباط بالمنشورات).
شيء مماثل للصورة الرمزية (Avatar) على سبيل المثال، الحصول على تجزئة الصورة الرمزية (عادةً لا تكون في عنوان URL)، ثم العثور على أي حسابات أخرى ربما استخدمتها أيضًا، إذا كانت هناك حاجة إلى تعليق (suspension) + حذف التحميل بدون ارتباط بمنشور.
أمور لطيفة:
تشغيل خطاف ويب (webhook) عند الحذف، لتشغيل مسح ذاكرة التخزين المؤقت لشبكة توصيل المحتوى (CDN) بعد الحذف لجميع متغيرات التحميلات.
الحذف المجمع/التلقائي لجميع المنشورات/المواضيع التي تحتوي على مرجع تحميل عند حذف التحميل.
في ديسكورس (واجهة الويب)، لا يبدو أنه من الممكن حذف (إلغاء ربط) الصورة الرمزية للمستخدم، سواء من قبل مسؤول/مشرف أو المستخدم نفسه (بخلاف تحميل بديل). هذا ممكن لخلفية الملف الشخصي والخلفية. لكن كلاهما لا يدمر التحميل فورًا، وإذا كان هناك مستخدم آخر غير معروف يستخدم نفس التحميل لجزء من ملفه الشخصي (صورة رمزية، خلفية ملف شخصي، بطاقة ملف شخصي) فلن يتم مسحها لاحقًا أيضًا.
انتهى بي الأمر إلى الاعتقاد بأنه قد يكون من المفيد محاولة إنشاء بعض سير العمل الآلي التي يمكنها التعامل مع معظم العملية أو كلها (مع مراجعة/موافقة بشرية و/أو مدخلات بشرية مبسطة). لجعل تطبيقها أسهل باستمرار، وتغطية الحالات الطرفية، وتقليل احتمالية وجود منشورات غير محذوفة تحتوي على مراجع تحميل ميتة. وأيضًا التعليق التلقائي إذا لزم الأمر (ما لم يكن التحميل المستهدف داخل اقتباس) ومسح ذاكرة التخزين المؤقت لشبكة توصيل المحتوى.
هذا ما توصلت إليه حتى الآن لاستعلامات مستكشف البيانات (لم أصل بعد إلى مرحلة “ربطها معًا”)، بهدف التغطية:
عناوين URL للصور الرمزية (المُعاد توجيهها عبر وكيل)
إعداد قائمة تجزئات التحميل (Upload Hashes List)
اسم المستخدم (من عنوان URL للصورة الرمزية المُعاد توجيهها) إلى تجزئة التحميل
-- [params]
-- user_id :username
SELECT
up.sha1 AS upload_hash
FROM
users u
JOIN uploads up ON up.id = u.uploaded_avatar_id
WHERE
u.id = :username
عنوان URL للمنشور/الموضوع إلى قائمة تجزئات التحميل
-- [params]
-- post_id :post_url
SELECT
COALESCE(json_agg(up.sha1), '[]'::json) AS upload_hashes
FROM
upload_references ur
JOIN uploads up ON up.id = ur.upload_id
WHERE
ur.target_id = :post_url
AND ur.target_type = 'Post'
أنواع عناوين URL للتحميل الأخرى التي أعرفها، تحتوي على التجزئة في عنوان URL نفسه (لا تحتاج إلى استخدام مستكشف البيانات للحصول على تلك التجزئات).
جمع وإعداد جميع المعلومات القابلة للتنفيذ حول تجزئة تحميل معينة
-- [params]
-- string :upload_hash
-- string :upload_schemeless_prefix
-- string :cdn_url_prefix
-- string :app_hostname
WITH target_uploads AS (
SELECT
id,
url,
user_id
FROM
uploads
WHERE
sha1 = :upload_hash
),
all_urls AS (
SELECT
url
FROM
target_uploads
UNION
SELECT
url
FROM
optimized_images
WHERE
upload_id IN (
SELECT
id
FROM
target_uploads)
),
post_data AS (
SELECT
p.id AS post_id,
p.topic_id,
u.id AS user_id,
u.username AS author,
p.created_at,
CASE WHEN p.post_number = 1 THEN
TRUE
ELSE
FALSE
END AS is_topic_starter,
CASE WHEN t.archetype = 'private_message' THEN
TRUE
ELSE
FALSE
END AS is_dm,
p.raw
FROM
upload_references ur
JOIN posts p ON p.id = ur.target_id
AND ur.target_type = 'Post'
JOIN topics t ON t.id = p.topic_id
JOIN users u ON u.id = p.user_id
WHERE
ur.upload_id IN (
SELECT
id
FROM
target_uploads)
AND p.deleted_at IS NULL
)
SELECT
(
SELECT
COALESCE(json_agg(id), '[]'::json)
FROM
target_uploads) AS upload_ids,
(
SELECT
COALESCE(json_agg(url), '[]'::json)
FROM
all_urls) AS upload_s3_schemeless_urls,
(
SELECT
COALESCE(json_agg(
CASE WHEN url LIKE '//%' THEN
REPLACE(url, :upload_schemeless_prefix, :cdn_url_prefix)
ELSE
:cdn_url_prefix || url
END), '[]'::json)
FROM
all_urls) AS upload_cdn_urls,
(
SELECT
COALESCE(json_agg(json_build_object('user_id', id, 'username', username)), '[]'::json)
FROM
users
WHERE
uploaded_avatar_id IN (
SELECT
id
FROM
target_uploads)) AS avatar_users,
(
SELECT
COALESCE(json_agg('https://' || :app_hostname || '/user_avatar/' || :app_hostname || '/' || username || '/'), '[]'::json)
FROM
users
WHERE
uploaded_avatar_id IN (
SELECT
id
FROM
target_uploads)) AS avatar_proxied_url_prefixes,
(
SELECT
COALESCE(json_agg(json_build_object('user_id', u.id, 'username', u.username)), '[]'::json)
FROM
user_profiles up
JOIN users u ON u.id = up.user_id
WHERE
up.profile_background_upload_id IN (
SELECT
id
FROM
target_uploads)) AS profile_background_users,
(
SELECT
COALESCE(json_agg(json_build_object('user_id', u.id, 'username', u.username)), '[]'::json)
FROM
user_profiles up
JOIN users u ON u.id = up.user_id
WHERE
up.card_background_upload_id IN (
SELECT
id
FROM
target_uploads)) AS card_background_users,
(
SELECT
COALESCE(json_agg(pd.topic_id), '[]'::json)
FROM
post_data pd
WHERE
pd.is_topic_starter = TRUE) AS topic_ids,
(
SELECT
COALESCE(json_agg(pd.post_id), '[]'::json)
FROM
post_data pd
WHERE
pd.is_topic_starter = FALSE) AS post_ids,
(
SELECT
COALESCE(json_agg(json_build_object('post_id', pd.post_id, 'topic_id', pd.topic_id, 'user_id', pd.user_id, 'author', pd.author, 'created_at', pd.created_at, 'is_topic_starter', pd.is_topic_starter, 'is_dm', pd.is_dm, 'raw', pd.raw)), '[]'::json)
FROM
post_data pd) AS post_details
لا يغطي: المواضيع/المنشورات المعلقة في قائمة المراجعة أو المسودات
المخرجات:
upload_ids (يجب أن يكون واحدًا فقط)
upload_s3_schemeless_urls
upload_cdn_urls
avatar_users
avatar_proxied_url_prefixes
profile_background_users
card_background_users
topic_ids
post_ids
post_details
سيوفر هذا المعلومات المطلوبة لاستخدام واجهات برمجة التطبيقات هذه بشكل انتقائي: