Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Flask role-based authorization
#1
I am working on a script about role-based authorization by using Flask. I am trying to run by gunicorn on Linux Ubuntu 18.02. However, every time I call the script, it does not proceed. Script, my prompt and the output are below.

from flask import Flask, redirect, url_for
from flask_login import LoginManager, UserMixin, login_user, logout_user
from functools import wraps
from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)

# Simulated user database
users_db = {
    'alice': {'password': 'password123', 'role': 'admin'},
    'bob': {'password': 'password123', 'role': 'user'},
}



# Authentication function
def authenticate(username, password):
    user = users_db.get(username)
    if user and user['password'] == password:
        return user
    return None


# Authorization decorator for roles
def role_required(required_role):
    def decorator(f):
        @wraps(f)
        def wrapped(*args, **kwargs):
            if not hasattr(g, 'user') or g.user['role'] != required_role:
                return jsonify({'error': 'Access denied'}), 403
            return f(*args, **kwargs)

        return wrapped

    return decorator


# Login route to simulate authentication
@app.route('/login', methods=['POST'])
def login():
    data = request.json
    username = data.get('username')
    password = data.get('password')
    user = authenticate(username, password)

    if user:
        g.user = user
        return jsonify({'message': 'Login successful'}), 200
    else:
        return jsonify({'error': 'Invalid credentials'}), 401


# Route accessible only by admin
@app.route('/admin', methods=['GET'])
@role_required('admin')
def admin_route():
    return jsonify({'message': 'Welcome, admin!'}), 200


# Route accessible by any authenticated user
@app.route('/user', methods=['GET'])
def user_route():
    if not hasattr(g, 'user'):
        return jsonify({'error': 'Unauthorized'}), 401
    return jsonify({'message': f"Welcome, {g.user['role']}!"}), 200


if __name__ == '__main__':

    app.run(debug=True)
Here is the call on terminal

>> gunicorn Authorization:app

and the output after calling the script.
Error:
[2024-05-03 14:34:07 +0200] [27712] [INFO] Starting gunicorn 21.2.0 [2024-05-03 14:34:07 +0200] [27712] [INFO] Listening at: http://127.0.0.1:8000 (27712) [2024-05-03 14:34:07 +0200] [27712] [INFO] Using worker: sync [2024-05-03 14:34:07 +0200] [27715] [INFO] Booting worker with pid: 27715
Then, I have to stop by ctrl+C.
Reply
#2
Although I do not have a role system setup, here is a basic example that I was playing around with a while back.
Hope it helps.
I installed gunicorn in the venv and it ran fine. On a side note you can also use pkill gunicorn to kill the server

database.py
import sqlite3 


class Database:
    def __init__(self):
        self.connection = sqlite3.connect('users.db')
        self.cursor = self.connection.cursor()

    def getuser(self, user, passwd):
        query = f'select user, password from users where user="{user}" and password="{passwd}"'
        return self.cursor.execute(query).fetchone()
app.py
import sqlite3
from flask import (Flask , render_template, url_for, request, 
flash, redirect, session)
from database import Database

app = Flask(__name__)
app.secret_key = 'my secret key'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/form')
def form():
    return render_template('form.html')

@app.route('/validate', methods=['POST', 'GET'])
def validate():
    if request.method == 'POST':
        user = request.form['user']
        passwd = request.form['mypass']
        db = Database()

        data = db.getuser(user, passwd)
        if data != None:
            if data[0] == user.lower() and data[1] == passwd:
                session['user'] = data[0]
                session['password'] = data[1]
                session['role'] = data[2]
                flash(f'Hello {data[0]}')
                return redirect(url_for('success'))
            
        flash(f'Sorry, username, password combination does not exist.')
        return redirect(url_for('error'))

@app.route('/error')
def error():
    return render_template('error.html')

@app.route('/success')
def success():
    return render_template('success.html')

@app.route('/logout')
def logout():
    session.pop('user', None)
    session.pop('password', None)
    session.pop('role', None)
    return redirect(url_for('index'))


if __name__ == '__main__':
    app.run(debug=True)
In templates folder
error.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {% with messages = get_flashed_messages() %}
    {% if messages %}

        {% for message in messages %}
        <p style="background-color: orange; color: navy; padding:8px;">{{ message }}</p>
        {% endfor %}

    {% endif %}
    {% endwith %}
<a href="{{url_for('form')}}">Login</a><br />
<a href="{{url_for('index')}}">Index</a>
</body>
</html>
form.html
<form action="{{url_for('validate')}}" method="post">
    <table>
        <tr>
            <td>User:</td><td><input type="text", name="user"></td>
        </tr>
        <tr>
            <td>Password:</td><td><input type="password" name="mypass"></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit"></td>
        </tr>
    </table>
</form>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FlaskBlog</title>
</head>
<body>
   <h1>Welcome to Flask</h1>
   <a href="{{url_for('form')}}">Login</a>
</body>
</html>
success.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Success Page</h1>
    {% with messages = get_flashed_messages() %}
    {% if messages %}

        {% for message in messages %}
        <p style="background-color: orange; color: navy; padding: 8px;">{{ message }}</p>
        {% endfor %}
 
    {% endif %}
    {% endwith %}
   <a href="{{url_for('index')}}">Logout</a>

