implement cinder reporting (#21218)
This commit is contained in:
Родитель
0fe855a03c
Коммит
e36dfd1f6b
|
@ -0,0 +1,127 @@
|
|||
from django.conf import settings
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class Cinder:
|
||||
QUEUE = 'amo-content-infringement'
|
||||
type = None # Needs to be defined by subclasses
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
# Ideally override this in subclasses to be more efficient
|
||||
return str(self.get_attributes().get('id', ''))
|
||||
|
||||
def get_attributes(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_context(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_entity_data(self):
|
||||
return {'entity_type': self.type, 'attributes': self.get_attributes()}
|
||||
|
||||
def get_relationship_data(self, to, relationship_type):
|
||||
return {
|
||||
'source_id': self.id,
|
||||
'source_type': self.type,
|
||||
'target_id': to.id,
|
||||
'target_type': to.type,
|
||||
'relationship_type': relationship_type,
|
||||
}
|
||||
|
||||
def build_report_payload(self, reason, reporter):
|
||||
context = self.get_context()
|
||||
if reporter:
|
||||
context['entities'] += [reporter.get_entity_data()]
|
||||
context['relationships'] += [
|
||||
reporter.get_relationship_data(self, 'amo_reporter_of')
|
||||
]
|
||||
return {
|
||||
'queue_slug': self.QUEUE,
|
||||
'entity_type': self.type,
|
||||
'entity': self.get_attributes(),
|
||||
'reasoning': reason,
|
||||
# 'report_metadata': ??
|
||||
'context': context,
|
||||
}
|
||||
|
||||
def report(self, reason, reporter_user):
|
||||
if self.type is None:
|
||||
# type needs to be defined by subclasses
|
||||
raise NotImplementedError
|
||||
reporter = (
|
||||
reporter_user
|
||||
and not reporter_user.is_anonymous()
|
||||
and CinderUser(reporter_user)
|
||||
)
|
||||
url = f'{settings.CINDER_SERVER_URL}create_report'
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'content-type': 'application/json',
|
||||
'authorization': f'Bearer {settings.CINDER_API_TOKEN}',
|
||||
}
|
||||
data = self.build_report_payload(reason, reporter)
|
||||
print(data)
|
||||
response = requests.post(url, json=data, headers=headers)
|
||||
if response.status_code == 201:
|
||||
return response.json().get('job_id')
|
||||
else:
|
||||
raise ConnectionError(response.content)
|
||||
|
||||
|
||||
class CinderUser(Cinder):
|
||||
type = 'amo_user'
|
||||
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return str(self.user.id)
|
||||
|
||||
def get_attributes(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.user.display_name,
|
||||
'email': self.user.email,
|
||||
'fxa_id': self.user.fxa_id,
|
||||
}
|
||||
|
||||
def get_context(self):
|
||||
addons = [CinderAddon(addon) for addon in self.user.addons.all()]
|
||||
return {
|
||||
'entities': [addon.get_entity_data() for addon in addons],
|
||||
'relationships': [
|
||||
self.get_relationship_data(addon, 'amo_author_of') for addon in addons
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
class CinderAddon(Cinder):
|
||||
type = 'amo_addon'
|
||||
|
||||
def __init__(self, addon):
|
||||
self.addon = addon
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return str(self.addon.id)
|
||||
|
||||
def get_attributes(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'guid': self.addon.guid,
|
||||
'slug': self.addon.slug,
|
||||
'name': str(self.addon.name),
|
||||
}
|
||||
|
||||
def get_context(self):
|
||||
authors = [CinderUser(author) for author in self.addon.authors.all()]
|
||||
return {
|
||||
'entities': [author.get_entity_data() for author in authors],
|
||||
'relationships': [
|
||||
author.get_relationship_data(self, 'amo_author_of')
|
||||
for author in authors
|
||||
],
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
from olympia.amo.tests import TestCase, addon_factory, user_factory
|
||||
|
||||
from ..cinder import CinderAddon, CinderUser
|
||||
|
||||
|
||||
class TestCinderAddon(TestCase):
|
||||
def test_build_report_payload(self):
|
||||
addon = addon_factory()
|
||||
reason = 'bad addon!'
|
||||
cinder_addon = CinderAddon(addon)
|
||||
|
||||
data = cinder_addon.build_report_payload(reason, None)
|
||||
assert data == {
|
||||
'queue_slug': 'amo-content-infringement',
|
||||
'entity_type': 'amo_addon',
|
||||
'entity': {
|
||||
'id': str(addon.id),
|
||||
'guid': addon.guid,
|
||||
'slug': addon.slug,
|
||||
'name': str(addon.name),
|
||||
},
|
||||
'reasoning': reason,
|
||||
'context': {'entities': [], 'relationships': []},
|
||||
}
|
||||
|
||||
# and if the reporter isn't anonymous
|
||||
reporter_user = user_factory()
|
||||
data = cinder_addon.build_report_payload(reason, CinderUser(reporter_user))
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(reporter_user.id),
|
||||
'name': reporter_user.display_name,
|
||||
'email': reporter_user.email,
|
||||
'fxa_id': reporter_user.fxa_id,
|
||||
},
|
||||
}
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(reporter_user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_reporter_of',
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
def test_build_report_payload_with_author(self):
|
||||
author = user_factory()
|
||||
addon = addon_factory(users=[author])
|
||||
reason = 'bad addon!'
|
||||
cinder_addon = CinderAddon(addon)
|
||||
|
||||
data = cinder_addon.build_report_payload(reason, None)
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(author.id),
|
||||
'name': author.display_name,
|
||||
'email': author.email,
|
||||
'fxa_id': author.fxa_id,
|
||||
},
|
||||
}
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(author.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_author_of',
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
# and if the reporter isn't anonymous
|
||||
reporter_user = user_factory()
|
||||
data = cinder_addon.build_report_payload(reason, CinderUser(reporter_user))
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(author.id),
|
||||
'name': author.display_name,
|
||||
'email': author.email,
|
||||
'fxa_id': author.fxa_id,
|
||||
},
|
||||
},
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(reporter_user.id),
|
||||
'name': reporter_user.display_name,
|
||||
'email': reporter_user.email,
|
||||
'fxa_id': reporter_user.fxa_id,
|
||||
},
|
||||
},
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(author.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_author_of',
|
||||
},
|
||||
{
|
||||
'source_id': str(reporter_user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_reporter_of',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
class TestCinderUser(TestCase):
|
||||
def test_build_report_payload(self):
|
||||
user = user_factory()
|
||||
reason = 'bad person!'
|
||||
cinder_user = CinderUser(user)
|
||||
|
||||
data = cinder_user.build_report_payload(reason, None)
|
||||
assert data == {
|
||||
'queue_slug': 'amo-content-infringement',
|
||||
'entity_type': 'amo_user',
|
||||
'entity': {
|
||||
'id': str(user.id),
|
||||
'name': user.display_name,
|
||||
'email': user.email,
|
||||
'fxa_id': user.fxa_id,
|
||||
},
|
||||
'reasoning': reason,
|
||||
'context': {'entities': [], 'relationships': []},
|
||||
}
|
||||
# and if the reporter isn't anonymous
|
||||
reporter_user = user_factory()
|
||||
data = cinder_user.build_report_payload(reason, CinderUser(reporter_user))
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(reporter_user.id),
|
||||
'name': reporter_user.display_name,
|
||||
'email': reporter_user.email,
|
||||
'fxa_id': reporter_user.fxa_id,
|
||||
},
|
||||
}
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(reporter_user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(user.id),
|
||||
'target_type': 'amo_user',
|
||||
'relationship_type': 'amo_reporter_of',
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
def test_build_report_payload_addon_author(self):
|
||||
user = user_factory()
|
||||
addon = addon_factory(users=[user])
|
||||
cinder_user = CinderUser(user)
|
||||
reason = 'bad person!'
|
||||
|
||||
data = cinder_user.build_report_payload(reason, None)
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_addon',
|
||||
'attributes': {
|
||||
'id': str(addon.id),
|
||||
'guid': addon.guid,
|
||||
'slug': addon.slug,
|
||||
'name': str(addon.name),
|
||||
},
|
||||
}
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_author_of',
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
# and if the reporter isn't anonymous
|
||||
reporter_user = user_factory()
|
||||
data = cinder_user.build_report_payload(reason, CinderUser(reporter_user))
|
||||
assert data['context'] == {
|
||||
'entities': [
|
||||
{
|
||||
'entity_type': 'amo_addon',
|
||||
'attributes': {
|
||||
'id': str(addon.id),
|
||||
'guid': addon.guid,
|
||||
'slug': addon.slug,
|
||||
'name': str(addon.name),
|
||||
},
|
||||
},
|
||||
{
|
||||
'entity_type': 'amo_user',
|
||||
'attributes': {
|
||||
'id': str(reporter_user.id),
|
||||
'name': reporter_user.display_name,
|
||||
'email': reporter_user.email,
|
||||
'fxa_id': reporter_user.fxa_id,
|
||||
},
|
||||
},
|
||||
],
|
||||
'relationships': [
|
||||
{
|
||||
'source_id': str(user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(addon.id),
|
||||
'target_type': 'amo_addon',
|
||||
'relationship_type': 'amo_author_of',
|
||||
},
|
||||
{
|
||||
'source_id': str(reporter_user.id),
|
||||
'source_type': 'amo_user',
|
||||
'target_id': str(user.id),
|
||||
'target_type': 'amo_user',
|
||||
'relationship_type': 'amo_reporter_of',
|
||||
},
|
||||
],
|
||||
}
|
|
@ -1509,3 +1509,9 @@ BIGQUERY_AMO_DATASET = 'amo_dev'
|
|||
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
||||
|
||||
SITEMAP_DEBUG_AVAILABLE = False
|
||||
|
||||
CINDER_SERVER_URL = env(
|
||||
'CINDER_SERVER_URL',
|
||||
default='https://stage.cinder.nonprod.webservices.mozgcp.net/api/v1/',
|
||||
)
|
||||
CINDER_API_TOKEN = env('CINDER_API_TOKEN', default=None)
|
||||
|
|
Загрузка…
Ссылка в новой задаче