diff --git a/app/dashboard/helpers.py b/app/dashboard/helpers.py index c8253b8f57b..5d2fc61e85e 100644 --- a/app/dashboard/helpers.py +++ b/app/dashboard/helpers.py @@ -35,10 +35,7 @@ Activity, BlockedURLFilter, Bounty, BountyEvent, BountyFulfillment, BountyInvites, BountySyncRequest, Coupon, HackathonEvent, UserAction, ) -from dashboard.notifications import ( - maybe_market_to_email, maybe_market_to_github, - notify_of_lowball_bounty, -) +from dashboard.notifications import maybe_market_to_email, maybe_market_to_github, notify_of_lowball_bounty from dashboard.tokens import addr_to_token from economy.utils import convert_amount from git.utils import get_issue_details, get_url_dict, org_name diff --git a/app/grants/urls.py b/app/grants/urls.py index 77b6961912d..63a255c5a4c 100644 --- a/app/grants/urls.py +++ b/app/grants/urls.py @@ -30,7 +30,7 @@ grant_new, grants, grants_addr_as_json, grants_bulk_add, grants_by_grant_type, grants_cart_view, grants_info, grants_landing, grants_type_redirect, ingest_contributions, ingest_contributions_view, invoice, leaderboard, manage_ethereum_cart_data, new_matching_partner, profile, quickstart, remove_grant_from_collection, save_collection, - toggle_grant_favorite, verify_grant, + toggle_grant_favorite, toggle_user_sybil, verify_grant, ) app_name = 'grants/' @@ -115,6 +115,6 @@ path('v1/api/export_info/grant_round.json', contribution_info_from_grant_during_round_as_json, name='contribution_addr_from_grant_during_round_as_json'), # custom API - path('v1/api/get-clr-data/', get_clr_sybil_input, name='get_clr_sybil_input') - + path('v1/api/get-clr-data/', get_clr_sybil_input, name='get_clr_sybil_input'), + path('v1/api/toggle_user_sybil', toggle_user_sybil, name='toggle_user_sybil') ] diff --git a/app/grants/views.py b/app/grants/views.py index 6fd943d98a4..3247819f272 100644 --- a/app/grants/views.py +++ b/app/grants/views.py @@ -86,7 +86,7 @@ from perftools.models import JSONStore, StaticJsonEnv from ratelimit.decorators import ratelimit from retail.helpers import get_ip -from townsquare.models import Announcement, Favorite, PinnedPost +from townsquare.models import Announcement, Favorite, PinnedPost, SquelchProfile from townsquare.utils import can_pin from web3 import HTTPProvider, Web3 @@ -3599,3 +3599,61 @@ def get_trust_bonus(request): _addrs.append(subscription.contributor_address) return allow_all_origins(JsonResponse(response, safe=False)) + + +def toggle_user_sybil(request): + ''' + POST endpoint which allows to mark a list of users as sybil + or remove them the sybil tag from them. + This is intended to be used by BSCI to ensure they can toggle it + every 12 hours based on their findings as opposed to having it done + at the end. + ''' + + json_body = json.loads(request.body) + + token = request.headers['token'] + sybil_users = json_body.get('sybil_users') + non_sybil_users = json_body.get('non_sybil_users') + + data = StaticJsonEnv.objects.get(key='BSCI_SYBIL_TOKEN').data + + if (not sybil_users and not non_sybil_users ) or not token or not data['token']: + return HttpResponseBadRequest("error: missing arguments") + + if token != data['token']: + return HttpResponseBadRequest("error: invalid token") + + squelched_profiles = SquelchProfile.objects.all() + + if sybil_users: + # iterate through users which need to be packed as sybil + for user in sybil_users: + try: + # get user profile + profile = Profile.objects.get(pk=user.get('id')) + + # check if user has entry in SquelchProfile + if not squelched_profiles.filter(profile=profile).first(): + # mark user as sybil + SquelchProfile.objects.create( + profile=profile, + comments=f"sybil: marked by bsci - {user.get('comment')}" + ) + except Exception as e: + print(f"error: unable to mark user ${user.get('id')} as sybil. {e}") + + + if non_sybil_users: + # iterate and remove sybil from user + for user in non_sybil_users: + try: + profile = Profile.objects.get(pk=user.get('id')) + print(squelched_profiles.filter(profile=profile)) + squelched_profiles.filter(profile=profile).delete() + print(squelched_profiles.filter(profile=profile)) + + except Exception as e: + print(f"error: unable to mark ${user.get('id')} as non sybil. {e}") + + return JsonResponse({'success': 'ok'}, status=200)