why the flash message is not appear - python-3.x

When i log in the flash message is not diplayed.
How can i fix it?
#app.route('/Login', methods=['GET','POST'])
def show_login():
if request.method == 'POST':
resp = make_response('your email is ' + request.form['email'])
resp.set_cookie('email_user', request.form['email'])
session['username'] = request.form['email']
flash("login is success", "success")
return redirect(url_for('show_profile', username= session['username']))
if 'username' in session:
username = session['username']
return redirect(url_for('show_profile', username=username))
return render_template('inihtml.html')

Can't see your template file? Have you added below code in your template file? flash is just saving the message in session (behind the scene) and you can access that by function get_flashed_messages(). As you are using category as well (Success in your case), so you have to give with_categories = true.
Below code should work for you if you haven't got already in your .html file.
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

Related

Hide buttons if user doesn't belong to any of Django groups

My problem is that I want to hide the button from all users who are not in group1 and group2 or in both groups. I did the following thing but it seems doesn't work at all.
My views.py:
def is_group1(user):
return user.groups.filter(name='Group1').exists()
def is_group2(user):
return user.groups.filter(name='Group2').exists()
def employee_list(request):
groups = [g.name for g in request.user.groups.filter(name__in=['Group1', 'Group2'])]
context = {'employee_list': Employee.objects.filter(dept__in=groups)}
return render(request, 'employee_register/employee_list.html', context)
My little example of employee_list.html:
<form>
{% if user.is_group1 %}
<button formaction="{% url 'employee_insert' %}">Add</button>
{% if user.is_group2%}
<button formaction="{% url 'employee_insert' %}">Add</button>
{% else %}
<p>You are not logged</p>
{% endif %}
</form>
Any thoughts how I can implement this ?
In order to hide a button if a user does not belong to a group, you can implement following method:
First, set-up categories using AbstractUser:
class CustomUser(AbstractUser):
class StatusType(models.Model):
VOLUNTEER = "VOLUNTEER"
MANAGER = "MANAGER"
EMPLOYEE = "EMPLOYEE"
STATUS = [
(MANAGER, "Manager"),
(EMPLOYEE, "Employee"),
(VOLUNTEER, "Volunteer"),
]
status_type = models.CharField(
max_length=50,
choices=StatusType.STATUS,
default=StatusType.VOLUNTEER,
verbose_name="Statut")
Then, in your template, add this to toggle the button:
{% if user.status_type == "MANAGER" %}
<form action="{% url 'interviews:advocacy_topic_create' %}" id="topic-create">
<button type="submit">Create</button>
</form>
{% endif %}
You should not create a view depending on each type of user.

If statement in method in forms.py not processing

I'm having some trouble getting this validation to work. I want the form to only submit if there's a valid .yaml, .yml, or .json at the end of the URL I'm submitting.
forms.py:
class TemplateForm(FlaskForm):
template_url = URLField( 'Template URL', validators=[InputRequired(), URL(message='error')])
submit = SubmitField('Add Template')
def validate_filetype(self, field):
form = TemplateForm
template_path = form.template_url
ext = os.path.splitext(template_path)[1]
if ext not in ('.json', '.yml', '.yaml'):
raise ValidationError('Invalid File Type')
views.py:
#apps.route('/new-template', methods=['GET', 'POST'])
#login_required
#admin_required
def new_template():
"""Add a new app."""
form = TemplateForm()
if form.validate_on_submit():
template_location = form.template_url.data
flash("added template: " + template_location)
template_path = urlparse(template_location).path
ext = os.path.splitext(template_path)[1]
flash("Extension = " + ext )
if ext == '.json':
flash('var = .json')
template_filename = wget.download(template_location, out='app/storage/templates/json')
flash(template_filename)
elif ext in ('.yml', '.yaml'):
flash('var = .yaml')
return redirect(url_for('apps.index'))
return render_template('apps/new_template.html', form=form)
new_index.html:
{% extends 'layouts/base.html' %}
{% import 'macros/form_macros.html' as f %}
{% import 'macros/check_password.html' as check %}
{% block scripts %}
{% endblock %}
{% block content %}
<div class="ui stackable centered grid container">
<div class="twelve wide column">
<a class="ui basic compact button" href="{{ url_for('apps.index') }}">
<i class="caret left icon"></i>
Back to dashboard
</a>
<h2 class="ui header">
New App Template
<div class="sub header">Add a new app template</div>
{% set flashes = {
'error': get_flashed_messages(category_filter=['form-error']),
'warning': get_flashed_messages(category_filter=['form-check-email']),
'info': get_flashed_messages(category_filter=['form-info']),
'success': get_flashed_messages(category_filter=['form-success'])
} %}
{{ f.begin_form(form, flashes) }}
{{ f.render_form_field(form.template_url, extra_classes=novalidate) }}
{{ f.render_form_field(form.submit) }}
{{ f.end_form() }}
</h2>
</div>
</div>
{% endblock %}
No matter what I do I can't get the raise ValidationError('Invalid File Type') to work. I'm trying to just use https://test.com and it won't throw the validation error.
Please let me know if there's anything else I should attach to provide more information. Everything is importing correctly so I'm pretty sure it's not a dependency issue.
This is the boiler plate I'm using: https://github.com/hack4impact/flask-base
This resolved it. Thank you #ngShravil.py I needed to use a custom validator and separate it into it's own method (outside of the class).
def validate_filetype(form, field):
template_path = field.data
ext = os.path.splitext(template_path)[1]
if ext not in ('.json', '.yml', '.yaml'):
raise ValidationError('Invalid File Type')
class TemplateForm(FlaskForm):
template_url = URLField( 'Template URL', validators=[InputRequired(), URL(message='error'), validate_filetype])
submit = SubmitField('Add Template')

