Flask app.after_request() keeps user on the same page - python

I have the following code:
#app.after_request
def sense_inactive(response):
if session.has_key('usercode'): ## if user has logged in
usercode = session['usercode']
inactive_rmt = info.find_one({'usercode': usercode})['inactive']
curr_time = time.time()
last_req = session['req_time']
## time_difference = datetime.combine(date.today(), curr_time) - datetime.combine(date.today(), last_req)
time_difference = curr_time - last_req
if time_difference > 60:
usercode = session['usercode']
insert = {'inactive': True}
info.update_one({'usercode': usercode}, {'$set': insert})
print 'user is inactive'
else:
usercode = session['usercode']
insert = {'inactive': False}
info.update_one({'usercode': usercode}, {'$set': insert})
else: ## if user hasn't logged in
return response
...that I'm attempting to use to determine whether or not a user is 'active' on my web app. However, running this code makes all links revert back to the same page; I click on a link, and the app.after_request code runs, but the page stays the same.
Is my 'return response' line causing the problem? I've read in some (somewhat cryptic) documentation that app.after_request decorated functions need parameters in order to function.

Assuming your code actually looks like this:
if 'usercode' in session:
...
else: # if user hasn't logged in
return response
You're only returning a response if the user is not logged in. Remove the else and always return the response whether you do something else or not.
if 'usercode' in session:
...
return response

Related

How to process webhook request coming from a 3rd party application?

I need help to evaluate weather i am doing it right or is there a better way, the scenario is an 3rd party application is sending an webhook request after a successful payment but the problem is that sometimes this application may send the same notification more than once.so it is recommended to ensure that implementation of the webhook is idempotent.so steps that i am implementing for this are
if signature is correct (assume it is corect),Find orders record in the database using orderId in the request params.
Please note: orderId in request params is payment_gateway_order_identifier in orders table.
if txStatus = 'SUCCESS' AND haven't already processed COLLECTION payment for this same order,
Create payments record.
201 response with nothing in the response body.
else
201 response with nothing in the response body.
else
422 response with {message: "Signature is incorrect"} in response body
views.py
#api_view(['POST'])
def cashfree_request(request):
if request.method == 'POST':
data=request.POST.dict()
payment_gateway_order_identifier= data['orderId']
amount = data['orderAmount']
transaction_status = data['txStatus']
signature = data['signature']
if(computedsignature==signature): #assume it to be true
order=Orders.objects.get(
payment_gateway_order_identifier=payment_gateway_order_identifier)
if transaction_status=='SUCCESS':
try:
payment= Payments.objects.get(orders=order)
return Response({"Payment":"Done"},status=status.HTTP_200_OK)
except (Payments.DoesNotExist):
payment = Payments(orders=order,amount=amount,datetime=datetime)
payment.save()
return Response(status=status.HTTP_200_OK)
else:
return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)
models.py
class Orders(models.Model):
id= models.AutoField(primary_key=True)
amount = models.DecimalField(max_digits=19, decimal_places=4)
payment_gateway_order_identifier = models.UUIDField(
primary_key=False,default=uuid.uuid4,editable=False,unique=True)
sussessfull
class Payments(models.Model):
id = models.AutoField(primary_key=True)
orders = models.ForeignKey(Orders, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=19, decimal_places=4, verbose_name='Price in INR')
datetime = models.DateTimeField(auto_now=False,auto_now_add=False)
This rather belongs to Codereview site. Anyway - you are doing up to 3 consecutive SQL queries, so there's a chance for a race condition. A simple way how to prevent that: use some KV storage like Redis/Memcache as a lock - save the value you're using as a nonce on the start of the function, and delete it on the end.
#api_view(['POST'])
def cashfree_request(request):
data = request.POST.dict()
payment_gateway_order_identifier = data['orderId']
# `nx` will set & return only if the key does not exist
# set a timeout in case it wont reach `delete()` on the end
if not redis.set("lock_%s" % payment_gateway_order_identifier, "1", nx=True, ex=2):
return Response(status=status.HTTP_409_CONFLICT)
amount = data['orderAmount']
transaction_status = data['txStatus']
signature = data['signature']
if computedsignature == signature:
order = Orders.objects.get(payment_gateway_order_identifier=payment_gateway_order_identifier)
if transaction_status == 'SUCCESS':
try:
Payments.objects.get(orders=order)
res = Response({"Payment": "Done"}, status=status.HTTP_200_OK)
except Payments.DoesNotExist:
payment = Payments(orders=order, amount=amount, datetime=datetime)
payment.save()
res = Response(status=status.HTTP_200_OK)
else:
res = Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)
# unlock for another request
redis.delete("lock_%s" % payment_gateway_order_identifier)
return res
you dont need if request.method == 'POST': since the code is accessible via POST only anyway, that will make your code less indented.
notice you dont handle the case where transaction_status is not SUCCESS

