I am writing a site for Flask, I have connected Flask-Security and I have a completely different template generated on the user authorization page, can it be connected to routes and how?
Here is the code for the view:
#app.route('/login', methods=['POST', 'GET'])
def login_page():
form = AuthorizationForm()
if form.validate_on_submit():
email = form.email.data
username = form.username.data
password = form.password.data
if email and username and password:
user = User.query.filter_by(email=email).first()
if check_password_hash(user.password, password):
login_user(user)
return redirect(url_for('index_page'))
else:
flash('Неправильний логін або пароль')
else:
flash('Будь ласка,завповніть всі поля')
return render_template('templates/security/login_user.html', title='Авторизація',
form=form, css_link=css_file)
But there is no effect
Help me please
There's a lot of unpack here!
First - you have defined a new form (is it derived from the flask-security LoginForm?); a new template, and a new view - and the view has the same URL as the default Flask-Security /login - not sure which one will take precedence.
Your code example actually has the 'render_template' outside the view code - a cut-n-paste error?
In Flask-Security you can independently override the template (still using the default Login form) or extend the Form (and do your validation in your form::validate method). It should be rare that you have to build your own view.
Related
I'm using Django/Python3 to make a simple API. I already made my models and views (also using serializers). Currently this is my login view:
class LoginView(generics.CreateAPIView):
queryset = User_Login.objects.all()
serializer_class = LoginUserSerializer
def post(self, request, *args, **kwargs):
id = request.data['id']
name = request.data['name']
password = request.data['password']
email = request.data['email']
User_Login.objects.create(id=id, name=name, password=password, email=email)
return HttpResponse({'message': 'User Created', 'id': id}, status=200)
All my views are basic like this, just to implement a database that I previously modeled.
I need to implement authentication (the one that generates simple tokens that the user need to add to their request's header) and I know It's easy, but I followed this tutorial and I got a lot of errors.
Any advice?
I'm looking for an efficient way to check a session variable for each view. I can do it like below per the docs, but is there a global function or decorator that could extract the username without repeating the same lines?
#app.route('/')
def index():
if 'username' in session: # this is repeated in every view
username = session['username'] # this is repeated in every view
return 'You are not logged in'
Your guess is correct. A decorator is a way to review the session and react to the result. In the example below, the user is redirected to the appropriate route based on the decorator if the user is not logged in. If a username is stored in the session, the decorated route is called.
If the login is optional for the respective route, it is public and no decorator is required. But it might be necessary to ask if the user is logged in.
from flask import (
redirect,
session,
url_for
)
from functools import wraps
# ...
def is_authenticated():
username = session.get('username')
return username and len(username.strip()) > 0
def login_required(f):
#wraps(f)
def wrapper(*args, **kwargs):
if not is_authenticated():
return redirect(url_for('login'))
return f(*args, **kwargs)
return wrapper
# Add the state query function to the jinja context.
app.jinja_env.globals.update(is_authenticated=is_authenticated)
#app.route('/login', methods=['GET', 'POST'])
def login():
# your login code here!
#app.route('/secret')
#login_required
def secret():
return 'You are logged in.'
#app.route('/public')
def public():
if is_authenticated():
return 'User is authenticated'
return 'User is not authenticated'
This code is used to check within the template whether the user is logged in.
{% if is_authenticated() %}
User is authenticated.
{% else %}
User is not authenticated.
{% endif %}
If you really want to ask for the session variable before each route, the before_request decorator might be a solution. In this case you cannot avoid storing variables in the g object to use them in your routes. However, this goes beyond your example or unnecessarily complicates the code as it only becomes necessary to use additional data.
I think the code I gave should be enough for simple purposes.
For more complex environments I recommend you take a look at Flask-Login or Flask-Security.
I created a diary web app in Django. It stores all diaries encrypted. I want to ask password when a user tries to view or update or delete his/her diary. It doesn't mean a login is required. I want to ask user's password even though the user login. I tried to create a decorator for this but I couldn't complete it. I have two views:
This view check to password is correct:
def check_master_password_view(request):
page = 'check'
profile = request.user.profile
if request.method == "POST":
checked = check_master_password(request.POST['password'], profile.master_password)
if checked:
return checked # OR Redirect another page
else:
messages.error(request, 'You entered wrong password !')
context = {
'page':page,
}
return render(request, 'users/create_or_check_master_password.html', context)
Another view is detail view:
def detail_diary_view(request, pk):
profile = request.user.profile
diary = profile.diary_set.get(id=pk)
diary.diary = decrypt_diary(request, diary.diary)
context = {
'diary': diary
}
return render(request, 'diary/detail_diary.html', context)
When the user clicks the link to view the diary, I want to show check_master_password view. If the user enters the correct password I want to redirect to the actual page (view, update, delete pages). How can I do this?
Here's the views.py page, which I created separately for the 'login' and 'register' pages.
Here is my login & register pages:
However, it is displayed like so:
Here is my 'urls' page:
I think you have an error in the return redirect part, once the user has logged in , you are again redirecting him/her to login page.
return redirect('login') is incorrect.
Take the reference from the given code base below:
def login(request):
if request.method=='POST':
user = auth.authenticate(username=request.POST['username'],password=request.POST['password'])
if user is not None:
auth.login(request,user)
return redirect('home')
else:
messages.info(request,'Informations are incorrect')
return render(request,'books/home.html')
In your case return redirect() path is wrong, make it correct,
take help from
https://github.com/DextroLaev/Book_Store-Django here.
I have the following test snippet:
def check(username, password):
if username == "b" and password == "password":
return True
return False
#route('/logout')
#route('/logout', method="POST")
def logout():
# template with a logout button
# this does redirect successfully, but this shouldn't happen
redirect('/after-login')
#route('/after-login')
#auth_basic(check)
def after_login():
return "hello"
#route('/login')
#route('/login', method="POST")
def login():
return template("views/login/login_page")
username = post_get('username')
password = post_get('password')
I'm attempting to log out of the system, but I haven't been able to find any resources on how to do this. Basically, I tried dir(response) and dir(request) and haven't found any functions that appears to set the session off (mostly attempting to reset cookies), unless I close the browser.
Issued the same problem. Well, The decision I found in docs and used is response.delete_cookie('<cookiename>')
So every time I enter the page with setting any cookies, first I delete all possibble to change cookies.
You want to log out of HTTP Basic Auth, which is not really what it was designed for. But there does seem to be a way: return an HTTP 401.
from bottle import abort
#route('/logout', method=["GET", "POST"])
def logout():
abort(401, "You're no longer logged in")
Does this work?