request.POST.get() returning none - python

I am running a website using Django. I am trying to Login but it is returning none and i am not getting any error. It shows 200 status code.
Here is my views.py code:
def user_login(request):
datas= {'log':False}
if request.method == "POST":
usern=request.POST.get('Username')
passw=request.POST.get('password')
response = requests.post(url='http://www.onebookingsystem.com/productionApi/API/Admin/login.php',data={"Username":usern,"password":passw})
json_data = response.json()
if json_data['status'] == 1:
user=authenticate(Username=usern,password=passw)
login(request,user)
range_yearly = 0
range_monthly = 0
respo = requests.get(url='http://www.onebookingsystem.com/productionApi/API/Admin/admin_dashboard.php')
data_dash = json.loads(respo.text)
when i am running in POST HTTP request,it shows successfully logged in,but
in GET HTTP request, it shows :Status 0 "mobile or password is missing".//required post params is missing.

This is propably because you're using requests without the session storage.
You can try it this (untested) way:
def user_login(request):
# Create client with session storage to store session cookies
client = requests.Session()
datas= {'log':False}
if request.method == "POST":
usern=request.POST.get('Username')
passw=request.POST.get('password')
# client stores session cookie at login
response = client.post(url='http://www.onebookingsystem.com/productionApi/API/Admin/login.php',data={"Username":usern,"password":passw})
# you can check that with
# print(client.cookies)
json_data = response.json()
if json_data['status'] == 1:
user=authenticate(Username=usern,password=passw)
login(request,user)
range_yearly = 0
range_monthly = 0
# client should be able to access because of its stored session cookie
respo = client.get(url='http://www.onebookingsystem.com/productionApi/API/Admin/admin_dashboard.php')
data_dash = json.loads(respo.text)
More information

Related

Where to store jwt token in flask app so that its picked up automatic jwt_required(optional=True)?

I was trying to create a flask app with user-login API call that generates access and refresh token and upon successful creation redirect back to homepage view which has jwt_required(optional=True) decorator but no matter how i try to save the token i'm unable to fetch it via get_jwt()
This is the API for generating the access and refresh token.
class UserLogin(MethodResource, Resource):
#doc(description='This is User Login Endpoint', tags=['User Endpoint'])
#use_kwargs(User_RequestSchema(exclude=("name", "email","admin")))
#marshal_with(Login_ResponseToken, code=200, description="Success | Returns: \nUser Registered Succesfully")
#marshal_with(Msg_ResponseSchema, code=401, description="Unauthorized | Returns: \n-Invalid User Credentials!")
#marshal_with(Msg_ResponseSchema, code=400, description="Bad Request | Returns: \n-Error loading Json body on request")
def post(self,**kwargs):
"""
If user roll_num and password correct create a new access and refresh token
else return invalid credentials 401 error
"""
try:
schema = User_RequestSchema(exclude=("name", "email","admin"))
data = schema.load(kwargs,unknown=EXCLUDE)
except:
output = {"message":"Error loading Json body in request"}
return output, 400 #Status-Bad Request
user = UserModel.find_by_rollnum(data['roll_num'])
# User Present and password correct
if user is not None and user.check_password(data['password']) and user.roll_num==data['roll_num']:
additional_claims = {"admin_access":user.admin}
access_token = create_access_token(identity=user.roll_num, additional_claims=additional_claims,fresh=True)
refresh_token = create_refresh_token(user.roll_num)
resp = jsonify(login=True)
set_access_cookies(resp, access_token.encode('utf-8'))
set_refresh_cookies(resp, refresh_token.encode('utf-8'))
resp.set_cookie('X-CSRF-TOKEN-ACCESS', access_token.encode('utf-8'))
resp.set_cookie('X-CSRF-TOKEN-REFRESH', refresh_token.encode('utf-8'))
output={"access_token":access_token,
"refresh_token":refresh_token,
"message": "Successful Login"}
return output, 200 # Status-OK
output = {"message": "Invalid User Credentials!"}
return output, 401 # Status-Unauthorized
This is the code that calls the login API and provides login information from login Form
#auth.route("/user_login", methods=["GET", "POST"])
def user_login():
form = LoginForm()
if form.validate_on_submit():
data = {"roll_num": form.roll_num.data,
"password": form.password.data}
# send request to login API
headers = CaseInsensitiveDict()
headers["Accept"] = "application/json"
headers["Content-Type"] = "application/json"
headers["Authorization"] = "Bearer {token}"
r = requests.post('http://localhost:5000/login', json=data, headers=headers)
if r.status_code==401:
flash("Wrong Roll Number or Password")
elif r.status_code==200:
print("Login correct")
flash("Log In successful")
access_token = r.json()['access_token']
resp = redirect(url_for('home.index'),access_token)
resp.headers = {'Authorization': 'Bearer {}'.format(access_token)}
return resp
print('Login_response',r)
print('Status Code',r.status_code)
print('data',r.text)
return render_template("login.html", form=form)
This is where the login should redirect on successful token generation
#home.route('/')
#home.route('/index')
#jwt_required(optional=True, locations=['headers', 'cookies'])
def index():
logged_in = 0
admin = 0
head = get_jwt_header()
print(head)
identity = get_jwt_identity()
print(identity)
claims = get_jwt()
print('claims:', claims)
if len(claims)!=0:
logged_in = 1
# If user is admin give ability to register
if claims['admin_access']==1:
admin = 1
print("Logged In: ", logged_in)
print("Admin: ", admin)
return render_template('index.html', admin=admin, logged_in=logged_in)
As far as I read should be able to get jwt claims and identity form the stored token, but no matter what I do i can't get this to work. It works in post man through assignment in environment variable. I can't figure out what I'm doing wrong?