</body>
</html>
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#3
(May-03-2024, 07:08 PM)menator01 Wrote: Although I do not have a role system setup, here is a basic example that I was playing around with a while back.
Hope it helps.
I installed gunicorn in the venv and it ran fine. On a side note you can also use pkill gunicorn to kill the server

I tried to execute both your and my code in venv.

Output when I run your code

Error:
[2024-05-04 19:09:22 +0200] [22308] [INFO] Starting gunicorn 21.2.0 [2024-05-04 19:09:22 +0200] [22308] [INFO] Listening at: http://127.0.0.1:8000 (22308) [2024-05-04 19:09:22 +0200] [22308] [INFO] Using worker: sync [2024-05-04 19:09:22 +0200] [22311] [INFO] Booting worker with pid: 22311 [2024-05-04 19:09:22 +0200] [22311] [ERROR] Exception in worker process Traceback (most recent call last): File "/usr/local/lib/python3.6/dist-packages/gunicorn/arbiter.py", line 609, in spawn_worker worker.init_process() File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 134, in init_process self.load_wsgi() File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 146, in load_wsgi self.wsgi = self.app.wsgi() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 58, in load return self.load_wsgiapp() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp return util.import_app(self.app_uri) File "/usr/local/lib/python3.6/dist-packages/gunicorn/util.py", line 371, in import_app mod = importlib.import_module(module) File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 994, in _gcd_import File "<frozen importlib._bootstrap>", line 971, in _find_and_load File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked ModuleNotFoundError: No module named 'Authorization_3' [2024-05-04 19:09:22 +0200] [22311] [INFO] Worker exiting (pid: 22311) [2024-05-04 19:09:22 +0200] [22308] [ERROR] Worker (pid:22311) exited with code 3 [2024-05-04 19:09:22 +0200] [22308] [ERROR] Shutting down: Master [2024-05-04 19:09:22 +0200] [22308] [ERROR] Reason: Worker failed to boot.
And, here is the output when I run mine

Error:
[2024-05-04 19:07:15 +0200] [22246] [INFO] Starting gunicorn 21.2.0 [2024-05-04 19:07:15 +0200] [22246] [INFO] Listening at: http://127.0.0.1:8000 (22246) [2024-05-04 19:07:15 +0200] [22246] [INFO] Using worker: sync [2024-05-04 19:07:15 +0200] [22249] [INFO] Booting worker with pid: 22249 [2024-05-04 19:07:15 +0200] [22249] [ERROR] Exception in worker process Traceback (most recent call last): File "/usr/local/lib/python3.6/dist-packages/gunicorn/arbiter.py", line 609, in spawn_worker worker.init_process() File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 134, in init_process self.load_wsgi() File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 146, in load_wsgi self.wsgi = self.app.wsgi() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 58, in load return self.load_wsgiapp() File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp return util.import_app(self.app_uri) File "/usr/local/lib/python3.6/dist-packages/gunicorn/util.py", line 371, in import_app mod = importlib.import_module(module) File "/usr/lib/python3.6/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 994, in _gcd_import File "<frozen importlib._bootstrap>", line 971, in _find_and_load File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked ModuleNotFoundError: No module named 'Authorization_2' [2024-05-04 19:07:15 +0200] [22249] [INFO] Worker exiting (pid: 22249) [2024-05-04 19:07:15 +0200] [22246] [ERROR] Worker (pid:22249) exited with code 3 [2024-05-04 19:07:15 +0200] [22246] [ERROR] Shutting down: Master [2024-05-04 19:07:15 +0200] [22246] [ERROR] Reason: Worker failed to boot.
Reply
#4
(May-03-2024, 07:08 PM)menator01 Wrote: Although I do not have a role system setup, here is a basic example that I was playing around with a while back.
Hope it helps.
I installed gunicorn in the venv and it ran fine. On a side note you can also use pkill gunicorn to kill the server

I just figured my major problem, since I am still a bit stranger to run Flask app. I ran your code again by http://localhost:5000/, and the snapshots are attachd

Attached Files

Thumbnail(s)
       
Reply
#5
It works for me.
I've edited app.py a little

I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#6
(May-04-2024, 06:18 PM)erdemath Wrote:
(May-03-2024, 07:08 PM)menator01 Wrote: Although I do not have a role system setup, here is a basic example that I was playing around with a while back.
Hope it helps.
I installed gunicorn in the venv and it ran fine. On a side note you can also use pkill gunicorn to kill the server

I just figured my major problem, since I am still a bit stranger to run Flask app. I ran your code again by http://localhost:5000/, and the snapshots are attachd

Directory structure

Attached Files

Thumbnail(s)
   
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#7
OK, it also finally worked for me. Thank you so much.

Now, the next question. How would you define users with their activities? Some dictionary, or and html list of people with their usernames?
Reply
#8
(May-04-2024, 06:38 PM)erdemath Wrote: OK, it also finally worked for me. Thank you so much.

Now, the next question. How would you define users with their activities? Some dictionary, or and html list of people with their usernames?

Not sure I understand the question.
Pages visited or something of that nature?
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#9
I see that you enter your name as ''username'' with some password. How does the script recognize you are the admin? Did you pre-define that specific username with its password somewhere in the script?
Reply
#10
It's one of the fields in the database. It is retrieved when getting a valid user. I then set it as a session variable.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Flask with paramiko based ssh client gives gevent LoopExit exception hbknjr 3 4,852 Dec-25-2018, 07:48 AM
Last Post: hbknjr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020