django/base/views.py

509 lines
23 KiB
Python
Raw Normal View History

2023-04-23 16:08:01 +00:00
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
2023-05-30 09:30:00 +00:00
from django.utils.translation import gettext_lazy as _
2023-05-05 20:15:03 +00:00
from django.db.models import Q
2023-12-05 14:46:34 +00:00
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, JsonResponse
#reg
from django.template.loader import render_to_string
from django.contrib.sites.shortcuts import get_current_site
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from django.core.mail import EmailMessage
#from django_otp.decorators import otp_required
#from django.contrib.auth.views import PasswordResetView
#from django.contrib.messages.views import SuccessMessageMixin
#from django.core.exceptions import ValidationError
#from django.urls import reverse_lazy
#from django.contrib.auth.models import BaseUserManager
# custom
from .tokens import account_activation_token
2023-05-05 20:15:03 +00:00
from users.models import User
2023-12-05 14:46:34 +00:00
from .models import VendorsData, CryptoCoins, VendorsAddresses, InvoiceCreation
from .forms import VendorEditForm, VendorAddrAddForm, UserRegistrationForm, PasswordResetForm, SetPasswordForm, InvoiceCreationForm, ApiPaymentCreationForm
from .functions import vendor_generator, checksumCheck, UrlValidator, RPCHost, RPCXMR
from .rpcs import rpcs, API_FEE
import uuid, hashlib, requests
2023-04-23 16:08:01 +00:00
# Create your views here.
2023-12-05 14:46:34 +00:00
def activateEmail(request, user, to_email):
mail_subject = 'Activate your user account.'
message = render_to_string('base/template_activate_account.html', {
'user': user.username,
'domain': get_current_site(request).domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
'protocol': 'https' if request.is_secure() else 'http'
})
email = EmailMessage(mail_subject, message, to=[to_email])
if email.send():
messages.success(request, f'Congrats, please check your email and activate your account by \
clicking on the activation link. Rememeber to check all folders')
else:
messages.error(request, f' Unable to send the activation email, please check and retry.')
def activate(request, uidb64, token):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
messages.success(request, 'Thank you for your email confirmation. Now you can login your account.')
else:
messages.error(request, 'Activation link is invalid!')
return redirect('login')
2023-04-23 16:08:01 +00:00
@login_required(login_url='login')
def index(request):
context = {}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_dashboard.html', context)
def RegiserUser(request):
title = "Register your account"
if request.method == "POST":
if request.POST.get('password') != request.POST.get('password_again'):
messages.error(request, 'Password does not match')
return redirect('register')
form = UserRegistrationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.email = form.cleaned_data['email'].lower()
user.set_password(form.cleaned_data['password'])
user.last_name = form.cleaned_data['last_name']
user.first_name = form.cleaned_data['first_name']
user.uuid = uuid.uuid4()
user.is_active = False
user.save()
activateEmail(request, user, form.cleaned_data.get('email'))
return redirect('login')
else:
form = UserRegistrationForm()
context = {"form": form, 'title': title}
return render(request, 'base/lp_register.html', context)
2023-04-23 16:08:01 +00:00
def LoginPage(request):
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
user = None
error = None
try:
user = User.objects.get(email=email)
except:
2023-12-05 14:46:34 +00:00
error = messages.error(request, 'Wrong password or account is inactive')
2023-04-23 16:08:01 +00:00
if user is not None and error is None:
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
return redirect('dashboard')
else:
2023-12-05 14:46:34 +00:00
messages.error(request, 'Wrong password or account is inactive')
2023-04-23 16:08:01 +00:00
2023-12-05 14:46:34 +00:00
context = {'title': 'Sign In'}
return render(request, 'base/lp_login.html', context)
2023-04-23 16:08:01 +00:00
def LogoutPage(request):
logout(request)
return redirect('login')
2023-12-05 14:46:34 +00:00
def password_reset_request(request):
title = "Password reset"
if request.method == 'POST':
form = PasswordResetForm(request.POST)
user = None
if form.is_valid():
email = form.cleaned_data['email'].lower()
try:
user = User.objects.get(email=email)
except:
messages.success(request, 'If the email is registered with us, you will receive an email with instructions for resetting your password.')
if user:
subject = "Password reset requested on Litepay.ch"
message = render_to_string("base/template_password_reset_email.html", {
'user': user,
'domain': get_current_site(request).domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
"protocol": 'https' if request.is_secure() else 'http'
})
email = EmailMessage(subject, message, to=[user.email])
if email.send():
messages.success(request,
"""
If the email is registered with us, you will receive an email with instructions for resetting your password.
"""
)
else:
messages.error(request, "Problem sending reset password email, please try again")
return redirect('login')
else:
form = PasswordResetForm()
context = {"form": form, 'title': title}
return render(request, "base/lp_pswd_reset.html", context)
def passwordResetConfirm(request, uidb64, token):
title = "Password reset"
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
if request.method == 'POST':
form = SetPasswordForm(user, request.POST)
if form.is_valid():
form.save()
messages.success(request, "Your password has been set. You may go ahead and log in.")
return redirect('login')
else:
for error in list(form.errors.values()):
messages.error(request, error)
context = {}
return render(request, 'base/lp_pswd_reset_confirm.html', context)
else:
messages.error(request, "Link is expired")
return redirect("dashboard")
#### VENDOR VIEWS ####
2023-04-23 16:08:01 +00:00
@login_required(login_url='login')
def VendorPage(request):
2023-05-05 20:15:03 +00:00
vendors = VendorsData.objects.filter(Q(vendorid_id=request.user.id) & Q(vendorDeleted=False))
2023-04-23 16:08:01 +00:00
context = {'vendors': vendors}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendor.html', context)
2023-05-05 20:15:03 +00:00
@login_required(login_url='login')
2023-05-30 09:30:00 +00:00
#@otp_required(login_url='two_factor:login')
2023-05-05 20:15:03 +00:00
def VendorEditPage(request, vdr ):
try:
2023-05-30 09:30:00 +00:00
vendors = VendorsData.objects.get(Q(vendorid_id=request.user.id) & Q(vendorUUID=vdr))
form = VendorEditForm()
vendor_title = "Edit Vendor"
if request.method == 'POST':
if request.POST.get('submit') == 'Submit':
try:
vendors = VendorsData.objects.get(Q(vendorid_id=request.user.id) & Q(vendorUUID=vdr))
form = VendorEditForm(request.POST, instance=vendors)
if form.is_valid():
form.save()
messages.success(request, "Vendor information saved")
return redirect('vendor')
else:
messages.error(request, "Something wrong happened, try again.")
except Exception as e:
2023-05-05 20:15:03 +00:00
messages.error(request, "Something wrong happened, try again.")
2023-05-30 09:30:00 +00:00
context = {'vendors': vendors, 'form': form, 'vendor_title': vendor_title}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorEdit.html', context)
2023-05-30 09:30:00 +00:00
except Exception as e:
messages.error(request, e)
return redirect('vendor')
2023-05-05 20:15:03 +00:00
@login_required(login_url='login')
def VendorCreatePage(request):
vendor_title = "Create Vendor"
2023-05-30 09:30:00 +00:00
context = {'vendor_title': vendor_title}
2023-05-05 20:15:03 +00:00
if request.method == 'POST':
try:
2023-05-30 09:30:00 +00:00
try:
vendor_accounts = len(VendorsData.objects.filter(vendorid_id=request.user.id))
if vendor_accounts > request.user.vendornr:
messages.error(request, "You have reached the maximum number of vendor accounts")
return redirect('vendor')
except: pass
2023-05-05 20:15:03 +00:00
form = VendorEditForm(request.POST)
if form.is_valid():
# Generate vendor
new_vendor = form.save(commit=False)
try:
vdr = vendor_generator()
vendor_check = VendorsData.objects.get(vendorUUID=vdr)
while vendor_check is vdr:
vdr = vendor_generator()
vendor_check = VendorsData.objects.get(vendorUUID=vdr)
except:
pass
2023-05-30 09:30:00 +00:00
secretKey = str(uuid.uuid4())
md5s = hashlib.md5(secretKey.encode()).hexdigest()
2023-05-05 20:15:03 +00:00
new_vendor.vendor = vdr
2023-05-30 09:30:00 +00:00
new_vendor.vendorSecretKey = md5s
new_vendor.vendorSkipScreen = False
2023-05-05 20:15:03 +00:00
new_vendor.vendorUUID = uuid.uuid4()
new_vendor.vendorid_id = request.user.id
# Save vendor
try:
new_vendor.save()
2023-05-30 09:30:00 +00:00
vendor_title = "Congrats!"
context = {'vendor_title': vendor_title, "vendor": new_vendor, 'secret': secretKey}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorSuccess.html', context)
2023-05-30 09:30:00 +00:00
except Exception:
messages.error(request, "Unable to create vendor") #
2023-05-05 20:15:03 +00:00
else:
2023-05-30 09:30:00 +00:00
messages.error(request, "The information submited is incomplete") #
2023-05-05 20:15:03 +00:00
except Exception as e:
messages.error(request, "Something wrong happened, try again.")
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorCreate.html', context)
2023-05-05 20:15:03 +00:00
2023-05-30 09:30:00 +00:00
@login_required(login_url='login')
def VendorAddrPage(request,vdr):
try:
coins = CryptoCoins.objects.filter(coinIsActive=True)
try:
vendors = VendorsData.objects.get(Q(vendorid_id=request.user.id) & Q(vendorUUID=vdr))
except:
messages.error(request, "Vendor not found")
return redirect('vendor')
addresses = VendorsAddresses.objects.filter(Q(vendorUUID=vdr) & Q(vendorid_id=request.user.id))
form = VendorAddrAddForm()
vendor_title = "Add a crypto address"
if request.method == 'POST':
if request.POST.get('submit') == 'Submit':
try:
if checksumCheck(request.POST.get('coin').lower(), request.POST.get('address')) == False:
2023-12-05 14:46:34 +00:00
messages.error(request, "Invalid address, please try again")
2023-05-30 09:30:00 +00:00
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorAddr.html', context)
2023-05-30 09:30:00 +00:00
except:
# stop here, return nothing, notify us.
return redirect('vendorAddr', vdr)
2023-12-05 14:46:34 +00:00
2023-05-30 09:30:00 +00:00
##check if duplicate
2023-12-05 14:46:34 +00:00
try:
for obj in VendorsAddresses.objects.filter(Q(coin=request.POST.get('coin')) & Q(addrIsActive=True) & Q(vendorUUID=vdr) & Q(vendorid_id=request.user.id)):
if obj.address == request.POST.get('address'):
messages.error(request, "Address already exists")
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
return render(request, 'base/lp_vendorAddr.html', context)
except:
pass
2023-05-30 09:30:00 +00:00
try:
form = VendorAddrAddForm(request.POST)
if form.is_valid():
new_address = form.save(commit=False)
new_address.vendorUUID = vdr
new_address.addrDeleted = False
new_address.addrIsActive = True
new_address.vendor_id = vendors.id
new_address.vendorid_id = request.user.id
try:
for obj in VendorsAddresses.objects.filter(Q(coin=request.POST.get('coin')) & Q(addrIsActive=True) & Q(vendorid_id=request.user.id)):
obj.addrIsActive = False
obj.save()
new_address.save()
messages.success(request, "Vendor address saved")
#add email notification
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorAddr.html', context)
2023-05-30 09:30:00 +00:00
except Exception as e:
messages.error(request, e) #
else:
messages.error(request, "Something wrong happened, try again!")
except Exception as e:
messages.error(request, "Something wrong happened, try again!")
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
2023-12-05 14:46:34 +00:00
return render(request, 'base/lp_vendorAddr.html', context)
2023-05-30 09:30:00 +00:00
except Exception as e:
messages.error(request, "Something wrong happened, try again!")
return redirect('vendor')
2023-05-05 20:15:03 +00:00
2023-12-05 14:46:34 +00:00
@csrf_exempt
def MerchInvoice(request):
if request.method == 'GET':
return HttpResponse(status=403)
elif request.method == 'POST':
required_fields = ['vendor', 'secret', 'callback', 'return', 'invoice']
for field in required_fields:
if request.POST.get(field) is None or request.POST.get(field).strip() == '':
return JsonResponse({'status': 'error', 'message': f'You did not send the {field} field, try again.'}, status=400)
price = request.POST.get('price')
currency = request.POST.get('currency')
callbackurl = requests.utils.unquote(request.POST.get('callback'))
returnurl = requests.utils.unquote(request.POST.get('return'))
email = request.POST.get('email')
if not currency:
currency = 'USD'
if price is None or not price.isdigit() or int(price) <= 0:
return JsonResponse({'status': 'error', 'message': 'You did not send a valid price, try again.'}, status=400)
if UrlValidator.validate(requests.utils.unquote(request.POST.get('callback')))!= True:
return JsonResponse({'status': 'error', 'message': 'Invalid callback URL'}, status=400)
if UrlValidator.validate(requests.utils.unquote(request.POST.get('return'))) != True:
return JsonResponse({'status': 'error', 'message': 'Invalid return URL'}, status=400)
try:
vendor = VendorsData.objects.get(vendor=request.POST.get('vendor'))
except:
return JsonResponse({'status': 'error', 'message':'Vendor ID unknown'}, status=400)
if vendor.vendorSecretKey != hashlib.md5(request.POST.get('secret').encode()).hexdigest():
return JsonResponse({'status': 'error', 'message': 'Invalid secret key'}, status=400)
invUUID = uuid.uuid5(uuid.NAMESPACE_URL,request.POST.get('invoice')+request.POST.get('vendor'))
if InvoiceCreation.objects.filter(Q(invoiceUUID=invUUID)):
protocol = 'https' if request.is_secure() else 'http'
domain = get_current_site(request).domain + '/v2/i/' + str(invUUID)
return JsonResponse({'status': 'success', 'url': protocol +'://'+ domain }, status=200)
try:
form = InvoiceCreationForm()
newForm = form.save(commit=False)
newForm.invoiceUUID = invUUID
newForm.invoiceID = request.POST.get('invoice')
newForm.invoiceAmount = request.POST.get('price')
newForm.invoiceCoin = currency
newForm.invoiceState = 0
newForm.invoiceCallbackLink = callbackurl
newForm.invoiceReturnLink = returnurl
newForm.invoiceBuyerEmail = email
newForm.invoiceDeleteLink = None
newForm.invoiceDeleted = 0
newForm.invoiceVendor_id = vendor.id
newForm.invoiceVendorid_id = vendor.vendorid_id
try:
newForm.save()
protocol = 'https' if request.is_secure() else 'http'
domain = get_current_site(request).domain + '/v2/i/' + str(invUUID)
return JsonResponse({'status': 'success', 'url': protocol +'://'+ domain }, status=200)
except Exception as e:
return JsonResponse({'status': 'error', 'message': 'Unable to save the invoice, try again'}, status=400)
except Exception as e:
return JsonResponse({'status': 'error', 'message': 'Unable to create the invoice, try again'}, status=400)
else:
return HttpResponse(status=403)
@csrf_exempt
def ApiInvoice(request):
if request.method == 'GET':
required_fields = ['method', 'address']
for field in required_fields:
if request.GET.get(field) is None or request.GET.get(field).strip() == '':
return JsonResponse({'status': 'error', 'message': f'You did not send the {field} field, try again.'}, status=400)
try:
if not CryptoCoins.objects.filter(Q(coinAPI=True) & Q(coinIsActive=True) & Q(coinSymbol = request.GET.get('method').upper())):
return JsonResponse({'status': 'error', 'message': 'Invalid method used'}, status=400)
except Exception:
return JsonResponse({'status': 'error', 'message': 'Something wrong happened, try again!'}, status=400)
if checksumCheck(request.GET.get('method').lower(), request.GET.get('address')) == False:
return JsonResponse({'status': 'error', 'message': 'Invalid destination address'}, status=400)
if request.GET.get('callback_url'):
if UrlValidator.validate(requests.utils.unquote(request.GET.get('callback_url'))) != True:
return JsonResponse({'status': 'error', 'message': 'Invalid callback URL'}, status=400)
statusFlag = 0
callbackurl = requests.utils.unquote(request.GET.get('callback_url'))
else:
statusFlag = 1
callbackurl = None
## RPC connection to Demons
match request.GET.get('method').upper():
case 'BTC' | 'LTC' | 'ZEC' | 'BCH' | 'BTCT' | 'DOGE':
rpc = RPCHost("http://%s:%s@%s:%s" % (rpcs[request.GET.get('method').upper()]['user'], rpcs[request.GET.get('method').upper()]['pass'], rpcs[request.GET.get('method').upper()]['host'], rpcs[request.GET.get('method').upper()]['port']))
case 'XMR':
rpc = RPCXMR(rpcs[request.GET.get('method').upper()]['host'], rpcs[request.GET.get('method').upper()]['user'], rpcs[request.GET.get('method').upper()]['pass'])
case _:
return JsonResponse({'status': 'error', 'message': 'RPC undergoing maintenance'}, status=400)
try:
match request.GET.get('method').upper():
case 'XMR':
wallet = rpc.call('create_address',{"account_index": 0})
wallet = wallet['address']
case 'LTC' | 'ZEC' | 'DOGE':
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,False,True)
wallet = rpc.call('getnewaddress')
case 'BTC' | 'BTCT':
#wallet = rpc.call('createwallet','test',False,False,'exdTHnRJ1BxZfBvU',False,True,True,False)
wallet = rpc.call('getnewaddress', '', 'p2sh-segwit')
case 'BCH':
wallet = rpc.call('getnewaddress')
wallet = wallet.replace('bitcoincash:', '')
case _:
## notify admin about the error
return JsonResponse({'status': 'error', 'message': 'CryptoCoin unavailable'}, status=400)
except Exception as error:
## notify admin about the error
# Failed to connect for remote procedure call.
return JsonResponse({'status': 'error', 'message': 'RPC unavailable'}, status=400)
try:
form = ApiPaymentCreationForm()
newForm = form.save(commit=False)
newForm.userUUID = uuid.uuid5(uuid.NAMESPACE_URL,request.GET.get('address'))
newForm.userAddr = request.GET.get('address')
newForm.userCoin = request.GET.get('method').upper()
newForm.usercallbackUrl = callbackurl
newForm.userIP = request.META.get("REMOTE_ADDR")
newForm.ourAddr = wallet
newForm.userAmount = 0.00000000
newForm.statusFlag = statusFlag
newForm.paidFlag = 0
try:
newForm.save()
return JsonResponse(
{'status': 'success',
'callback_url': callbackurl,
'address': wallet,
'destination': request.GET.get('address'),
'fee': API_FEE
}, status=200)
except Exception as e:
return JsonResponse({'status': 'error', 'message': 'Unable to save the invoice, try again'}, status=400)
except Exception as e:
return JsonResponse({'status': 'error', 'message': 'Unable to create the invoice, try again'}, status=400)
elif request.method == 'POST':
return HttpResponse(status=403)
else:
return HttpResponse(status=403)
def InvoicePage(request, inv):
try:
invoice = InvoiceCreation.objects.get(invoiceUUID=inv)
vendor = VendorsData.objects.get(Q(id=invoice.invoiceVendor_id))
vendorCryptoCoins = VendorsAddresses.objects.filter(Q(addrIsActive=True) & Q(vendor_id=invoice.invoiceVendor_id))
context = {'invoice': invoice, 'coins': vendorCryptoCoins, "vendor": vendor}
return render(request, 'base/lp_invoice.html', context)
except Exception as e:
return HttpResponse(e)
#return redirect('dashboard')