Flask-Session: How to uniquely identify between the different user's session data on a single browser - session-cookies

I wrote a small flask app for a shopping cart and user login.
I used the flask-session extension and sqlite3 for the
The problem I faced.
I logged in as user A, and I added some items to the cart.
Then I logged out from the app and logged in as another user B from the same browser.
I did not close the browser. Now when I checked the cart, I could see the items that
user A had added to his cart.
This is not what I expected, essentially I should have got an empty cart.
Kindly let me know what mistake I made.
I am pasting the code below that I used.
from flask import Flask, render_template, redirect, url_for, request, session
from flask_session import Session
import sqlite3
app = Flask(__name__)
app.config['SECRET_KEY'] = "ASecretKey-1"
app.config['SESSION_PERMANENT'] = True
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
def connectDB():
dbObj = sqlite3.connect('shoppingCart.db')
dbObj.row_factory = sqlite3.Row
cur = dbObj.cursor()
return (dbObj, cur)
def disConnectDB(dbObj, cur):
cur.close()
dbObj.close()
del cur, dbObj
#app.route('/')
#app.route('/home')
def home():
if not session.get('userName'):
return render_template('login.html', pageTitle='Login Page')
dbObj, cur = connectDB()
data = cur.execute('SELECT rowid, * FROM inventory').fetchall()
disConnectDB(dbObj, cur)
contextValues=dict(pageTitle='HomePage', data=data, userName=session.get('userName'))
return render_template('home.html', **contextValues)
#app.get('/login')
#app.post('/login')
def login():
userName = request.form.get('userName')
password = request.form.get('password')
if (not userName) or (not password):
return "<h1 style='color:darkorange'>Form incomplete.</h1>"
else:
dbObj, cur = connectDB()
data = cur.execute("SELECT * FROM users WHERE userName =? AND password=?", (userName,password,)).fetchone()
disConnectDB(dbObj, cur)
print("*"*25,data)
if data:
session['userName'] = userName
if not session.get('cart'):
session['cart'] = []
else:
return "<h1 style='color:darkorange'>Incorrect Credentials.</h1>"
return redirect(url_for('home'))
#app.route('/logout')
def logout():
session.pop('userName')
return redirect(url_for('home'))
#app.route('/cart')
def cart():
cart = session.get('cart')
return render_template('cart.html',pageTitle='cart',cart=cart)
#app.route('/addtocart', methods=['GET','POST'])
def addtocart():
if session.get('userName'):
qty = int(request.form.get('qty'))
itemID = request.form.get('itemID')
dbObj, cur = connectDB()
itemData = cur.execute("SELECT * FROM inventory WHERE rowid=?",(itemID,)).fetchone()
itemName= itemData['Item']
price = itemData['Price']
available_quantity=itemData['Quantity']
if available_quantity - qty >= 0:
available_quantity = available_quantity-qty
session['cart'].append([itemName,qty,price*qty])
cur.execute("UPDATE inventory SET Quantity=? WHERE rowid=?",(available_quantity,itemID,))
dbObj.commit()
disConnectDB(dbObj, cur)
return render_template('addtocart.html', pageTitle='Added to cart', itemName=itemName, quantity=qty)
else:
disConnectDB(dbObj, cur)
return "<h1 style='color:darkorange'>Insufficent quantity! Item cannot be added!</h1><br><a href='/home'>Return to home page</a>"
else:
return "<h1 style='color:darkorange'>You are not authorized to visit this page!</h1><a href='/home'>Return to login page</a>"

When a user uses your /logout route, you just clear the userName key from the session, but the cart is still stored in the session. The session is tied to the browser, and it will retain whatever is left in it. When the same browser logs in later, the cart data is still in the session.
The simplest, safest way to fix that is to call session.clear() any time the session should be invalidated. That will remove all data from the session, giving you a clean slate. I would do that in the /logout route and at the beginning of any successful login attempt (before setting the userName and initial cart list). If you don't clear the session on login, then a logged in user could go to the login page without logging out, log in as a different user, and have the first user's cart still in the session. That is unlikely to happen, but it shouldn't be possible in any case.

Related

How to deploy a model having no predict attribute?

