im trying to build an flask application with user authentication. each user has different pages to be shown. the issue im facing is whenever user A logs in his username is saved in session variable and i use this to prevent users toggling through url without logging in first. but whenever user B logs in,user A is able to see what user B can. the previous session data is being over written. it would amazing if anyone can let me know how do i declare another session each time a new user walks in.
from flask import Flask,render_template,redirect,session,request,g,make_response,url_for
import psycopg2
import os
appt = Flask(__name__)
appt.secret_key= os.urandom(16)
conn=psycopg2.connect( database="one",user="postgres",password="0000",host="localhost",port="5432" )
cursor = conn.cursor()
cursor.execute("select username from use")
us=cursor.fetchall()
cursor.execute("select password from use")
psw= cursor.fetchall()
i use the above database data for user authentication
#appt.route('/',methods=['GET','POST'])
def index():
if request.method=='POST':
global user_name
user_name=request.form['username'] # make it global
pass_word=request.form['password']
for i in range(len(us)):
if user_name in us[i][0]:
new=psw[i][0]
if new==pass_word:
print(session.get('user'))
if 'user' not in session:
print('new user')
user = request.form['username'] # setting user to cookie with userid: username
resp = make_response(render_template('monitor.html'))
resp.set_cookie('userID', user) # setting a cookie
print(request.cookies.get('userID'))
return resp
else:
print('old user')
return session.get('user')
else:
return render_template('login.html',info="invalid user")
return render_template('login.html')
#appt.route('/logout', methods=['GET', 'POST'])
def logout():
print("hello")
if g.user:
if request.method == 'GET':
print("hello")
print(session['user'][0])
session.pop('user',None)
return render_template("login.html")
else:
return redirect("monitor.html")
#appt.before_request
def before_request():
#g.user=None
if 'user' in session:
g.user = session['user']
if __name__ == '__main__':
appt.run(debug=True)
Related
I want to make introduction and make bot give role to the user after user introduce himself.
My code is
import discord
from Secret import Token
from discord.ext import commands
from discord.utils import get
bot = commands.Bot(command_prefix='*',intents=discord.Intents.all())
#Introduction
#bot.command(pass_context=True)
async def ind(ctx,user: discord.User = None):
#UserID
if not user:
userId = ctx.author.id
#Name
await ctx.channel.send(f'<#{userId}> Name?')
msg = await bot.wait_for('message')
name = (msg.content)
#Age
await ctx.channel.send(f'<#{userId}> Age?')
msg2 = await bot.wait_for('message')
old = (msg2.content)
#Give Role
role = user.guild.get_role()
user.add_role(1030982386235736064)
#Send Info
channel = bot.get_channel(1030963854450761598)
await channel.send(f'<#{userId}>\nName -> {name}\nAge -> {old}')
await channel.send('------------------------------------------>')
bot.run(Token)
and Its get error after use command
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'guild'
I'm trying to run Quart+Telethon with multiple clients. This example shows one global client. I have this working.
Now I need my app to handle multiple users simultaneously logging in and doing stuff.
This post suggests using asyncio.gather.
How do I need to change my code such that I can have multiple people logging in?
Here I placed the bulk of Quart functionality into the work() function (wherever client is referenced). In the def main() I start the app and then invoke asyncio.gather.
When running the app with two work() functions (two clients) in asyncio.gather I get error "AssertionError: Handler is overwriting existing for endpoint phone_form".
And if I run only with one work() function I get a different error: "ConnectionError('Cannot send requests while disconnected')"
What am I missing?
Thx
import os
import asyncio
from dotenv import load_dotenv
from quart import Quart, render_template_string, request, render_template
from telethon import TelegramClient
load_dotenv('.env')
API_ID = int(os.getenv('API_ID'))
API_HASH = str(os.getenv('API_HASH'))
app = Quart(__name__)
async def work(client):
async with client:
#app.route("/")
async def phone_form():
return await render_template('phone_form.html')
#app.route("/validation_form", methods=['POST'])
async def validation_form():
""" Ask the user for the confirmation code they just got. """
global phone
# Check form parameters (phone/code)
form = await request.form
if 'phone' in form:
phone = form['phone']
await client.send_code_request(phone)
return await render_template('validation_form.html', phone_nr=phone)
async def main():
import hypercorn.asyncio
# create task so that starting hypercorn server is no blocking functions that come after it
server = asyncio.create_task(hypercorn.asyncio.serve(app, hypercorn.Config()))
# have many clients here, using the app asynchronously
await asyncio.gather(
work(TelegramClient('user1', API_ID_, API_HASH)),
work(TelegramClient('user2', API_ID, API_HASH)),
)
# this is to start blocking - means after this subsequent functions will need to wait until hypercorn is finished (hypercorn runs forever!)
# this await also lets server run indefinitely
await server
if __name__ == '__main__':
asyncio.run(main())
The code is trying to set N function handlers to the same routes, that's what causing the error here. I believe you need a different approach here - make adding sessions a continuous process with routes dealing with the last (new) session.
I'm not sure how hypercorn server should be started so using it's part from your example.
eg.
API_ID = int(os.getenv('API_ID'))
API_HASH = str(os.getenv('API_HASH'))
app = Quart(__name__)
clients = []
async def work():
new_cli = None
phone = None
#app.route("/")
async def index():
""" Some page containing 'new session' button redirecting to /phone_form """
new_cli = None
phone = None
return render_template('index.html')
#app.route("/phone_form")
async def phone_form():
num = len(clients) + 1
new_cli = TelegramClient(f'user{num}', API_ID_, API_HASH)
await new_cli.connect()
return await render_template('phone_form.html')
#app.route("/validation_form", methods=['POST'])
async def validation_form():
""" Ask the user for the confirmation code they just got. """
# Check form parameters (phone/code)
form = await request.form
if 'phone' in form:
phone = form['phone']
await client.send_code_request(phone)
return await render_template('validation_form.html', phone_nr=phone)
#app.route("/confirm_code", methods=['POST'])
async def confirm_code():
""" Finish auth process. """
form = await request.form
if 'code' in form:
await new_cli.sign_in(phone, form['code'])
clients.append(new_cli)
new_cli = None
phone = None
async def main():
import hypercorn.asyncio
server = asyncio.create_task(hypercorn.asyncio.serve(app, hypercorn.Config()))
await work()
await server
if __name__ == '__main__':
asyncio.run(main())
You may also want to add checkers if new client session is present. Resulted sessions can be used later.
I would like my bot when I restart it or crash it activates an event that deletes momentary data. I tried using on_disconnect as an event but it doesn't work. In the code below I used on_disconnect as a command but I wish there was an event. It's possible?
async def on_disconnect(ctx):
cursor = levelsystem_db.cursor()
for member in ctx.guild.members:
cursor.execute(f"SELECT * FROM anti_spam WHERE client_id = {str(member.id)}")
result = cursor.fetchall()
print(member, member.id, len(result))
if (len(result) != 0):
cursor.execute(f"DELETE FROM anti_spam WHERE client_id = {str(member.id)}")
levelsystem_db.commit()
print(f"ho rimosso i dati di {member}")
EDIT:
import discord
class Bot(discord.Client):
def __init__(self) -> None:
discord.Client.__init__(self)
return
async def on_ready(self) -> None:
await self.close() # This can simulate a crash for now
return
if __name__ == '__main__':
client = Bot()
client.run(token)
# Code after crash here
print('Bot has crashed')
cursor = levelsystem_db.cursor()
guild = client.get_guild(637626960599842824)
print(guild)
for member in guild.members:
cursor.execute(f"SELECT * FROM anti_spam WHERE client_id = {str(member.id)}")
result = cursor.fetchall()
print(member, member.id, len(result))
if (len(result) != 0):
cursor.execute(f"DELETE FROM anti_spam WHERE client_id = {str(member.id)}")
levelsystem_db.commit()
print(f"ho rimosso i dati di {member}")
If the bot crashes, you can have code after your client.run('TOKEN') that will be executed. For example:
import discord
class Bot(discord.Client):
def __init__(self) -> None:
discord.Client.__init__(self)
return
async def on_ready(self) -> None:
await self.close() # This can simulate a crash for now
return
if __name__ == '__main__':
client = Bot()
client.run('TOKEN')
# Code after crash here
print('Bot has crashed')
With this implementation, you could even call a subprocess that would bring the bot back online.
Edit (Event Loop Error Fix):
You will want to import these:
from asyncio import set_event_loop
from asyncio import SelectorEventLoop
from selectors import SelectSelector
Then have this line before creating the client:
set_event_loop(SelectorEventLoop(SelectSelector()))
I have implemented django rest auth with Allauth and its working fine if I login through google access_token but there is a case when some client device need to login by google id_token.
I am getting error if I use id_token instead of access_token
{
"non_field_errors": [
"Incorrect value"
]
}
please help me out
Update your files like
../allauth/socialaccount/providers/google/provider.py:
class GoogleProvider(OAuth2Provider):
....
def extract_uid(self, data):
try:
return str(data['id'])
except KeyError:
return str(data['user_id'])
../allauth/socialaccount/providers/google/views.py:
class GoogleOAuth2Adapter(OAuth2Adapter):
provider_id = GoogleProvider.id
access_token_url = 'https://accounts.google.com/o/oauth2/token'
authorize_url = 'https://accounts.google.com/o/oauth2/auth'
profile_url = 'https://www.googleapis.com/oauth2/v1/userinfo'
token_url = 'https://www.googleapis.com/oauth2/v1/tokeninfo'
def complete_login(self, request, app, token, **kwargs):
if 'rest-auth/google' in request.path:
print('rest-auth api')
# /api/rest-auth/google
# but not for website login with google
resp = requests.get(self.token_url,
params={'id_token': token.token,
'alt': 'json'})
else:
print('else else rest-auth api')
resp = requests.get(self.profile_url,
params={'access_token': token.token,
'alt': 'json'})
resp.raise_for_status()
extra_data = resp.json()
login = self.get_provider() \
.sociallogin_from_response(request,
extra_data)
return login
oauth2_login = OAuth2LoginView.adapter_view(GoogleOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(GoogleOAuth2Adapter)
For using id_token you will get only these fileds (access_type, audience, email, email_verified, expires_in, issued_at, issued_to, issuer, nonce, scope, user_id, verified_email). So if your user table required phone and name you can set the to empty name='' etc. For this you can use the following code.
Set user model required fields to empty for covering id_token case
It depends upon your user model, in my case we need both phone and name so I have set them empty. If you don't do this you will get failed constraints errors.
../allauth/socialaccount/providers/base.py
class Provider(object):
def sociallogin_from_response(self, request, response):
....
common_fields = self.extract_common_fields(response)
common_fields['name'] = common_fields.get('name', '')
common_fields['phone'] = common_fields.get('phone', '')
common_fields['username'] = uid
....
I have set the username to user id obtained from social platform api. Later I am forcing user to update its details (username, name, phone etc).
I am writing chat app and I need session data in my websocket handler. Problem is that login and logout is done by AJAX request, and updating/clearing cookie cannot be seen by websocket handler - it sees only state from the time website was initially rendered. But it cannot see, when cookie is changed by AJAX request. Do you have any idea, how this can be implemented?
import json
import tornado.web
import tornado.websocket
class BaseHandler(object):
#property
def db(self):
return self.application.db
def get_current_user(self):
id = self.get_secure_cookie('user')
user = self.db.get_user_by_id(id) if id else ''
return user
class JsonHandler(BaseHandler, tornado.web.RequestHandler):
def write(self, response):
if response:
response = json.dumps(response)
TemplateHandler.write(self, response)
#property
def body(self):
return json.loads(self.request.body.decode())
class WebSocketHandler(BaseHandler, tornado.websocket.WebSocketHandler):
pass
class Login(JsonHandler):
def post(self):
login = self.body.get('login')
password = self.body.get('password')
user = self.db.validate_user(login, password)
if user:
self.set_secure_cookie('user', str(user['id']))
self.write(user)
else:
raise tornado.web.HTTPError(401)
class Logout(JsonHandler):
def post(self):
self.clear_cookie('user')
self.write('')
class WebSocket(WebSocketHandler):
clients = set()
def open(self):
WebSocket.clients.add(self)
def on_close(self):
WebSocket.clients.remove(self)
def on_message(self, message):
# how to use method self.get_current_user()
# it uses self.get_secure_cookie('user')
# but it is not updated dynamically by Login and Logout handlers
# because websocket does not share state with them
for client in WebSocket.clients:
client.write_message(message)