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.
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)
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)
We develop web applications to our customers using python/django/angular.
Contact us at hello@cowhite.com