AWS chalice local works but not chalice deploy

I am pretty new to coding and aws chalice. I tried writing a code that gets messages from trading-view and executes orders depending on the signals.
I tested the code locally and everything worked fine, but when I test the Rest API I get the following error:
{"message":"Missing Authentication Token"}
I set up my credentials via "aws configure" as explained here: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html
I also created a config.txt file in my aws folder and checked my settings via "aws configure get" and they were fine.
The index function in the beginning worked too, so there should be a problem within my code?
I changed some values and cut some functions and the strategy part out, but the code looks somewhat like this:
from chalice import Chalice
from datetime import datetime
from binance.client import Client
from binance.enums import *
import ccxt
exchange = ccxt.binance({
'apiKey': 'KEY',
'secret': 'SECRET',
'enableRateLimit': True,
'options': {
'defaultType': 'future',
},
})
def buy_order(quantity, symbol, order_type = ORDER_TYPE_MARKET,side=SIDE_BUY,recvWindow=5000):
try:
print("sending order")
order = client.futures_create_order(symbol = symbol, type = order_type, side = side, quantity = quantity,recvWindow=recvWindow)
print(order)
except Exception as e:
print("an exception occured - {}".format(e))
return False
return True
app = Chalice(app_name='tradingview-webhook-alert')
indicator1 = "x"
indicator2 = "y"
TRADE_SYMBOL = "Test123"
in_position = False
def diff_time(time1, time2):
fmt = '%Y-%m-%dT%H:%M:%SZ'
tstamp1 = datetime.strptime(time1, fmt)
tstamp2 = datetime.strptime(time2, fmt)
if tstamp1 > tstamp2:
td = tstamp1 - tstamp2
else:
td = tstamp2 - tstamp1
td_mins = int(round(td.total_seconds() / 60))
return td_mins
#app.route('/test123', methods=['POST'])
def test123():
global indicator1, indicator2
request = app.current_request
message = request.json_body
indicator = message["indicator"]
price = message["price"]
value = message["value"]
if indicator == "indicator1":
indicator1 = value
if indicator == "indicator2":
indicator2 = value
if in_position == False:
if (indicator1 >123) & (indicator2 < 321):
balance = exchange.fetch_free_balance()
usd = float(balance['USDT'])
TRADE_QUANTITY = (usd / price)*0.1
order_succeeded = buy_order(TRADE_QUANTITY, TRADE_SYMBOL)
if order_succeeded:
in_position = True
return {"test": "123"}
I tested it locally with Insomnia and tried the Rest API link there and in my browser, both with the same error message. Is my testing method wrong or is it the code? But even then, why isn't the Rest API link working, when I include the index function from the beginning again? If I try the index function from the beginning, I get the {"message": "Internal server error"} .
This is probably a very very basic question but I couldn't find an answer online.
Any help would be appreciated!
I am not pretty sure if that helps you because I don't really understand your question but:
You are using a POST-request which will not be executed by opening a URL.
Try something like #app.route('/test123', methods=['POST', 'GET']) so that if you just open the URL, it will execute a GET-request
Some more information:
https://www.w3schools.com/tags/ref_httpmethods.asp

ID not replaced by %s in python django