How do I make independent API's?

I'm far from being an expert on the topic and my question might even make no sense, but I'm trying to make an app that gathers data from a server I made. There's a Python script I made that logs into a website and scrapes data from it. When you make a GET request to the API, the Python functions get called and the data is put on a server for the app to take. Thing is: whenever a user makes a GET request (or even a POST request, to send the credentials needed for the Python script to log in), the server changes for every user. For example, if a user posts his credentials, the dictionary "credentials" is changed for everyone and if a second user posts his credentials at the same time, the dictionary might get the wrong values for one of the two users. Here's the code:
from flask import Flask, request, jsonify
import backend as b
app = Flask(__name__)
credentials = dict()
subjectNames = ['Italiano', 'Inglese', 'Filosofia', 'Storia', 'Matematica', 'Informatica', 'Fisica', 'Scienze', 'Arte', 'Educazione Fisica']
#app.route('/login', methods=['POST'])
def getCredentials():
if request.method == 'POST':
username = request.get_json(force=True).get('username')
password = request.get_json(force=True).get('password')
credentials['username'] = username
credentials['password'] = password
return jsonify({'credentials': credentials})
#app.route ('/creds', methods=['GET'])
def creds():
return jsonify({'credentials': credentials})
#app.route('/api', methods=['GET'])
def api():
if request.method == 'GET':
query = str(request.args['query'])
if query == 'marks':
d = {}
m = b.getFullMarks(b.login(credentials['username'], credentials['password']))
for i in range(len(subjectNames)):
d[subjectNames[i]] = m[i]
return jsonify(d)
elif query == 'names':
d = {}
m = b.getNames(b.login(credentials['username'], credentials['password']))
for i in range(len(subjectNames)):
d[subjectNames[i]] = m[i]
return jsonify(d)
elif query == 'calendar':
d = {}
m = b.calendar(b.login(credentials['username'], credentials['password']))
d['Calendar'] = m
return jsonify(d)
elif query == 'badge':
d = {}
m = b.badge(b.login(credentials['username'], credentials['password']))
d['Badge'] = m
return jsonify(d)
if __name__ == '__main__':
app.run()
Leaving aside the fact that you keep all of the credentials in memory, and if the server crashes, you lost everything.
You can't use a dictionary to do as you want, as you already know, a dictionary can only hold a single representation of the same key (in our case, 'username'). so when a 2nd user calls the /login endpoint, you're overwriting the previous one and vice versa.
As mentioned before, most applications will generate a token on a successful login, and will send it back to the calling user.
The user will add it as a header on his upcoming requests, this allows the service to identify the calling user, and do whatever it needs.
You can look for existing implementations, or do something on your own.
but eventually, you'll need to map the token to the user, e.g:
#app.route('/login', methods=['POST'])
def getCredentials():
if request.method == 'POST':
username = request.get_json(force=True).get('username')
password = request.get_json(force=True).get('password')
token = generate_token_for_user(username, password)
credentials[token] = {'username': username, 'password': password}
return jsonify({'token': token})
and in the api call:
#app.route('/api', methods=['GET'])
def api():
token = request.headers['Authorization'] # assuming you're using this for your token
creds = credentials.get(token)
d = {}
if request.method == 'GET':
query = str(request.args['query'])
if query == 'marks':
m = b.getFullMarks(b.login(creds['username'], creds['password']))
for i in range(len(subjectNames)):
d[subjectNames[i]] = m[i]
return jsonify(d)
elif query == 'names':
m = b.getNames(b.login(creds['username'], creds['password']))
for i in range(len(subjectNames)):
d[subjectNames[i]] = m[i]
return jsonify(d)
elif query == 'calendar':
m = b.calendar(b.login(creds['username'], creds['password']))
d['Calendar'] = m
return jsonify(d)
elif query == 'badge':
m = b.badge(b.login(creds['username'], creds['password']))
d['Badge'] = m
return jsonify(d)
Offcourse, that maintaining a token lifecycle is a bit more complex, need to invalidate the token after a period of time, and you'll need to validate it on every request (usually with a middleware), but this is the concept.

