Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compliance - blocked country and user list #5602

Merged
merged 4 commits into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
'event_ethdenver2019',
'inbox',
'feeswapper',
'oauth2_provider'
'oauth2_provider',
'compliance'
]

MIDDLEWARE = [
Expand Down
Empty file added app/compliance/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions app/compliance/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.contrib import admin

from .models import Country, Entity


class GeneralAdmin(admin.ModelAdmin):
ordering = ['-id']
list_display = ['created_on', '__str__']

admin.site.register(Country, GeneralAdmin)
admin.site.register(Entity, GeneralAdmin)
5 changes: 5 additions & 0 deletions app/compliance/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class ComplianceConfig(AppConfig):
name = 'compliance'
Empty file.
Empty file.
72 changes: 72 additions & 0 deletions app/compliance/management/commands/pull_compliance_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'''
Copyright (C) 2019 Gitcoin Core

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

'''

import urllib.request
import xml.etree as etree
import xml.etree.ElementTree as ET

from django.core.management.base import BaseCommand
from django.db import transaction

from compliance.models import Country, Entity


def insert_countries():
# clear existing table
Country.objects.all().delete()

# pull data
countries = 'Balkans, Belarus, Burma, Cote D\'Ivoire , Cuba, Democratic Republic of Congo, Iran, Iraq, Liberia, North Korea, Sudan, Syria, Zimbabwe'.split(',')

# insert data
for country in countries:
Country.objects.create(name=country)


def insert_entities():
# clear existing table
Entity.objects.all().delete()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to ever do any kind of tracking / recording of compliance related service denial or anything like that we'll have to not rewrite this table over and over - a premature optimization for now but lets all make sure we are aware of this for the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it; @alexvotofuture should we keep a record of OFAC denials? would it be handy to have to show regulatory compliance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets punt to a v2


# pull data
url = 'https://www.treasury.gov/ofac/downloads/consolidated/consolidated.xml'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who gave this this btw ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont understand the question?

response = urllib.request.urlopen(url).read()
tree = ET.fromstring(response)

# insert data
for ele in tree:
try:
response = {}
keys = ['firstName', 'lastName', 'sdnType', 'city', 'country', 'program', 'stateOrProvince', 'uid']
for key in keys:
elements = ele.findall('{http://tempuri.org/sdnList.xsd}' + f'{key}')
element = elements[0].text if len(elements) else ''
response[key] = element
response['fullName'] = (response.get('firstName', '') + ' ' + response.get('lastName', '')).strip()
Entity.objects.create(**response)
except Exception as e:
print(e)


class Command(BaseCommand):

help = 'syncs compliance info from remote server'

def handle(self, *args, **options):
with transaction.atomic():
insert_countries()
insert_entities()
47 changes: 47 additions & 0 deletions app/compliance/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Generated by Django 2.2.4 on 2019-12-05 20:47

from django.db import migrations, models
import economy.models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Country',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)),
('modified_on', models.DateTimeField(default=economy.models.get_time)),
('name', models.CharField(max_length=500)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Entity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_on', models.DateTimeField(db_index=True, default=economy.models.get_time)),
('modified_on', models.DateTimeField(default=economy.models.get_time)),
('firstName', models.CharField(max_length=500)),
('lastName', models.CharField(max_length=500)),
('fullName', models.CharField(max_length=500)),
('sdnType', models.CharField(max_length=500)),
('city', models.CharField(max_length=500)),
('country', models.CharField(max_length=500)),
('program', models.CharField(max_length=500)),
('stateOrProvince', models.CharField(max_length=500)),
('uid', models.CharField(max_length=25)),
],
options={
'abstract': False,
},
),
]
Empty file.
27 changes: 27 additions & 0 deletions app/compliance/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.db import models

from economy.models import SuperModel


class Entity(SuperModel):
firstName = models.CharField(max_length=500)
lastName = models.CharField(max_length=500)
fullName = models.CharField(max_length=500)
sdnType = models.CharField(max_length=500)
city = models.CharField(max_length=500)
country = models.CharField(max_length=500)
program = models.CharField(max_length=500)
stateOrProvince = models.CharField(max_length=500)
uid = models.CharField(max_length=25)

def __str__(self):
"""Return the string representation of this obj."""
return f'{self.fullName}'


class Country(SuperModel):
name = models.CharField(max_length=500)

def __str__(self):
"""Return the string representation of this obj."""
return f'{self.name}'
3 changes: 3 additions & 0 deletions app/compliance/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
3 changes: 3 additions & 0 deletions app/compliance/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.shortcuts import render

# Create your views here.
26 changes: 25 additions & 1 deletion app/dashboard/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,31 @@ def get_tx_status(txid, network, created_on):


def is_blocked(handle):
return BlockedUser.objects.filter(handle__iexact=handle, active=True).exists()
# check admin block list
is_on_blocked_list = BlockedUser.objects.filter(handle__iexact=handle, active=True).exists()
if is_on_blocked_list:
return True

# check banned country list
from compliance.models import Country, Entity
owocki marked this conversation as resolved.
Show resolved Hide resolved
last_login = self.actions.filter(action='Login').order_by('pk').last()
if last_login:
last_login_country = last_login.location_data.get('country_name')
if last_login_country:
is_on_banned_countries = Country.objects.filter(name=last_login_country)
if is_on_banned_countries:
return True

# check banned entity list
if self.user:
first_name = self.user.first_name
last_name = self.user.last_name
full_name = '{first_name} {last_name}'
is_on_banned_user_list = Entitty.objects.filter(fullName__icontains=full_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if is_on_banned_user_list:
return True

return False


def get_nonce(network, address):
Expand Down
1 change: 1 addition & 0 deletions scripts/crontab
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/us
*/8 * * * * cd gitcoin/coin; bash scripts/run_management_command.bash send_tips_for_bounty_fulfiller >> /var/log/gitcoin/send_tips_for_bounty_fulfiller.log 2>&1
35 1 * * * cd gitcoin/coin; bash scripts/run_management_command.bash update_popularity >> /var/log/gitcoin/update_popularity.log 2>&1
*/7 * * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash update_tx_status >> /var/log/gitcoin/update_tx_status.log 2>&1
1 3 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash pull_compliance_list >> /var/log/gitcoin/pull_compliance_list.log 2>&1

## REPORTING
1 1 1 * * cd gitcoin/coin; bash scripts/run_management_command.bash activity_report $(date --date='-1 month' +%Y/%m/%d) $(date +%Y/%m/%d) >> /var/log/gitcoin/activity_report.log 2>&1
Expand Down