def read_lf_notifiation(request, id, slug):
lf = LostAndFound.objects.get(slug=slug)
notf = N_lostandfound.objects.get(id=id, lf=lf)
if notf.read == False:
notf.read = True
notf.save()
return HttpResponseRedirect('/lostandfound/%s/?notif_id=%s' %(slug, notf.id))
So read_lf_notification is supposed to read the notfication and redirect to the same page but with the url parameter of notif_id. So I want to give the value of notif_id, the id of notf, but when it redirects to the same page, the response is
http://localhost:8000/this-is-slug/?notf_id=id
But what I want is
http://localhost:8000/this-is-slug/?notf_id=12
What am I doing wrong here?
Thanks in advance

Django raises 404 error during HttpResponseRedirect but after refreshing, shows the current page

I have a page called 'Read Later' where the users read later posts are stored. I have the Read Later on the nav bar. Now, when the user has no read later posts and clicks on Read Later, the user is redirected back to the original page. I have a function based def for Read Later.
views.py :
def show_readlater(request, *args):
global redirect
global redirect_lock
global return_address
if not(redirect_lock):
redirect = None
else:
redirect_lock = False
if not(request.user.is_authenticated()):
raise PermissionDenied
else:
user_instance = User.objects.get(username = request.user.username)
userprofile_instance = UserProfile.objects.get(user = user_instance)
readlater_objects = ReadLaterList.objects.all()
readlater_list = []
count = 0
for x in readlater_objects:
if x.username == request.user.username:
readlater_post = Post.objects.get(slug = x.slug)
readlater_list.append(readlater_post)
count = count + 1
if count == 0 :
redirect = "no_readlater"
redirect_lock = True
return HttpResponseRedirect(return_address) # The user is redirect back to the original page
post_title = "Read Later"
template = "posts/show_posts.html"
dictionary = {
"total_posts" : readlater_list,
"title" : post_title,
"count" : count,
"redirect" : redirect,
}
return render(request, template, dictionary)
Here, redirect is to display a message that no Read Later posts are there, in the original page.
The issue is that, when the redirect happens, Django says page not found, but upon refresh the page is loaded.
What is happening ?
first of all change this
global redirect
global redirect_lock
global return_address
to
request.session['redirect']= redirect
for all global variables
and use redirect instead HttpResponseRedirect
Make sure the url specified in the global variable "return_address" is correct and specified in your app/urls.py.

Django Responds code 500 no matter what

I have a method in Django where I get POST data from a mobile app and all I do is save it and send a Response. The problem is though the the data gets saved but no matter what the app receives the response code 500.
<Response [500]>
code:
#csrf_exempt
def store_recordings(request):
if request.method == 'POST':
print "In POST",request.POST
driverName = request.POST['driverName']
driverMobileNum = request.POST['driverMobileNum']
customerMobileNum = request.POST['customerMobileNum']
salesOrderNo = request.POST['salesOrderNo']
callRecord = request.POST['callRecord']
latitude = request.POST['latitude']
longitude = request.POST['longitude']
callStart = request.POST['callStart']
callEnd = request.POST['callEnd']
callDuration = request.POST['callDuration']
callType = request.POST['callType']
driverrecording = DriverRecording(driverName=driverName,driverMobileNum=driverMobileNum,customerMobileNum=customerMobileNum,salesOrderNo=salesOrderNo,callRecord=callRecord,latitude=latitude,longitude=longitude,callStart=callStart,callEnd=callEnd,callDuration=callDuration,callType=callType)
save_or_not = driverrecording.save()
driverexist = DriverNames.objects.all()
new_driver_flag = False
driverName_list = [each.driverName for each in driverexist]
driverName_list = list(set(driverName_list))
if driverName in driverName_list:
pass
else:
DriverNames(driverName=driverName,driverMobileNum=driverMobileNum).save()
return HttpResponse(status=201)
else:
return HttpResponse(status=400)
I am perplexed what is the problem.
Thanks.
Almost certainly, one or more of those fields is not being sent, so you are getting a KeyError. If you set DEBUG to True you would see the traceback.
You should be using Django's forms framework, instead of directly accessing the POST data. That will validate the input and allow you to display any errors.

Categories