Way2SMS python code not sending SMS whereas POSTS returns Success

I get Successful status code for my POST requests , Login is working fine , but the SMS is not sent
I have gone through all codes on internet, most of them are out-dated, as the site has changed its code.
import requests as req
def login_way2sms():
with req.Session() as mySession:
url = 'http://www.way2sms.com/re-login'
home_url = 'http://www.way2sms.com/'
mobile = [your registered mobile number]
password = [your password]
headers = dict(Referrer="http://www.way2sms.com/")
before = mySession.get(home_url)
login_data = dict(mobileNo=mobile, password=password, CatType='', redirectPage='', pid='')
mySession.post(url, data=login_data, headers=headers)
after = mySession.get(home_url)
return mySession
def send_msg(mysession): #saw sendsms-toss in Inspect under Network tab
url = 'http://www.way2sms.com/smstoss'
home_url = 'http://www.way2sms.com/'
sms_url = 'http://www.way2sms.com/send-sms'
group_contact_url = 'http://www.way2sms.com/GroupContacts'
web_msg_count_url = 'http://www.way2sms.com/CheckWebMsgCount'
headers = dict(Referrer="http://www.way2sms.com/send-sms")
before = mysession.get(home_url)
token = '2B7CF7C9D2F14935795B08DAD1729ACF'
message = 'How to make this work?'
mobile = '[a valid phone number]'
ssaction = 'undefined'
senderid = 'WAYSMS'
msg_data = dict(Token=token, message=message, toMobile=mobile, ssaction=ssaction, senderId=senderid)
mysession.post(url, data=msg_data, headers=headers)
after = mysession.get(home_url)
mysession.post(group_contact_url, headers=headers)
group_contacts = mysession.get(sms_url)
mysession.post(web_msg_count_url, headers=headers)
web_msg_count = mysession.get(sms_url)
# last 2 POST requests send after clicking the Send Msg button
def main():
login_way2sms() #login using username and password
send_msg(currsession) #send sms
main()
I finally got it right , Thanks for replying. We can do it without using the apikey and secret keys as well, Here take a look at this. And init is just another script where constant urls and login is defined, nothing much there.
import requests as req
import init
def login_way2sms(credential):
with req.Session() as mySession:
mobile = credential.username
password = credential.password
headers = dict(Referrer="http://www.way2sms.com/")
login_data = dict(mobileNo=mobile, password=password, CatType='', redirectPage='', pid='')
mySession.post(init.login_url, data=login_data, headers=headers)
return mySession
def get_token(mysession):
cookies = mysession.cookies['JSESSIONID']
token = cookies[4:]
return token
def send_msg(mysession, token):
"""
:rtype: req.Session()
"""
headers = dict(Referrer="http://www.way2sms.com/send-sms")
message = 'Hi, I am Upgraded a little!!!'
mobile = '[valid phone]'
msg_data = dict(Token=token, message=message, toMobile=mobile, ssaction=init.ssaction, senderId=init.senderid)
mysession.post(init.sms_url, data=msg_data, headers=headers)
def main():
credential = init.enter_credentials()
currsession = login_way2sms(credential)
reply = currsession.get(init.home_url)
page_content: str = str(reply.content)
if (reply.status_code == 200) and (page_content.find('send-sms', 10, 200) != -1):
print("Login Successful!\n")
else:
print("Login Failed , Try again\n")
credential = init.enter_credentials()
currsession = login_way2sms(credential)
token = get_token(currsession)
send_msg(currsession, token)
main()
The following method and code worked for me after creating a free account at way2sms (I hope you already did it). Then click on API tab then campaign at left. Then create test API and Secret Key (free with 25 message limit). Then use the following code--
import requests
import json
URL = 'http://www.way2sms.com/api/v1/sendCampaign'
# get request
def sendPostRequest(reqUrl, apiKey, secretKey, useType, phoneNo, senderId, textMessage):
req_params = {
'apikey':'your_apiKey',
'secret':'your_secretKey',
'usetype':'stage'
'phone': 'receiving_phone_number',
'message':'The textMessage I want to send',
'senderid':'Your Name'
}
return requests.post(reqUrl, req_params)
# get response
response = sendPostRequest(URL, 'provided-api-key', 'provided-secret', 'prod/stage', 'valid-to-mobile', 'active-sender-id', 'message-text' )
"""
Note:-
you must provide apikey, secretkey, usetype, mobile, senderid and message values
and then requst to api
"""
# print response if you want
print response.text
Just fill the fields and run in python 2.7. Working perfectly on any Indian number.