Check if a view has a decorator flask

I want to somehow check if a endpoint has a decorator like login_required, is there a way I could do it?
This is how I get all url_rules:
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
def sitemap():
links = []
for rule in
if "GET" in rule.methods and has_no_empty_params(rule):
url = flask.url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
return links
This is my navigation bar in which I use these, but I want to somehow not display the views who have the decorator login_required.
{% for url, endpoint in endpoints %}
{% if request.url_rule != endpoint %}
<a href="{{ url }}">
<button class="tablecontent">{{ endpoint.split('.', 1)[1] }}</button>
</a>
{% endif %}
{% endfor %}
I am sorry for the late edit, but if someone is still here, any help would be appreciated. Or maybe I should better hard code the view names in a dictionary?

slackAPI python propagate message replies under parent messages issue with Jinja in flask

Basically i want to loop through parent messages in a slack channel and fetch parent messages in front end but i also want to check if there are any replies under any parent message and fetch them under the parent message in front end. Bear in mind that there are two methods involved from slack, conversations.history and conversations.replies where conversations.replies requires the parameter of ts (timestamp). So what im trying to do is to check the timestamps of each message and if its found in conversations.replies then propagate the message or at least thats what im trying to do.
python:
#app.route("/", methods=['GET', 'POST'])
def home():
convo_history = client.conversations_history(channel=channel_to_listen)
messages = convo_history['messages']
for thread_ts in messages:
thread_reply = thread_ts['ts']
# app.logger.info(thread_reply)
convo_replies = client.conversations_replies(channel=channel_to_listen, ts=thread_reply)
# app.logger.info(convo_replies)
messages_replies = convo_replies['messages']
assert convo_history['ok']
return render_template('index.html', messages=messages, messages_replies=messages_replies)
Jinja:
{% for message in messages %}
{% if message['ts'] in messages_replies %}
<h2>{{ message['ts'] | ctime}}</h2>
<h3>{{ message['text'] }}</h3>
<h4>{{ messages_replies['text'] }}</h4>
{% else %}
<h2>{{ message['ts'] | ctime}}</h2>
<h3>{{ message['text'] }}</h3>
<br>
{% endif %}
{% endfor %}

current_user.is_authenticated always False (TACACS and flask_login)

