Working with decorators in Flask

Decorators in Flask

A decorator is a wonderful ingredient with which you can add more generic flavor to one or more functions. Using decorator, you can implement authentication, authorization, input validation, etc.

Decorator usage for authentication

from functools import wraps
from flask import g, request, redirect, url_for

def login_required(f):
@wraps(f)
def wrap(*args, ** kwargs):
    '''if 'logged_in' in session:
        return f(*args, ** kwargs)'''

    authorization = None
    if "MyToken" in request.headers:
        authorization = request.headers['MyToken']

        user_id = get_from_cache("user-token-%s" % authorization)

        if user_id:
            user_id = int(user_id)
            user_data = get_from_cache("user-data-%s" % user_id)

            if user_data is not None:

                user_data = json.loads(user_data)
                set_user_details_in_session(user_data)
                request.user_id = user_id ## try to understand this line
                session['user_id'] = user_id
                session['email'] = user_data['email']
                return f(*args, **kwargs)
            else:
                return jsonify({"error": "Invalid Token", "status_code": 0}), 400

        else:
            return jsonify({"error": "Invalid Token", "status_code": 0}), 400

    return jsonify({"error": "Authentication failed", "status_code": 0}), 400
return wrap

Now, let us say we have a view called get_profile, and say for instance that view can be called only after the above authentication is passed, then we can add the decorator just above the get_profile view definition as shown below.

@login_required
def update_user_profile():


    request_data = request.form

    user = User()
    response = user.update_user_profile(request_data=request_data, files_data=request.files)

    return myresponse(response)

Decorator usage for authorization

Just like how we created a decorator for authentication, we can create one more for authorization as shown below.

from functools import wraps
from flask import g, request, redirect, url_for

def authorization_required():
    def decorator(f):


        @wraps(f)
        def wrap(*args, ** kwargs):




            user_id = session["user_id"]

            org = validate_user(user_id) //this function contains business specific logic to validate user

            if  "is_active" in org["data"] and org["data"]["is_active"]  == 1:
                return f(*args, **kwargs)
            else:
                return jsonify({
                    "message": org["message"],
                    "error": org["message"],
                    "status_code": 0}), 400
        return wrap
    return decorator

and now if the request to the view get_profile needs needs to get both authenticated and authorized, then we can add both the decorators just about the view get_profile as shown below.

@login_required
@organization_required(admin_required=False)
def get_profile(id)
    request_data = request.form

    user = User()
    response = user.update_user_profile(request_data=request_data, files_data=request.files)

    return myresponse(response)

Recent Posts

Archive

2021
2020
2019
2018
2017
2016
2015
2014

Tags

Authors

Feeds

RSS / Atom