Middleware logging limitation Django 1.11

Background:
I have integration test which is working fine, but later on failed when I
added the customized middleware
def test_mobile_update_customer(self):
user = User.objects.create(username='warhead')
self.client.force_authenticate(user=user)
mommy.make(Customer, family_name='IBM', created_user=self.soken_staff, updated_user=self.soken_staff)
data = {
"family_name": "C0D1UM"
}
customer = Customer.objects.first()
res = self.client.patch(reverse('api:customer-detail', kwargs={'pk': customer.id}), data=data)
self.assertEqual(200, res.status_code)
customer.refresh_from_db()
self.assertEqual('C0D1UM', customer.family_name)
self.assertEqual('spearhead', customer.created_user.username)
self.assertEqual('warhead', customer.updated_user.username)
Problem:
The middleware break it with Exception
File "/Users/el/Code/norak-cutter/soken/soken-web/soken_web/middleware.py", line 47, in process_request
data['PATCH'] = json.loads(request.body)
File "/Users/el/.pyenv/versions/soken/lib/python3.6/site-packages/django/http/request.py", line 264, in body
raise RawPostDataException("You cannot access body after reading from request's data stream")
django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
The problem is data has been read before the RESTful api do the job.
Then the program raises an exception.
def process_request(self, request):
if request.path.startswith('/api/'):
data = collections.OrderedDict()
data["user"] = request.user.username
data["path"] = request.path
data["method"] = request.method
data["content-type"] = request.content_type
if request.method == 'GET':
data['GET'] = request.GET
elif request.method == 'POST':
data['POST'] = request.POST
# https://stackoverflow.com/questions/4994789/django-where-are-the-params-stored-on-a-put-delete-request
# elif request.method == 'PUT':
# data['PUT'] = json.loads(request.body)
# test_mobile_update_customer
# raise RawPostDataException("You cannot access body after reading from request's data stream")
# django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
# elif request.method == 'PATCH':
# data['PATCH'] = json.loads(request.body)
elif request.method == 'DELETE':
pass
self.__uuid = str(uuid.uuid4())
request_logger.info(f'{self.__uuid} {json.dumps(data)}')
Update2
Attempt:
I change client constructor refer to https://github.com/encode/django-rest-framework/issues/2774
def test_mobile_update_customer(self):
user = User.objects.create(username='warhead')
# self.client.force_authenticate(user=user)
from django.test import Client
client = Client()
client.force_login(user)
mommy.make(Customer, family_name='IBM', created_user=self.soken_staff, updated_user=self.soken_staff)
data = {
"family_name": "C0D1UM"
}
customer = Customer.objects.first()
res = client.patch(reverse('api:customer-detail', kwargs={'pk': customer.id}), data=data, content_type='application/json')
self.assertEqual(200, res.status_code)
customer.refresh_from_db()
self.assertEqual('C0D1UM', customer.family_name)
self.assertEqual('spearhead', customer.created_user.username)
self.assertEqual('warhead', customer.updated_user.username)
It does not work. The Client misinterpret the payload
>>> res.content
b'{"detail":"JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)"}'
Workaround:
I don't know this is correct for all cases or not, but I workaround by this
test.py
https://gist.github.com/elcolie/88eb7c90cfca1c369a020ac232c7fbcc
middleware.py
https://gist.github.com/elcolie/5d9b1a2f890a0efcb46fdb95c0e90908
result.py
https://gist.github.com/elcolie/298e595b404c1a5839ed8dd584d2f07f
Question:
How do I do integration test of PATCH with the same time that testcase will not break by my middleware?
Right now I have to choose either one of them.