Summary
I'm trying to implement a TACACS+ based flask_login system and I'm stuck because the current_user.is_authenticated is always false. I am not using any local databases - the username and password that is submitted via my login form are directly passed to TACACS.
My custom User class implements the 3 attributes and 1 method described in flask_login's documentation here:
Below, you'll find the relevant code for each file so you can set this up in your own environment.
There is a lot of information below, so I wanted to share my actual question as clearly as possible:
How can I connect my custom User class to the current_user proxy?
The underlying issue with my implementation is that when I go to any flask routes with the #login_required decorator, the app thinks the user is not logged in and redirects them to the login page. I've determined it to be because the current_user.is_authenticated attribute is never True.
app.py
from flask import Flask, request, render_template, url_for, flash, redirect, session, Markup
from forms import LoginForm
from flask_login import LoginManager, login_user, logout_user, login_required, current_user, UserMixin
import user_auth as auth
# TODO: Save the user_dict to a pickle file so that users persist between service restarts
user_dict = {}
class User():
def __init__(self, username, password):
self.username = username
self.password = password
# Send TACACS authentication and authorization requests
priv = auth.login(self.username, self.password)
if priv:
self.is_authenticated = True
self.is_active = True
self.is_anonymous = False
if priv == 'admin':
self.priv_lvl = 15
elif priv == 'user':
self.priv_lvl = 10
elif priv == 'employee':
self.priv_lvl = 5
else:
self.is_authenticated = False
self.is_anonymous = True
self.priv_lvl = -1
def get_id(self):
return self.username
app = Flask(__name__)
app.secret_key = 'mysecretkey!'
app.static_url_path = 'static/'
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'index'
#login_manager.user_loader
def load_user(user):
global user_dict
if user in user_dict.keys():
return user_dict[user]
#app.route('/', methods=['GET', 'POST'])
def index():
form = LoginForm()
try:
if user.is_authenticated:
return render_template('test.html')
except UnboundLocalError:
user = None
pass
if form.validate_on_submit():
username = form.username.data
password = form.password.data
user = User(username, password)
username = password = None
print(f"User {user.username} logged in. User authenticated: {user.is_authenticated}")
print(f"Is current_user authenticated? {current_user.is_authenticated}")
if user.priv_lvl >= 0:
# SOLUTION -> The following was missing
login_user(user, remember=form.remember.data)
user_dict.update({
user.username : user
})
# END SOLUTION
print("User is authorized to view test.html.")
return render_template('test.html', current_user=current_user, user=user)
else:
flash(f'Invalid login', 'error')
return render_template('index.html', title='Login Required', form=form, user=user)
return render_template('index.html', title='Login Required', form=form, user=user)
#app.route("/home", methods=['GET'])
#login_required
def home():
return render_template('test.html')
user_auth.py
from tacacs_plus.client import TACACSClient
from tacacs_plus.flags import TAC_PLUS_ACCT_FLAG_START, TAC_PLUS_ACCT_FLAG_WATCHDOG, TAC_PLUS_ACCT_FLAG_STOP
import socket
ISE = 'my.ip.add.rr'
auth_key = 'password'
def login(username, password):
cli = TACACSClient(ISE, 49, auth_key, timeout=10, family=socket.AF_INET)
authen = cli.authenticate(username, password)
if authen.valid:
author = cli.authorize(username, arguments=[b"service=", b"protocol="])
if author.valid:
role = author.arguments[0].decode('utf-8')
if 'user' in role.lower():
priv = 'user'
elif 'admin' in role.lower():
priv = 'admin'
else:
print("User has authenticated successfully, but failed authorization.")
priv = 'employee'
else:
print("User failed authentication.")
priv = None
return priv
forms.py
from flask_wtf import FlaskForm
from wtforms import Form, StringField, SubmitField, BooleanField
from wtforms.fields import PasswordField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
password = PasswordField("Password", validators=[DataRequired()])
remember = BooleanField("Remember Me")
submit = SubmitField("Login")
index.html
<div id='login-container' class='container'>
<form method="POST" action="">
{{ form.csrf_token }}
{{ form.hidden_tag() }}
<fieldset>
<legend class="border-bottom mb-4">Login</legend>
<p>Use your TACACS credentials.</p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alerts">
{% for message in messages %}
<div class="alert alert-warning" role="alert">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class='form-group'>
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class='custom-invalid-feedback'>
{% for error in form.username.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class='form-group'>
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class='custom-invalid-feedback'>
{% for error in form.password.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
{{form.remember.label}}
{{form.remember}}
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</fieldset>
</form>
</div>
test.html
{% if user.is_authenticated %}
<h2>My custom user class is authenticated</h2>
{% else %}
<h2> My custom user class is NOT authenticated</h2>
{% endif %}
{% if current_user.is_authenticated %}
<h2> current_user is authenticated</h2>
{% else %}
<h2>current_user is NOT authenticated</h2>
{% endif %}
requirements.txt (in case you want to test in your own environment)
Jinja2==2.10
dominate==2.5.1
Flask==1.1.1
flask_login==0.5.0
flask_wtf==0.14.3
plotly==4.5.3
tacacs_plus==2.6
WTForms==2.2.1
Note: If you want to test in your own application and don't want to bother with TACACS, manually set priv equal to admin or user
When I login with valid credentials, here is what I see from my console:
User LetMeIn logged in. User authenticated: True
Is current_user authenticated? False
User is authorized to view test.html.
... And on the test.html page in my browser, I see
I figured it out after dissecting my code for the quadrillionth time.
Simply put, I was missing the login_user() function call. This is what associates the custom User class to the flask_login current_user association.
I also needed to create a simple local username storage method so that the required load_user function could work properly. I did this by adding a globally accessible dictionary that stores my custom User object as a value associated to a key that holds the username.
I will update the code snippets in my original post with these changes in hopes that my efforts will be useful for someone in the future. I couldn't find much online about integrating TACACS with flask_login.

Resources