app.py
from flask import Flask, jsonify, request,render_template
import pickle
app = Flask(__name__,template_folder='template')
# load model
model = pickle.load(open("model.pkl",'rb'))
# app
#app.route('/')
def home():
return render_template('recommendation.html')
# routes
#app.route('/api', methods=['POST'])
def predict():
result=request.form
query_user_name=result["user name"]
user_input = {'query':query_user_name}
output_data=model(query_user_name)
print(output_data)
# send back to browser
output ={output_data}
return f'<html><body><h1>{output_data}</h1><form action="/"><button type="submit">back </button> </form></body></html>'
if __name__ == '__main__':
app.run(debug=True)
I am deploying it using a model made from following function,not a pre-existing model having predict attribute.
def model(user):
recommended_list=[]
top_list=[]
x = data.iloc[data.loc[data.Users == user].index[0],2:]
similar = np.array([(data.iloc[i,0],weight_factor(x,data.iloc[i, 2:])) for i in range(0,data.shape[0],1)])
index= np.argsort( similar[:,1] )
index=index[::-1]
similar=similar[index]
neighbours = similar[similar[:,1].astype(float) > 0.6] #Taking threshold as 0.6
for i in range(0,len(neighbours),1):
for j in range(2,len(data.columns),1):
if data.iloc[data.loc[data.Users == neighbours[i][0]].index[0],j]==1 and data.iloc[data.loc[data.Users == user].index[0],j]==0:
recommended_list.append(data.columns[j])
if (len(neighbours)>10):
for i in range(0,10,1): #Top 10 neighbours
top_list.append(neighbours[i][0])
else:
for i in range(len(neighbours)):
top_list.append(neighbours[i][0])
if user in top_list: #Remove the user of which we are asked to find neighbours,each user is always strongly correlated with itself and its of no use to us.
top_list.remove(user)
print(" ")
print("Top users similar to this user are:")
print(" ")
for i in range(0,len(top_list),1):
print(top_list[i])
print(" ")
print("Users similar to this user liked these products too:")
print(" ")
recommended_array=np.unique(np.array(recommended_list))
for i in range(0,len(recommended_array),1):
print(recommended_array[i])
How to deploy it using flask,my output is not being shown in the window,though on deploying the home page is being shown and input is being taken.
your function "model(user)" must return somethings
example:
def model(user):
# code
return somethings

SCIM userName in PATCH operation