Redirect url clashes with flask-;login

I currently have a flask server and an angular js front end on which users can buy things from third party vendors.
These third party vendors have their own payment gateways to which I connect my front end to... So at the point of making the payment, we redirect the user to the payment gateway... Once a payment is made, we have a redirect url on our flask servers that captures the success message (and the payment details).
The issue here is that since we do it on the front end (and since this is a third party's website), the flask-login does not seem to work. We use session to store some of the data of the purchase and thus, we cant seem to be able to connect the product the customer has bought with the transaction he made to buy it!
I have given my apis below:
#api.route('/quoteRequest/',methods = ['POST'])
# #flask_login.login_required
def carquote():
data = request.get_json()
c = quoteController.FUTGENGI(data = data, lob = "Motor", stage="quote")
d = c.finOutput
finalQuotes = []
finalQuotes.append(d)
return Response(json.dumps(finalQuotes),mimetype = "application/json")
#api.route("/proposalRequest/",methods = ['POST'])
def proposalRequest():
data = request.get_json()
current_app.logger.debug(data)
c = quoteController.FUTGENGI(data = data, lob = "Motor", stage="proposal")
output = json.loads(c.quoteDict)
session['proposal'][data['Quote']['insurerID']] = data
return Response(json.dumps(output),mimetype = "application/json")
#Redirect URL:
#api.route('/FUTGENGI/policyCreate/', methods = ['GET','POST'])
def policyCreate(insurerID):
if request.method == "GET":
par = OrderedDict(
WS_P_ID = request.args.get('TranID')
TID = request.args.get('UID')
PGID = request.args.get('PaymentID')
Premium = request.args.get('Amt')
Response = request.args.get('Response')
)
if(par['Response'] == "Success"):
for k,v in par.items():
session['proposal']['FUTGENGI'][k] = v
c = quoteController.FUTGENGI(data = session['proposal']['FUTGENGI'], lob = "Motor", stage="payment")
return Response(json.dumps(c.paymentOutput), mimetype = "application/json")
else:
return Response(json.dumps({"output":"Oops. Something went wrong. Please try again"}), mimetype = "application/json")

Categories