diff --git a/api/custom/quarantine.go b/api/custom/quarantine.go index 459e59fb0640db4ce8364cca3183268c4d19b057..4922cf9304592d77b65c7d65d14fad53284c21ee 100644 --- a/api/custom/quarantine.go +++ b/api/custom/quarantine.go @@ -117,6 +117,45 @@ func QuarantineUserMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) return &api.DoNotCacheResponse{Payload: &MediaQuarantinedResponse{NumQuarantined: total}} } +func QuarantineDomainMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { + canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user) + if !canQuarantine { + return api.AuthFailed() + } + + params := mux.Vars(r) + + serverName := params["serverName"] + + log = log.WithFields(logrus.Fields{ + "serverName": serverName, + "localAdmin": isLocalAdmin, + }) + + if !allowOtherHosts && serverName != r.Host { + return api.AuthFailed() + } + + db := storage.GetDatabase().GetMediaStore(r.Context(), log) + userMedia, err := db.GetAllMediaForServer(serverName) + if err != nil { + log.Error("Error while listing media for the server: " + err.Error()) + return api.InternalServerError("error retrieving media for server") + } + + total := 0 + for _, media := range userMedia { + resp, ok := doQuarantineOn(media, allowOtherHosts, log, r.Context()) + if !ok { + return resp + } + + total += resp.(*MediaQuarantinedResponse).NumQuarantined + } + + return &api.DoNotCacheResponse{Payload: &MediaQuarantinedResponse{NumQuarantined: total}} +} + func QuarantineMedia(r *http.Request, log *logrus.Entry, user api.UserInfo) interface{} { canQuarantine, allowOtherHosts, isLocalAdmin := getQuarantineRequestInfo(r, log, user) if !canQuarantine { diff --git a/api/webserver/webserver.go b/api/webserver/webserver.go index 724cb383ae8eb540d94b16fa70eb0c010f95a1b5..570c18cdf0cffaf472780e8fbb1224b93685d6f1 100644 --- a/api/webserver/webserver.go +++ b/api/webserver/webserver.go @@ -41,6 +41,7 @@ func Init() { quarantineHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineMedia), "quarantine_media", counter, false} quarantineRoomHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineRoomMedia), "quarantine_room", counter, false} quarantineUserHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineUserMedia), "quarantine_user", counter, false} + quarantineDomainHandler := handler{api.AccessTokenRequiredRoute(custom.QuarantineDomainMedia), "quarantine_domain", counter, false} localCopyHandler := handler{api.AccessTokenRequiredRoute(unstable.LocalCopy), "local_copy", counter, false} infoHandler := handler{api.AccessTokenRequiredRoute(unstable.MediaInfo), "info", counter, false} configHandler := handler{api.AccessTokenRequiredRoute(r0.PublicConfig), "config", counter, false} @@ -91,6 +92,7 @@ func Init() { routes["/_matrix/media/"+version+"/admin/quarantine/{server:[a-zA-Z0-9.:\\-_]+}/{mediaId:[a-zA-Z0-9.\\-_]+}"] = route{"POST", quarantineHandler} routes["/_matrix/media/"+version+"/admin/quarantine/room/{roomId:[^/]+}"] = route{"POST", quarantineRoomHandler} routes["/_matrix/media/"+version+"/admin/quarantine/user/{userId:[^/]+}"] = route{"POST", quarantineUserHandler} + routes["/_matrix/media/"+version+"/admin/quarantine/server/{serverName:[^/]+}"] = route{"POST", quarantineDomainHandler} routes["/_matrix/media/"+version+"/admin/datastores/{datastoreId:[^/]+}/size_estimate"] = route{"GET", storageEstimateHandler} routes["/_matrix/media/"+version+"/admin/datastores"] = route{"GET", datastoreListHandler} routes["/_matrix/media/"+version+"/admin/datastores/{sourceDsId:[^/]+}/transfer_to/{targetDsId:[^/]+}"] = route{"POST", dsTransferHandler} diff --git a/docs/admin.md b/docs/admin.md index aad4fbf70cb9af6f8f6ef1745bd2a5f5a275565b..a00bf4774ca4e8ba1773e4ee3336f3472d3453a9 100644 --- a/docs/admin.md +++ b/docs/admin.md @@ -80,6 +80,12 @@ URL: `POST /_matrix/media/unstable/admin/quarantine/room/<room id>?access_token= URL: `POST /_matrix/media/unstable/admin/quarantine/user/<user id>?access_token=your_access_token` +#### Quarantine a whole server's worth of media + +URL: `POST /_matrix/media/unstable/admin/quarantine/server/<server name>?access_token=your_access_token` + +Note that this will only quarantine what is currently known to the repo. It will not flag the domain for future quarantines. + ## Datastore management Datastores are used by the media repository to put files. Typically these match what is configured in the config file, such as s3 and directories.