I have implemented user provisioning/deprovisioning with SCIM like so :
users_controller.rb
class Scim::UsersController < Scim::ScimController
before_action :set_scim_provider
def index
startIndex = params[:startIndex].to_i
startIndex = 1 if startIndex < 1# if the user send a startIndex < 1, it is bad data, we don't take it.
itemsPerPage = params[:count].to_i
if itemsPerPage < 1 || itemsPerPage > #scim_provider.max_results
itemsPerPage = #scim_provider.default_number_of_results
end
scim_users = #scim_provider.identity_provider.communaute_accesses.from_scim
if params["filter"]
parser = Scim::QueryFilter::Parser.new
rpn_array = parser.parse(params["filter"])
tree = parser.tree
if tree.length == 3 and tree[0]== 'eq' and tree[1] == 'userName'
userName = tree[2]
scim_users = scim_users.where(provider_identifier: userName.delete('"'))
else
fail 'e'
end
end
paginated_users = scim_users.order(:created_at).offset(startIndex - 1).limit(itemsPerPage)
r = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": scim_users.size,
"Resources": paginated_users.map { |ca| #scim_provider.representation_for_user(ca) },
"startIndex": startIndex,
"itemsPerPage": itemsPerPage
}
render_json_result(r, 200)
end
def create
if #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
render_409_conflict("uniqueness")
else
ca = #scim_provider.identity_provider.communaute_accesses.find_by(provider_identifier: #body_params['userName'], communaute_id: #scim_provider.identity_provider.communaute.id)
if ca.nil?
ca = #scim_provider.identity_provider.communaute_accesses.create(provider_identifier: #body_params['userName'], communaute_id: #scim_provider.identity_provider.communaute.id)
end
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
ca.queue_send
end
render_json_result(#scim_provider.representation_for_user(ca), 201)
end
def show
user = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
if user
render_json_result(#scim_provider.representation_for_user(user), 200)
else
render_404_not_found(params[:id])
end
end
def update
ca = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
uc = UserCommunaute.find_by(provider_identifier: #body_params['userName'])
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
unless ca.nil?
if ca.pending?
ca.update_last_raw_value("scim", #body_string)
ca.update(active: false)
if ca.active == false
fail "Unable to delete this user because of activeness" if ca.active == true
ca.destroy!
end
render_json_result(#scim_provider.representation_for_communaute_access_patch(ca), 200)
end
end
unless uc.nil?
uc.update(active: #body_params['active'])
if uc.active == false
uc.user.communaute_accesses.from_scim.destroy_all
uc.user.user_communautes.from_scim.destroy_all
render_json_result(#scim_provider.representation_for_user_communaute_patch(uc), 200)
end
end
end
end
Explanations:
When updating a user, SCIM sends a PATCH request like this:
{"schemas"=>["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations"=>[{"op"=>"Replace", "path"=>"active", "value"=>"False"}]} (#body_params in the code)
Which is what i am expecting. But, for a while, i was receiving the userName also in the body response during the PATCH operation.
This is how I fetch the correct user in my DB.
Actual result:
I don't receive the userName anymore when SCIM hits my update action.
Expected results:
Being able to receive information about the user during the PATCH operation to fetch the userName and find the right user in my database.
I have tried almost everything. When SCIM hits the index action, which it does everytime before going anywhere else, it does return me a userName et everything ends up as a 200 OK.
Then, when passing through update, it sends me nothing.
What I have tried last is to isolate the userName as an instance variable in the index action to fetch it after in the update like so:
# index
...
if params["filter"]
parser = Scim::QueryFilter::Parser.new
rpn_array = parser.parse(params["filter"])
tree = parser.tree
if tree.length == 3 and tree[0]== 'eq' and tree[1] == 'userName'
#user_name = tree[2]
scim_users = scim_users.where(provider_identifier: #user_name.delete('"'))
else
fail 'e'
end
end
...
# update
def update
ca = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #user_name)
uc = UserCommunaute.find_by(provider_identifier: #user_name)
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
...
But, #user_name in update seems to disappear as its value is nil.
I am deprovisioning from Azure Active Directory and Okta in a production environment.
Mapping is ok in both platforms.
Provisioning is working like a charm.
Please refer to https://developer.okta.com/docs/reference/scim/scim-20/#update-a-specific-user-patch for PATCH /Users/{userId}. Could you not make use of the userId in the url to identify the user ?

Basic Twitter Data Mining Causing Problem

This is my first attempt to extract tweets using twitter api and tweepy. When I execute my code it keep printing 401 every time in a new line. What am I doing wrong is I am not able to figure out. Any help is appreciated.
import tweepy
import json
access_token = ""
access_token_secret = ""
consumer_key = ""
consumer_secret = ""
auth = tweepy.OAuthHandler(consumer_key,consumer_secret)
auth.set_access_token(access_token,access_token_secret)
class MyStreamListener(tweepy.StreamListener):
def __init__(self, api=None):
super(MyStreamListener, self).__init__()
self.num_tweets = 0
self.file = open("tweets.txt", "w")
def on_status(self, status):
tweet = status._json
self.file.write( json.dumps(tweet) + '\n' )
self.num_tweets += 1
if self.num_tweets < 100:
return True
else:
return False
self.file.close()
def on_error(self, status):
print(status)
l = MyStreamListener()
stream=tweepy.Stream(auth,l)
stream.filter()
tweets_data_path = 'tweets.txt'
tweets_file = open(tweets_data_path, "r")
tweets_data = []
for line in tweets_file:
tweet = json.loads(line)
tweets_data.append(tweet)
tweets_file.close()
print(tweets_data[0].keys())
Go to your twitter account settings and change timezone to that as of your computer. Then, go to twitter app settings and generate new consumer key and new access token. These newly generated keys and tokens you should use to avoid 401 error.

How to write query in grails controller

I am using grails 1.3.7. I am sending username and password from my view page to controller. And it's rendering correctly on browser. But I need to write query for collect data with that username and password from database. But I have no idea how to write query in grails controller. Can anyone please help me on this ? Here is my action below where I want to write query for logging in to the home page >>>
def loginAction = {
def username = params?.username
def password = params?.password
def val = username + " --- " +password
render val
}
Something like:
def loginAction = {
def username = params?.username
def password = params?.password
User user = User.findByUsername(username)
def val = user?.password == password ? 'Valid' : 'Invalid'
render val
}
But you really should read docs for GORM - http://grails.org/doc/latest/guide/GORM.html

User.get () is broken in Grails 2.0, returns me null

I have been struggling for days to return the user but I do not want, I pass the id of this logged in, but it returns null. Someone else has this happened?
println "User ID: ${springSecurityService.principal.id}" //If you print the Id
def id = springSecurityService.principal.id
def user = User.get(id)
println "User: ${user}" // Not found, it prints null
I need help...
thanks..
According to the documentation, you should be able to just do:
def user = springSecurityService.currentUser

Resources