def receive_tip_v3(request, key, txid, network): """Handle the receiving of a tip (the POST). Returns: TemplateResponse: the UI with the tip confirmed. """ these_tips = Tip.objects.filter(web3_type='v3', txid=txid, network=network) tips = these_tips.filter(metadata__reference_hash_for_receipient=key) | these_tips.filter(metadata__reference_hash_for_funder=key) tip = tips.first() is_authed = request.user.username.lower() == tip.username.lower() or request.user.username.lower() == tip.from_username.lower() or not tip.username not_mined_yet = get_web3(tip.network).eth.getBalance(Web3.toChecksumAddress(tip.metadata['address'])) == 0 did_fail = False if not_mined_yet: tip.update_tx_status() did_fail = tip.tx_status in ['dropped', 'unknown', 'na', 'error'] if not request.user.is_authenticated or request.user.is_authenticated and not getattr( request.user, 'profile', None ): login_redirect = redirect('/login/github?next=' + request.get_full_path()) return login_redirect num_redemptions = tip.metadata.get("num_redemptions", 0) max_redemptions = tip.metadata.get("max_redemptions", 0) is_redeemable = not (tip.receive_txid and (num_redemptions >= max_redemptions)) and is_authed has_this_user_redeemed = request.user.profile.tip_payouts.filter(tip=tip).count() if has_this_user_redeemed: is_redeemable = False if not is_redeemable: messages.info(request, 'This tip has been received already') elif not is_authed: messages.error(request, f'This tip is for @{tip.username} but you are logged in as @{request.user.username}. Please logout and log back in as {tip.username}.') elif did_fail: messages.info(request, f'This tx {tip.txid}, failed. Please contact the sender and ask them to send the tx again.') elif not_mined_yet: messages.info(request, f'This tx {tip.txid}, is still mining. Please wait a moment before submitting the receive form.') elif request.POST.get('receive_txid') and is_redeemable: params = request.POST # db mutations try: profile = get_profile(tip.username) eth_address = params['forwarding_address'] if not is_valid_eth_address(eth_address): eth_address = profile.preferred_payout_address if params['save_addr']: if profile: profile.preferred_payout_address = eth_address profile.save() tip.receive_txid = params['receive_txid'] tip.receive_tx_status = 'pending' tip.receive_address = eth_address tip.received_on = timezone.now() num_redemptions = tip.metadata.get("num_redemptions", 0) # note to future self: to create a tip like this in the future set # tip.username # tip.metadata.max_redemptions # tip.metadata.override_send_amount # tip.amount to the amount you want to send # ,"override_send_amount":1,"max_redemptions":29 num_redemptions += 1 tip.metadata["num_redemptions"] = num_redemptions tip.save() record_user_action(tip.from_username, 'receive_tip', tip) record_tip_activity(tip, tip.username, 'receive_tip') TipPayout.objects.create( txid=tip.receive_txid, profile=request.user.profile, tip=tip, ) messages.success(request, 'This tip has been received') is_redeemable = False has_this_user_redeemed = True except Exception as e: messages.error(request, str(e)) logger.exception(e) params = { 'issueURL': request.GET.get('source'), 'class': 'receive', 'title': _('Receive Tip'), 'gas_price': round(recommend_min_gas_price_to_confirm_in_time(120), 1), 'tip': tip, 'has_this_user_redeemed': has_this_user_redeemed, 'key': key, 'is_redeemable': is_redeemable, 'is_authed': is_authed, 'disable_inputs': not is_redeemable or not is_authed, } return TemplateResponse(request, 'onepager/receive.html', params)
def job_settings(request): """Display and save user's Account settings. Returns: TemplateResponse: The user's Account settings template response. """ msg = '' profile, es, user, is_logged_in = settings_helper_get_auth(request) if not user or not profile or not is_logged_in: login_redirect = redirect('/login/github?next=' + request.get_full_path()) return login_redirect if request.POST: if 'preferred_payout_address' in request.POST.keys(): eth_address = request.POST.get('preferred_payout_address', '') if not is_valid_eth_address(eth_address): eth_address = profile.preferred_payout_address profile.preferred_payout_address = eth_address profile.save() msg = _('Updated your Address') elif request.POST.get('disconnect', False): profile.github_access_token = '' profile = record_form_submission(request, profile, 'account-disconnect') profile.email = '' profile.save() create_user_action(profile.user, 'account_disconnected', request) messages.success( request, _('Your account has been disconnected from Github')) logout_redirect = redirect(reverse('logout') + '?next=/') return logout_redirect elif request.POST.get('delete', False): # remove profile profile.hide_profile = True profile = record_form_submission(request, profile, 'account-delete') profile.email = '' profile.save() # remove email delete_user_from_mailchimp(es.email) if es: es.delete() request.user.delete() AccountDeletionRequest.objects.create( handle=profile.handle.lower(), profile={ 'ip': get_ip(request), }) profile.delete() messages.success(request, _('Your account has been deleted.')) logout_redirect = redirect(reverse('logout') + '?next=/') return logout_redirect else: msg = _('Error: did not understand your request') context = { 'is_logged_in': is_logged_in, 'nav': 'home', 'active': '/settings/job', 'title': _('Job Settings'), 'navs': get_settings_navs(request), 'es': es, 'profile': profile, 'msg': msg, } return TemplateResponse(request, 'settings/job.html', context)
def receive(request, key, txid, network): """Handle the receiving of a kudos (the POST). Returns: TemplateResponse: the UI with the kudos confirmed """ these_kudos_transfers = KudosTransfer.objects.filter(web3_type='v3', txid=txid, network=network) kudos_transfers = these_kudos_transfers.filter( Q(metadata__reference_hash_for_receipient=key) | Q(metadata__reference_hash_for_funder=key)) kudos_transfer = kudos_transfers.first() if not kudos_transfer: raise Http404 is_authed = kudos_transfer.trust_url or request.user.username.replace( '@', '').lower() in [ kudos_transfer.username.replace('@', '').lower(), kudos_transfer.from_username.replace('@', '').lower() ] not_mined_yet = get_web3(kudos_transfer.network).eth.getBalance( Web3.toChecksumAddress(kudos_transfer.metadata['address'])) == 0 did_fail = False if not_mined_yet: kudos_transfer.update_tx_status() did_fail = kudos_transfer.tx_status in [ 'dropped', 'unknown', 'na', 'error' ] if not kudos_transfer.trust_url: if not request.user.is_authenticated or request.user.is_authenticated and not getattr( request.user, 'profile', None): login_redirect = redirect('/login/github/?next=' + request.get_full_path()) return login_redirect if kudos_transfer.receive_txid: messages.info(request, _('This kudos has been received')) elif not is_authed: messages.error( request, f'This kudos is for {kudos_transfer.username} but you are logged in as {request.user.username}. Please logout and log back in as {kudos_transfer.username}.' ) elif did_fail: messages.info( request, f'This tx {kudos_transfer.txid}, failed. Please contact the sender and ask them to send the tx again.' ) elif not_mined_yet and not request.GET.get('receive_txid'): message = mark_safe( f'The <a href="https://etherscan.io/tx/{txid}">transaction</a> is still mining. ' 'Please wait a moment before submitting the receive form.') messages.info(request, message) elif request.POST.get('receive_txid') and not kudos_transfer.receive_txid: params = request.POST # db mutations try: profile = get_profile(kudos_transfer.username.replace('@', '')) eth_address = params['forwarding_address'] if not is_valid_eth_address(eth_address): eth_address = profile.preferred_payout_address if params['save_addr']: if profile: # TODO: Does this mean that the address the user enters in the receive form # Will overwrite an already existing preferred_payout_address? Should we # ask the user to confirm this? profile.preferred_payout_address = eth_address profile.save() kudos_transfer.receive_txid = params['receive_txid'] kudos_transfer.receive_address = eth_address kudos_transfer.received_on = timezone.now() if request.user.is_authenticated: kudos_transfer.recipient_profile = request.user.profile kudos_transfer.save() record_user_action(kudos_transfer.username, 'new_kudos', kudos_transfer) record_user_action(kudos_transfer.from_username, 'receive_kudos', kudos_transfer) record_kudos_email_activity(kudos_transfer, kudos_transfer.username, 'receive_kudos') record_kudos_activity(kudos_transfer, kudos_transfer.username, 'receive_kudos') messages.success(request, _('This kudos has been received')) except Exception as e: messages.error(request, str(e)) logger.exception(e) params = { 'issueURL': request.GET.get('source'), 'class': 'receive', 'gas_price': round(recommend_min_gas_price_to_confirm_in_time(120), 1), 'kudos_transfer': kudos_transfer, 'title': f"Receive {kudos_transfer.kudos_token_cloned_from.humanized_name} Kudos" if kudos_transfer and kudos_transfer.kudos_token_cloned_from else _('Receive Kudos'), 'avatar_url': kudos_transfer.kudos_token_cloned_from.img_url if kudos_transfer and kudos_transfer.kudos_token_cloned_from else None, 'card_desc': f"You've received a {kudos_transfer.kudos_token_cloned_from.humanized_name} kudos!" if kudos_transfer and kudos_transfer.kudos_token_cloned_from else _('You\'ve received a kudos'), 'key': key, 'is_authed': is_authed, 'disable_inputs': kudos_transfer.receive_txid or not_mined_yet or not is_authed, 'tweet_text': urllib.parse.quote_plus( f"I just got a {kudos_transfer.kudos_token_cloned_from.humanized_name} Kudos on @gitcoin. " ) } return TemplateResponse(request, 'transaction/receive.html', params)
def account_settings(request): """Display and save user's Account settings. Returns: TemplateResponse: The user's Account settings template response. """ msg = '' profile, es, user, is_logged_in = settings_helper_get_auth(request) if not user or not profile or not is_logged_in: login_redirect = redirect('/login/github?next=' + request.get_full_path()) return login_redirect if request.POST: if 'persona_is_funder' or 'persona_is_hunter' in request.POST.keys(): profile.persona_is_funder = bool( request.POST.get('persona_is_funder', False)) profile.persona_is_hunter = bool( request.POST.get('persona_is_hunter', False)) profile.save() if 'preferred_payout_address' in request.POST.keys(): eth_address = request.POST.get('preferred_payout_address', '') if not is_valid_eth_address(eth_address): eth_address = profile.preferred_payout_address profile.preferred_payout_address = eth_address profile.save() msg = _('Updated your Address') elif request.POST.get('export', False): export_type = request.POST.get('export_type', False) response = HttpResponse(content_type='text/csv') name = f"gitcoin_{export_type}_{timezone.now().strftime('%Y_%m_%dT%H_00_00')}" response[ 'Content-Disposition'] = f'attachment; filename="{name}.csv"' writer = csv.writer(response) writer.writerow([ 'id', 'date', 'From', 'From Location', 'To', 'To Location', 'Type', 'Value In USD', 'url', 'txid', 'token_name', 'token_value' ]) profile = request.user.profile earnings = profile.earnings if export_type == 'earnings' else profile.sent_earnings earnings = earnings.filter( network='mainnet').order_by('-created_on') for earning in earnings: writer.writerow([ earning.pk, earning.created_on.strftime("%Y-%m-%dT%H:00:00"), earning.from_profile.handle if earning.from_profile else '*', earning.from_profile.data.get('location', 'Unknown') if earning.from_profile else 'Unknown', earning.to_profile.handle if earning.to_profile else '*', earning.to_profile.data.get('location', 'Unknown') if earning.to_profile else 'Unknown', earning.source_type.model_class(), earning.value_usd, earning.txid, earning.token_name, earning.token_value, earning.url, ]) return response elif request.POST.get('disconnect', False): profile.github_access_token = '' profile = record_form_submission(request, profile, 'account-disconnect') profile.email = '' profile.save() create_user_action(profile.user, 'account_disconnected', request) redirect_url = f'https://www.github.com/settings/connections/applications/{settings.GITHUB_CLIENT_ID}' logout(request) logout_redirect = redirect(redirect_url) logout_redirect[ 'Cache-Control'] = 'max-age=0 no-cache no-store must-revalidate' return logout_redirect elif request.POST.get('delete', False): # remove profile profile.hide_profile = True profile = record_form_submission(request, profile, 'account-delete') profile.email = '' profile.save() # remove email delete_user_from_mailchimp(es.email) if es: es.delete() request.user.delete() AccountDeletionRequest.objects.create( handle=profile.handle.lower(), profile={ 'ip': get_ip(request), }) profile.avatar_baseavatar_related.all().delete() try: profile.delete() except: profile.github_access_token = '' profile.user = None profile.hide_profile = True profile.save() messages.success(request, _('Your account has been deleted.')) logout_redirect = redirect(reverse('logout') + '?next=/') return logout_redirect else: msg = _('Error: did not understand your request') context = { 'is_logged_in': is_logged_in, 'nav': 'home', 'active': '/settings/account', 'title': _('Account Settings'), 'navs': get_settings_navs(request), 'es': es, 'profile': profile, 'msg': msg, } return TemplateResponse(request, 'settings/account.html', context)
def account_settings(request): """Display and save user's Account settings. Returns: TemplateResponse: The user's Account settings template response. """ msg = '' profile, es, user, is_logged_in = settings_helper_get_auth(request) if not user or not profile or not is_logged_in: login_redirect = redirect('/login/github/?next=' + request.get_full_path()) return login_redirect if request.POST: if 'persona_is_funder' or 'persona_is_hunter' in request.POST.keys(): profile.persona_is_funder = bool( request.POST.get('persona_is_funder', False)) profile.persona_is_hunter = bool( request.POST.get('persona_is_hunter', False)) profile.save() if 'preferred_payout_address' in request.POST.keys(): eth_address = request.POST.get('preferred_payout_address', '') if not is_valid_eth_address(eth_address): eth_address = profile.preferred_payout_address profile.preferred_payout_address = eth_address profile.save() msg = _('Updated your Address') elif request.POST.get('export', False): export_type = request.POST.get('export_type', False) profile = request.user.profile earnings = profile.earnings if export_type == 'earnings' else profile.sent_earnings earnings = earnings.filter( network='mainnet').order_by('-created_on') return export_earnings_csv(earnings, export_type) elif request.POST.get('disconnect', False): profile.github_access_token = '' profile = record_form_submission(request, profile, 'account-disconnect') profile.email = '' profile.save() create_user_action(profile.user, 'account_disconnected', request) redirect_url = f'https://www.github.com/settings/connections/applications/{settings.GITHUB_CLIENT_ID}' logout(request) logout_redirect = redirect(redirect_url) logout_redirect[ 'Cache-Control'] = 'max-age=0 no-cache no-store must-revalidate' return logout_redirect elif request.POST.get('delete', False): # remove profile profile.hide_profile = True profile = record_form_submission(request, profile, 'account-delete') profile.email = '' profile.save() # remove email mautic_proxy_backend('POST', f'contacts/{profile.mautic_id}/delete') if es: es.delete() request.user.delete() AccountDeletionRequest.objects.create( handle=profile.handle.lower(), profile={ 'ip': get_ip(request), }) profile.avatar_baseavatar_related.all().delete() try: profile.delete() except: profile.github_access_token = '' profile.user = None profile.hide_profile = True profile.save() messages.success(request, _('Your account has been deleted.')) logout_redirect = redirect(reverse('logout') + '?next=/') return logout_redirect else: msg = _('Error: did not understand your request') context = { 'is_logged_in': is_logged_in, 'nav': 'home', 'active': '/settings/account', 'title': _('Account Settings'), 'navs': get_settings_navs(request), 'es': es, 'profile': profile, 'msg': msg, } return TemplateResponse(request, 'settings/account.html', context)