This commit is contained in:
Andrew Williamson 2023-09-27 17:40:44 +01:00 коммит произвёл GitHub
Родитель 0fe855a03c
Коммит e36dfd1f6b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 373 добавлений и 0 удалений

127
src/olympia/abuse/cinder.py Normal file
Просмотреть файл

@ -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)