509 lines
23 KiB
Python
Executable File
509 lines
23 KiB
Python
Executable File
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
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.db.models import Q
|
|
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
|
|
from users.models import User
|
|
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
|
|
|
|
|
|
# Create your views here.
|
|
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')
|
|
|
|
|
|
@login_required(login_url='login')
|
|
def index(request):
|
|
context = {}
|
|
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)
|
|
|
|
|
|
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:
|
|
error = messages.error(request, 'Wrong password or account is inactive')
|
|
|
|
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:
|
|
messages.error(request, 'Wrong password or account is inactive')
|
|
|
|
context = {'title': 'Sign In'}
|
|
return render(request, 'base/lp_login.html', context)
|
|
|
|
def LogoutPage(request):
|
|
logout(request)
|
|
return redirect('login')
|
|
|
|
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 ####
|
|
|
|
@login_required(login_url='login')
|
|
def VendorPage(request):
|
|
vendors = VendorsData.objects.filter(Q(vendorid_id=request.user.id) & Q(vendorDeleted=False))
|
|
context = {'vendors': vendors}
|
|
return render(request, 'base/lp_vendor.html', context)
|
|
|
|
@login_required(login_url='login')
|
|
#@otp_required(login_url='two_factor:login')
|
|
def VendorEditPage(request, vdr ):
|
|
try:
|
|
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:
|
|
messages.error(request, "Something wrong happened, try again.")
|
|
context = {'vendors': vendors, 'form': form, 'vendor_title': vendor_title}
|
|
return render(request, 'base/lp_vendorEdit.html', context)
|
|
except Exception as e:
|
|
messages.error(request, e)
|
|
return redirect('vendor')
|
|
|
|
@login_required(login_url='login')
|
|
def VendorCreatePage(request):
|
|
vendor_title = "Create Vendor"
|
|
context = {'vendor_title': vendor_title}
|
|
if request.method == 'POST':
|
|
try:
|
|
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
|
|
|
|
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
|
|
|
|
secretKey = str(uuid.uuid4())
|
|
md5s = hashlib.md5(secretKey.encode()).hexdigest()
|
|
new_vendor.vendor = vdr
|
|
new_vendor.vendorSecretKey = md5s
|
|
new_vendor.vendorSkipScreen = False
|
|
new_vendor.vendorUUID = uuid.uuid4()
|
|
new_vendor.vendorid_id = request.user.id
|
|
# Save vendor
|
|
try:
|
|
new_vendor.save()
|
|
vendor_title = "Congrats!"
|
|
context = {'vendor_title': vendor_title, "vendor": new_vendor, 'secret': secretKey}
|
|
return render(request, 'base/lp_vendorSuccess.html', context)
|
|
except Exception:
|
|
messages.error(request, "Unable to create vendor") #
|
|
else:
|
|
messages.error(request, "The information submited is incomplete") #
|
|
except Exception as e:
|
|
messages.error(request, "Something wrong happened, try again.")
|
|
return render(request, 'base/lp_vendorCreate.html', context)
|
|
|
|
@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:
|
|
messages.error(request, "Invalid address, please try again")
|
|
context = {'vendor_title': vendor_title, 'coins': coins, 'vendors': vendors, "addresses": addresses}
|
|
return render(request, 'base/lp_vendorAddr.html', context)
|
|
except:
|
|
# stop here, return nothing, notify us.
|
|
return redirect('vendorAddr', vdr)
|
|
|
|
##check if duplicate
|
|
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
|
|
|
|
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}
|
|
return render(request, 'base/lp_vendorAddr.html', context)
|
|
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}
|
|
return render(request, 'base/lp_vendorAddr.html', context)
|
|
except Exception as e:
|
|
messages.error(request, "Something wrong happened, try again!")
|
|
return redirect('vendor')
|
|
|
|
@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') |