From 5637b47ac47a26261dd8aa3790da7365920a31ac Mon Sep 17 00:00:00 2001
From: Travis Ralston <travpc@gmail.com>
Date: Sat, 20 Jan 2018 21:52:32 -0700
Subject: [PATCH] Document quarantine API and quarantine media with the same
 hash

It's a bit non-sensical to leave media with the same hash unquarantined.
---
 docs/admin.md                                 | 12 ++++++++++
 .../matrix-media-repo/client/r0/quarantine.go |  2 +-
 .../services/media_service/media_service.go   | 22 +++++++++++++++++--
 3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/docs/admin.md b/docs/admin.md
index 53bb84b7..281ee404 100644
--- a/docs/admin.md
+++ b/docs/admin.md
@@ -9,3 +9,15 @@ URL: `POST /_matrix/media/r0/admin/purge_remote?before_ts=1234567890&access_toke
 This will delete remote media from the file store that was downloaded before the timestamp specified. If the file is referenced by newer remote media or local files to any of the configured homeservers, it will not be deleted. Be aware that removing a homeserver from the config will cause it to be considered a remote server, and therefore the media may be deleted.
 
 Any remote media that is deleted and requested by a user will be downloaded again.
+
+## Quarantine media
+
+URL: `POST /_matrix/media/r0/admin/quarantine/<server>/<media id>?access_token=your_access_token`
+
+The `<server>` and `<media id>` can be retrieved from an MXC URI (`mxc://<server>/<media id>`).
+
+The quarantine media API allows administrators to quarantine media that may not be appropriate for their server. Using this API will prevent the media from being downloaded any further. It will *not* delete the file from your storage though: that is a task left for the administrator.
+
+Remote media that has been quarantined will not be purged either. This is so that the media remains flagged as quarantined. It is safe to delete the file on your disk, but not delete the media from the database.
+
+Quarantining media will also quarantine any media with the same file hash.
diff --git a/src/github.com/turt2live/matrix-media-repo/client/r0/quarantine.go b/src/github.com/turt2live/matrix-media-repo/client/r0/quarantine.go
index 630fc22b..d3dc774d 100644
--- a/src/github.com/turt2live/matrix-media-repo/client/r0/quarantine.go
+++ b/src/github.com/turt2live/matrix-media-repo/client/r0/quarantine.go
@@ -49,7 +49,7 @@ func QuarantineMedia(w http.ResponseWriter, r *http.Request, log *logrus.Entry)
 		return client.BadRequest("media not found or other error encountered - see logs")
 	}
 
-	err = mediaSvc.SetMediaQuarantined(media, true)
+	err = mediaSvc.SetMediaQuarantined(media, true, isAdmin)
 	if err != nil {
 		log.Error("Error quarantining media: " + err.Error())
 		return client.InternalServerError("Error quarantining media")
diff --git a/src/github.com/turt2live/matrix-media-repo/services/media_service/media_service.go b/src/github.com/turt2live/matrix-media-repo/services/media_service/media_service.go
index 03c449b2..42b99be0 100644
--- a/src/github.com/turt2live/matrix-media-repo/services/media_service/media_service.go
+++ b/src/github.com/turt2live/matrix-media-repo/services/media_service/media_service.go
@@ -63,13 +63,31 @@ func (s *mediaService) IsTooLarge(contentLength int64, contentLengthHeader strin
 	return false // We can only assume
 }
 
-func (s *mediaService) SetMediaQuarantined(media *types.Media, isQuarantined bool) (error) {
+func (s *mediaService) SetMediaQuarantined(media *types.Media, isQuarantined bool, allowOtherHosts bool) (error) {
 	err := s.store.SetQuarantined(media.Origin, media.MediaId, isQuarantined)
 	if err != nil {
 		return err
 	}
-
 	s.log.Warn("Media has been quarantined: " + media.Origin + "/" + media.MediaId)
+
+	// Quarantine other media with the same hash
+	otherMedia, err := s.store.GetByHash(media.Sha256Hash)
+	if err != nil {
+		return err
+	}
+	for _, m := range otherMedia {
+		if m.Origin != media.Origin && !allowOtherHosts {
+			s.log.Warn("Skipping quarantine on " + m.Origin + "/" + m.MediaId + " because it is on a different host from " + media.Origin + "/" + media.MediaId)
+			continue
+		}
+
+		err := s.store.SetQuarantined(m.Origin, m.MediaId, isQuarantined)
+		if err != nil {
+			return err
+		}
+		s.log.Warn("Media has been quarantined: " + m.Origin + "/" + m.MediaId)
+	}
+
 	return nil
 }
 
-- 
GitLab