J’ai cherché, mais il semble qu’un point de terminaison d’API pour supprimer un téléversement n’existe pas.
Je publie ceci ici, car je n’ai trouvé aucune mention ou suggestion à ce sujet, le plus proche que j’ai trouvé était : API: a scope with access to /uploads
Dans les paramètres de portée granulaire de la clé API pour les téléversements, je vois que ‘create’ (créer) est disponible, mais ‘delete’ (supprimer) ne l’est pas.
Il semble qu’une solution de contournement potentielle pourrait être de créer une automatisation personnalisée et de la déclencher via l’API.
Selon votre configuration, les téléchargements étant une ressource partagée (référencée par des publications, le profil utilisateur, des badges, etc.), il est quelque peu risqué de les supprimer sans une diligence raisonnable appropriée.
De plus, ils sont automatiquement nettoyés après un court laps de temps s’ils ne sont référencés nulle part.
Le cas d’utilisation concerne la suppression des téléchargements nécessitant une intervention rapide dans le cadre de flux de travail d’automatisation avec intervention humaine, en utilisant activepieces, l’explorateur de données et l’API.
L’objectif est de permettre aux modérateurs réguliers d’avoir accès à un moyen simple de supprimer complètement et en toute confiance les téléchargements immédiatement, sans accès SSH, et de couvrir de manière exhaustive tous les cas connus de rupture des références de téléchargement, ainsi que de purger automatiquement le CDN des URL spécifiques (et dans le cas des avatars proxifiés, le préfixe d’URL basé sur le nom d’utilisateur).
J’ai été soulagé en testant de voir que les références aux avatars, aux arrière-plans de profil et aux arrière-plans de carte sont gérées automatiquement lorsqu’un téléchargement est détruit.
Les deux scénarios principaux seraient la « terre brûlée » et la « suppression chirurgicale ». Voici le travail en cours pour la terre brûlée :
Conversion en une liste de hachages de téléchargement :
URL d’avatar (extraire le nom d’utilisateur à l’aide d’une expression régulière) → obtenir le hachage de l’avatar via une requête d’explorateur de données (le hachage n’est pas dans l’URL)
URL de sujet/message → collecter tous les hachages de téléchargement utilisés dans ce message à l’aide de l’explorateur de données
URL de téléchargement originales/optimisées directes (y compris l’arrière-plan de profil et l’arrière-plan de carte) → extraire les hachages à l’aide d’une expression régulière
Ensuite, interroger chaque hachage pour trouver toutes les occurrences (une requête d’explorateur de données pour couvrir tous les cas, un seul hachage à la fois) :
liste de noms d’utilisateur/ID, pour les utilisateurs qui l’ont utilisé comme avatar
liste de noms d’utilisateur/ID, pour les utilisateurs qui l’ont utilisé comme arrière-plan de profil
liste de noms d’utilisateur/ID, pour les utilisateurs qui l’ont utilisé comme arrière-plan de carte
liste de tous les messages (bruts) qui utilisent ce téléchargement
Actions :
suspendre tous les utilisateurs qui ont utilisé le téléchargement pour un avatar, un arrière-plan de profil ou un arrière-plan de carte
suspendre tous les utilisateurs qui ont des messages faisant référence au téléchargement cible, mais exclure si leur référence est imbriquée dans une citation
supprimer tous les sujets
supprimer tous les messages
détruire le téléchargement (pas de point de terminaison API)
purger toutes les URL CDN (optimisées/non optimisées)
purger le préfixe standard pour les URL d’avatar proxifiées pour chaque nom d’utilisateur associé (pour couvrir toutes les tailles)
Le scénario de suppression chirurgicale serait essentiellement le même, mais sans suspendre les utilisateurs associés et nécessiterait quelques changements concernant la collecte de tous les hachages de téléchargement à partir des URL de messages/sujets.
Probablement toujours supprimer les messages/sujets eux-mêmes pour éviter les références cassées, mais supprimer le balisage de téléchargement pour ce téléchargement spécifique (sans toucher aux autres téléchargements) serait supérieur si possible. Comme cette automatisation si elle ne supprimait pas toutes les références de téléchargement en markdown.
Idéalement, j’aimerais pouvoir bloquer également les hachages, afin qu’après avoir parcouru ce qui précède, quelqu’un ne puisse pas simplement créer un nouveau compte et le télécharger à nouveau.
Je ne pense pas que ce soit possible actuellement pour un modérateur ordinaire, par exemple en utilisant des mots surveillés. Donc, peut-être qu’un balayage périodique comme celui ci-dessus pour une liste de hachages serait un moyen de gérer cela.
Il dispose de points de terminaison pour obtenir les téléchargements d’une publication et pour supprimer un téléchargement étant donné les identifiants de téléchargement et de publication.
Il étend également la fonctionnalité de recherche pour obtenir toutes les publications contenant un téléchargement spécifique, étant donné le hachage.
Je mets juste ce lien pour les utilisateurs qui liront et seront d’accord avec votre publication, ils pourraient être intéressés par voter pour ceci (je sais que vous l’avez déjà lu) :
Oui ! J’ai pratiquement versé des larmes de joie en voyant votre plugin plus tôt ce mois-ci haha. Un immense merci de l’avoir créé et partagé.
Quelques scénarios que je n’ai pas réussi à couvrir avec :
Utilisation du téléchargement : préfixe de recherche, il ne semblait pas possible de trouver les arrière-plans de profil ou les arrière-plans de carte (sauf si quelqu’un liait directement ces images dans une publication également).
Suppression définitive des images dans ce scénario (image sans association avec des publications).
Similaire pour l’Avatar, par exemple obtenir le hachage de l’avatar (il n’est généralement pas dans l’URL), puis trouver tout autre compte qui l’a peut-être également utilisé, si une suspension est nécessaire + supprimer le téléchargement sans association de publication.
Agréable à avoir :
Déclencher un webhook lors de la suppression, afin de déclencher des purges CDN après la suppression pour toutes les variantes des téléchargements.
Suppression en masse/automatique de toutes les publications/sujets qui font référence au téléchargement lorsque celui-ci est supprimé.
Dans Discourse (interface web), il semble impossible de supprimer (délier) un avatar d’utilisateur, que ce soit par un administrateur/modérateur ou par l’utilisateur lui-même (autre que télécharger un remplacement). C’est possible pour l’arrière-plan du profil et la bannière. Mais les deux ne détruisent pas immédiatement le téléchargement et si un autre utilisateur inconnu existe qui utilise le même téléchargement pour une partie de son profil (avatar, arrière-plan de profil, carte de profil), il ne sera pas purgé plus tard non plus.
J’ai fini par penser qu’il pourrait être utile d’essayer de créer des flux de travail automatisés capables de gérer la majorité ou la totalité du processus (avec examen/approbation humaine et/ou entrée humaine simplifiée). Pour faciliter une application cohérente, couvrir les cas limites et idéalement minimiser la possibilité d’avoir des publications non supprimées avec des références de téléchargement mortes. Également suspension automatique si nécessaire (sauf si le téléchargement cible se trouve à l’intérieur d’une citation) et purge CDN.
Voici ce que j’avais jusqu’à présent pour les requêtes d’explorateur de données (pas encore à l’étape de les « coller ensemble »), avec l’objectif de couvrir :
URL de sujet
URL de publication
URL d’image directe (publications, arrière-plan de profil, arrière-plan de carte)
URL d’avatar (proxifiées)
Préparer la liste des hachages de téléchargement
nom_utilisateur (à partir de l’URL d’avatar proxifiée) vers hachage de téléchargement
-- [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 de publication/sujet vers liste de hachages de téléchargement
-- [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'
Les autres types d’URL de téléchargement dont je suis au courant ont le hachage dans l’URL elle-même (il n’est pas nécessaire d’utiliser l’explorateur de données pour obtenir ces hachages).
Rassembler et préparer toutes les informations exploitables sur un hachage de téléchargement
-- [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
Ne couvre pas : les sujets en file d’attente d’examen en attente ou les brouillons de publications
Suspendre un utilisateur (pour les publications, on peut utiliser le contenu brut dans post_details pour exclure conditionnellement les utilisateurs si le markdown du téléchargement est dans une citation)
Suppression du téléchargement (API n’existe pas actuellement)
Et pour des actions supplémentaires :
Purger toutes les URL CDN (toutes les variantes, optimisées et originales, etc.)
Purger les URL de préfixe des avatars proxifiés (pour couvrir toutes les tailles)
Géré automatiquement par Discourse :
Suppression de la référence de téléchargement de tous les profils utilisateur (avatar, arrière-plan de profil et arrière-plan de carte) immédiatement lorsqu’un téléchargement est détruit/supprimé.