from django.shortcuts import render, reverse from .models import User, Product, UserIdentifierTypes, ProductIdentifierTypes from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import csrf_protect from django.contrib.auth.decorators import login_required from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.contrib.auth import logout as auth_logout from .backend import * from .store_exceptions import * from .stresstest import * @require_http_methods(["GET"]) def index(request): """ GET: Return the rendered index page. Users can login here. """ return render(request, "index.html", { "users": UserLogic.getFrequentUsersList(), "ident_types": UserIdentifierTypes.to_dict(), }) @login_required(login_url="index") @require_http_methods(["GET", "POST"]) @csrf_protect def buy(request): """ GET: Return the rendered page to buy products POST: Puchase a product @body_param product_id: int @body_param token: int """ if request.method == 'GET': # Return the rendered page return render(request, "buy.html", { "most_bought": ProductLogic.getMostBoughtProductsList(), "recently_bought": ProductLogic.getLastBoughtProductsList(request.user.id), "drinks": ProductLogic.getDrinks(), "candies": ProductLogic.getCandies(), "products": Product.objects.all(), "ident_types": ProductIdentifierTypes.to_dict(), }) elif request.method == 'POST': # Perform a purchase user_id = request.user.id product_id = request.POST.get("product_id") token = request.POST.get("token") try: purchase_return_tuple = PurchaseLogic().purchase(user_id, product_id, token) except (UserNotEnoughMoney, NegativeMoneyAmount) as exc: return JsonResponse({'error': str(exc)}, status=400) if purchase_return_tuple >= 0: return JsonResponse({"purchase_id": purchase_return_tuple}) else: return HttpResponse(status=400) @login_required(login_url="index") @require_http_methods(["POST"]) @csrf_protect def buy_revert(request): """ POST: Revert a purchase. @body_param token: int @body_param purchase_id: int """ purchase_id = request.POST.get("purchase_id") token = request.POST.get("token") try: PurchaseLogic.annullatePurchase(purchase_id, token) except (PurchaseNotAnnullable, UserNotEnoughMoney) as exc: return JsonResponse({'error': str(exc)}, status=400) return HttpResponse(status=200) @login_required(login_url="index") @require_http_methods(["GET", "POST"]) @csrf_protect def charge(request): """ GET: Show the rendered page to charge money. POST: Charge money. @body_param token: int @body_param amount: float """ if request.method == "GET": return render(request, "charge.html", { "recent_charges": ChargeLogic.getLastChargesList(request.user.id), }) elif request.method == "POST": user_id = request.user.id token = request.POST.get("token") amount = request.POST.get("amount") amount = Decimal(amount) try: charge_id = ChargeLogic.charge(user_id, amount, token) except NegativeMoneyAmount as exc: return JsonResponse({'error': str(exc)}, status=400) return JsonResponse({'charge_id': charge_id}) @login_required(login_url="index") @require_http_methods(["POST"]) @csrf_protect def charge_revert(request): """ POST: Revert a charge. @body_param charge_id: int @body_param token: int """ charge_id = request.POST.get("charge_id") token = request.POST.get("token") try: ChargeLogic.annullateCharge(charge_id, token) except (ChargeNotAnnullable, UserNotEnoughMoney) as exc: return JsonResponse({'error': str(exc)}, status=400) return HttpResponse(status=200) @login_required(login_url="index") @require_http_methods(["GET", "POST"]) @csrf_protect def transfer(request): """ GET: Return the rendered page to transfer money to another user. POST: Transfer money to another user. @body_param token: int @body_param receiver: int @body_param amount: float """ if request.method == "GET": return render(request, "transfer.html", { "users": TransferLogic.getFreuquentTransferTargeds(request.user.id), "recent_transfers": TransferLogic.getLastTransfers(request.user.id), }) elif request.method == "POST": user_id = request.user.id token = request.POST.get("token") receiver_id = request.POST.get("receiver") amount = Decimal(request.POST.get("amount")) try: transfer_id = TransferLogic.transfer( user_id, receiver_id, amount, token) except (UserNotEnoughMoney, NegativeMoneyAmount) as exc: return JsonResponse({'error': str(exc)}, status=400) return JsonResponse({"transfer_id": transfer_id}) @login_required(login_url="index") @require_http_methods(["POST"]) @csrf_protect def transfer_revert(request): """ POST: Revert a transfer. @body_param transfer_id: int @body_param token: int """ transfer_id = request.POST.get('transfer_id') token = request.POST.get('token') try: TransferLogic.annullateTransfer(transfer_id, token) except (TransferNotAnnullable, UserNotEnoughMoney) as exc: return JsonResponse({'error': str(exc)}, status=400) return HttpResponse(status=200) # Authentication @require_http_methods(["POST"]) @csrf_protect def login(request): """ Login an user. @body_param identifier: string/int @body_param identifier_type: int """ identifier = request.POST.get('identifier') ident_type = request.POST.get('identifier_type') try: UserLogic.login(request, identifier, ident_type) except (UserIdentifierNotExists, DisabledIdentifier): return HttpResponseRedirect(reverse("index")) return HttpResponseRedirect(reverse("buy")) @login_required(login_url="index") @csrf_protect def logout(request): """ Logout the current user. """ auth_logout(request) return HttpResponseRedirect(reverse("index")) # At-most-once token @login_required(login_url="index") @require_http_methods(["POST"]) @csrf_protect def getToken(request): """ Return a new token used for the at-most-once protocol. """ token = TokenLogic.get_token() return JsonResponse({"token": token}) # Test def stressTest(request): nthreads = 10 barrier = Barrier(nthreads + 1) lock = Lock() for i in range(0, nthreads): st = StressTester(i + 1, 0, 4, barrier, lock, 60) st.start() tmp = input("press any key to start") barrier.wait() def test(request): transfers = TransferLogic.getFreuquentTransferTargeds(1) for transfer in transfers: print(transfer) print("n_transfers:", len(transfers)) def test2(request): pass