From d5b89f01d7e81f7f629ae7cced7bbbd46f60d581 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Mon, 2 Sep 2019 15:21:26 +0200
Subject: [PATCH] See #890: added shortcuts for setting moderation policies
 directly when handling reports

---
 api/funkwhale_api/manage/filters.py           |  7 ++
 .../manage/moderation/InstancePolicyModal.vue | 99 +++++++++++++++++++
 .../manage/moderation/ReportCard.vue          | 10 +-
 front/src/components/semantic/Modal.vue       |  2 +
 4 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 front/src/components/manage/moderation/InstancePolicyModal.vue

diff --git a/api/funkwhale_api/manage/filters.py b/api/funkwhale_api/manage/filters.py
index de9758d28..5791afba3 100644
--- a/api/funkwhale_api/manage/filters.py
+++ b/api/funkwhale_api/manage/filters.py
@@ -325,6 +325,10 @@ class ManageInstancePolicyFilterSet(filters.FilterSet):
         ]
     )
 
+    target_domain = filters.CharFilter("target_domain__name")
+    target_account_domain = filters.CharFilter("target_actor__domain__name")
+    target_account_username = filters.CharFilter("target_actor__preferred_username")
+
     class Meta:
         model = moderation_models.InstancePolicy
         fields = [
@@ -333,6 +337,9 @@ class ManageInstancePolicyFilterSet(filters.FilterSet):
             "silence_activity",
             "silence_notifications",
             "reject_media",
+            "target_domain",
+            "target_account_domain",
+            "target_account_username",
         ]
 
 
diff --git a/front/src/components/manage/moderation/InstancePolicyModal.vue b/front/src/components/manage/moderation/InstancePolicyModal.vue
new file mode 100644
index 000000000..d905a1d8c
--- /dev/null
+++ b/front/src/components/manage/moderation/InstancePolicyModal.vue
@@ -0,0 +1,99 @@
+<template>
+  <button class="ui button" @click.prevent="show = !show">
+    <i class="shield icon"></i>&nbsp;
+    <slot>
+      <translate translate-context="Content/Moderation/Button.Label">Moderation rules…</translate>
+    </slot>
+    <modal :show.sync="show" @show="fetchData">
+      <div class="header">
+        <translate :translate-params="{obj: target}" translate-context="Popup/Moderation/Title/Verb">Manage moderation rules for %{ obj }</translate>
+      </div>
+      <div class="content">
+        <div class="description">
+          <div v-if="isLoading" class="ui active loader"></div>
+          <instance-policy-card v-else-if="obj && !showForm" :object="obj" @update="showForm = true">
+            <header class="ui header">
+              <h3>
+                <translate translate-context="Content/Moderation/Card.Title">This entity is subject to specific moderation rules</translate>
+              </h3>
+            </header>
+            </instance-policy-card>
+            <instance-policy-form
+              v-else
+              @cancel="showForm = false"
+              @save="showForm = false; result = {count: 1, results: [$event]}"
+              @delete="result = {count: 0, results: []}; showForm = false"
+              :object="obj"
+              :type="type"
+              :target="target" />
+        </div>
+        <div class="ui hidden divider"></div>
+        <div class="ui hidden divider"></div>
+      </div>
+      <div class="actions">
+        <div class="ui deny button">
+          <translate translate-context="*/*/Button.Label/Verb">Close</translate>
+        </div>
+      </div>
+    </modal>
+
+  </button>
+</template>
+
+<script>
+import axios from 'axios'
+import InstancePolicyForm from "@/components/manage/moderation/InstancePolicyForm"
+import InstancePolicyCard from "@/components/manage/moderation/InstancePolicyCard"
+import Modal from '@/components/semantic/Modal'
+
+export default {
+  props: {
+    target: {required: true},
+    type: {required: true},
+  },
+  components: {
+    InstancePolicyForm,
+    InstancePolicyCard,
+    Modal,
+  },
+  data () {
+    return {
+      show: false,
+      isLoading: false,
+      errors: [],
+      showForm: false,
+      result: null,
+    }
+  },
+  computed: {
+    obj () {
+      if (!this.result) {
+        return null
+      }
+      return this.result.results[0]
+    }
+  },
+  methods: {
+    fetchData () {
+      let params = {}
+      if (this.type === 'domain') {
+        params.target_domain = this.target
+      }
+      if (this.type === 'actor') {
+        let parts = this.target.split('@')
+        params.target_account_username = parts[0]
+        params.target_account_domain = parts[1]
+      }
+      let self = this
+      self.isLoading = true
+      axios.get('/manage/moderation/instance-policies/', {params: params}).then((response) => {
+        self.result = response.data
+        self.isLoading = false
+      }, error => {
+        self.isLoading = false
+        self.errors = error.backendErrors
+      })
+    }
+  }
+}
+</script>
diff --git a/front/src/components/manage/moderation/ReportCard.vue b/front/src/components/manage/moderation/ReportCard.vue
index d6beec400..6bc2ce86f 100644
--- a/front/src/components/manage/moderation/ReportCard.vue
+++ b/front/src/components/manage/moderation/ReportCard.vue
@@ -135,13 +135,16 @@
                   <translate translate-context="*/*/*">{{ configs[target.type].label }}</translate>
                 </td>
               </tr>
-              <tr v-if="target && target.type !== 'account'">
+              <tr v-if="obj.target_owner && (!target || target.type !== 'account')">
                 <td>
                   <translate translate-context="*/*/*">Owner</translate>
                 </td>
                 <td>
                   <actor-link :admin="true" :actor="obj.target_owner"></actor-link>
                 </td>
+                <td>
+                  <instance-policy-modal class="basic" type="actor" :target="obj.target_owner.full_username" />
+                </td>
               </tr>
               <tr v-if="obj.target_state.is_local">
                 <td>
@@ -161,6 +164,9 @@
                 <td>
                   {{ obj.target_state.domain }}
                 </td>
+                <td>
+                  <instance-policy-modal class="basic" type="domain" :target="obj.target_state.domain" />
+                </td>
               </tr>
               <tr v-for="field in targetFields" :key="field.id">
                 <td>{{ field.label }}</td>
@@ -226,6 +232,7 @@ import { diffWordsWithSpace } from 'diff'
 import NoteForm from '@/components/manage/moderation/NoteForm'
 import NotesThread from '@/components/manage/moderation/NotesThread'
 import ReportCategoryDropdown from '@/components/moderation/ReportCategoryDropdown'
+import InstancePolicyModal from '@/components/manage/moderation/InstancePolicyModal'
 import entities from '@/entities'
 import {setUpdate} from '@/utils'
 import showdown from 'showdown'
@@ -247,6 +254,7 @@ export default {
     NoteForm,
     NotesThread,
     ReportCategoryDropdown,
+    InstancePolicyModal,
   },
   data () {
     return {
diff --git a/front/src/components/semantic/Modal.vue b/front/src/components/semantic/Modal.vue
index 076b3e466..c3af1524b 100644
--- a/front/src/components/semantic/Modal.vue
+++ b/front/src/components/semantic/Modal.vue
@@ -46,9 +46,11 @@ export default {
       handler (newValue) {
         if (newValue) {
           this.initModal()
+          this.$emit('show')
           this.control.modal('show')
         } else {
           if (this.control) {
+            this.$emit('hide')
             this.control.modal('hide')
             this.control.remove()
           }
-- 
GitLab