### Granular Resource Protection Example Source: https://pythonhosted.org/Flask-Principal/index Demonstrates how to implement fine-grained access control for blog posts, allowing only the author to edit their own articles. ```APIDOC ## Granular Resource Protection This section details how to implement granular resource protection, such as allowing only the author of a blog post to edit it. ### Protected Endpoint Example ```python @app.route('/posts/', methods=['PUT', 'PATCH']) def edit_post(post_id): permission = EditBlogPostPermission(post_id) if permission.can(): # Save the edits ... return render_template('edit_post.html') abort(403) # HTTP Forbidden ``` ### Identity Loading Logic This logic should be placed within your `identity_loaded` signal handler. ```python from collections import namedtuple from functools import partial from flask.ext.login import current_user from flask.ext.principal import identity_loaded, Permission, RoleNeed, \ UserNeed BlogPostNeed = namedtuple('blog_post', ['method', 'value']) EditBlogPostNeed = partial(BlogPostNeed, 'edit') class EditBlogPostPermission(Permission): def __init__(self, post_id): need = EditBlogPostNeed(unicode(post_id)) super(EditBlogPostPermission, self).__init__(need) @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name)) # Assuming the User model has a list of posts the user # has authored, add the needs to the identity if hasattr(current_user, 'posts'): for post in current_user.posts: identity.provides.add(EditBlogPostNeed(unicode(post.id))) ``` ``` -------------------------------- ### Flask-Principal User Information Provider Example Source: https://pythonhosted.org/Flask-Principal/index This example demonstrates how to use the identity-loaded signal from Flask-Principal to enrich the Identity object with user-specific information, such as roles. It connects to the signal and adds UserNeed and RoleNeed objects based on the current user's attributes. This functionality is useful for implementing role-based access control. ```python from flask.ext.login import current_user from flask.ext.principal import identity_loaded, RoleNeed, UserNeed @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name)) ``` -------------------------------- ### Initializing Flask-Principal Extension Source: https://pythonhosted.org/Flask-Principal/index This Python code shows the basic setup for the Flask-Principal extension. It involves creating an instance of the `Principal` class and passing the Flask application instance to it. The `use_sessions` and `skip_static` parameters can be configured for session-based identification and static endpoint handling, respectively. ```python from flask_principal import Principal app = Flask(__name__) principals = Principal(app, use_sessions=True, skip_static=False) ``` -------------------------------- ### Flask-Login and Flask-Principal Authentication Example Source: https://pythonhosted.org/Flask-Principal/index This code snippet shows a hypothetical integration of Flask-Login and Flask-Principal for user authentication. It handles login and logout actions, emitting the identity-changed signal to inform Flask-Principal of authentication status updates. Dependencies include Flask, Flask-Login, Flask-WTF, and Flask-Principal. ```python from flask import Flask, current_app, request, session from flask.ext.login import LoginManager, login_user, logout_user, \ login_required, current_user from flask.ext.wtf import Form, TextField, PasswordField, Required, Email from flask.ext.principal import Principal, Identity, AnonymousIdentity, \ identity_changed app = Flask(__name__) Principal(app) login_manager = LoginManager(app) @login_manager.user_loader def load_user(userid): # Return an instance of the User model return datastore.find_user(id=userid) class LoginForm(Form): email = TextField() password = PasswordField() @app.route('/login', methods=['GET', 'POST']) def login(): # A hypothetical login form that uses Flask-WTF form = LoginForm() # Validate form input if form.validate_on_submit(): # Retrieve the user from the hypothetical datastore user = datastore.find_user(email=form.email.data) # Compare passwords (use password hashing production) if form.password.data == user.password: # Keep the user info in the session using Flask-Login login_user(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) return redirect(request.args.get('next') or '/') return render_template('login.html', form=form) @app.route('/logout') @login_required def logout(): # Remove the user information from the session logout_user() # Remove session keys set by Flask-Principal for key in ('identity.name', 'identity.auth_type'): session.pop(key, None) # Tell Flask-Principal the user is anonymous identity_changed.send(current_app._get_current_object(), identity=AnonymousIdentity()) return redirect(request.args.get('next') or '/') ``` -------------------------------- ### Defining an Identity Loader in Flask-Principal Source: https://pythonhosted.org/Flask-Principal/index This Python snippet illustrates how to define an identity loader function using the `@principals.identity_loader` decorator. This function is executed before each request to identify the current user, returning an `Identity` object. This example uses a simple hardcoded identity 'ali' for demonstration. ```python from flask import Flask from flask_principal import Principal, Identity app = Flask(__name__) principals = Principal(app) @principals.identity_loader def load_identity_from_weird_usecase(): return Identity('ali') ``` -------------------------------- ### Flask-Principal Identity Class Source: https://pythonhosted.org/Flask-Principal/index The Identity class represents a user's identity within the system, typically created upon login or request start. It stores the user ID and authentication type and is used to check permissions via the 'can' method. ```python class flask_principal.Identity(_id_ , _auth_type=None_) Represent the user’s identity. Parameters:| * **id** – The user id * **auth_type** – The authentication type used to confirm the user’s identity. ---|--- The identity is used to represent the user’s identity in the system. This object is created on login, or on the start of the request as loaded from the user’s session. Once loaded it is sent using the identity-loaded signal, and should be populated with additional required information. Needs that are provided by this identity should be added to the provides set after loading. `can`(_permission_) Whether the identity has access to the permission. Parameters:| **permission** – The permission to test provision for. ---|--- ``` -------------------------------- ### Defining an Identity Saver in Flask-Principal Source: https://pythonhosted.org/Flask-Principal/index This Python code demonstrates how to define an identity saver function with the `@principals.identity_saver` decorator. This function is invoked when the user's identity needs to be persisted across requests, typically by storing it in a cookie or session. The example shows saving the identity to a hypothetical `my_special_cookie`. ```python from flask import Flask from flask_principal import Principal, Identity app = Flask(__name__) principals = Principal(app) @principals.identity_saver def save_identity_to_weird_usecase(identity): my_special_cookie['identity'] = identity ``` -------------------------------- ### Principal Extension Initialization Source: https://pythonhosted.org/Flask-Principal/index Details on how to initialize the Flask-Principal extension with the Flask application. ```APIDOC ## Starting the extension ### `Principal(app=None, use_sessions=True, skip_static=False)` **Description:** Initializes the Principal extension for a Flask application. **Parameters:** * **app** (*Flask*): The Flask application instance to extend. * **use_sessions** (*bool*): Whether to use sessions for identifying and storing user identification. Defaults to `True`. * **skip_static** (*bool*): Whether to ignore static endpoints during identity loading. Defaults to `False`. **Example:** ```python from flask import Flask from flask_principal import Principal app = Flask(__name__) principals = Principal(app) ``` ``` -------------------------------- ### Customizing Flask-Principal Identity Loading for Resource Ownership Source: https://pythonhosted.org/Flask-Principal/index This Python code snippet shows how to extend the Flask-Principal identity loading mechanism. It adds custom needs for blog post editing and integrates them with the user's identity based on their authored posts. This requires Flask, Flask-Login, and Flask-Principal. ```python from collections import namedtuple from functools import partial from flask.ext.login import current_user from flask.ext.principal import identity_loaded, Permission, RoleNeed, \ UserNeed BlogPostNeed = namedtuple('blog_post', ['method', 'value']) EditBlogPostNeed = partial(BlogPostNeed, 'edit') class EditBlogPostPermission(Permission): def __init__(self, post_id): need = EditBlogPostNeed(unicode(post_id)) super(EditBlogPostPermission, self).__init__(need) @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): # Set the identity user object identity.user = current_user # Add the UserNeed to the identity if hasattr(current_user, 'id'): identity.provides.add(UserNeed(current_user.id)) # Assuming the User model has a list of roles, update the # identity with the roles that the user provides if hasattr(current_user, 'roles'): for role in current_user.roles: identity.provides.add(RoleNeed(role.name)) # Assuming the User model has a list of posts the user # has authored, add the needs to the identity if hasattr(current_user, 'posts'): for post in current_user.posts: identity.provides.add(EditBlogPostNeed(unicode(post.id))) ``` -------------------------------- ### Identity Loader Decorator Source: https://pythonhosted.org/Flask-Principal/index Documentation for the `@principals.identity_loader` decorator used to define a function for loading user identities. ```APIDOC ## Identity Loader ### `identity_loader(f)` **Description:** A decorator used to define a function as an identity loader. This function is called before each request to determine the current user's identity. **Usage:** Apply this decorator to a function that returns an `Identity` object or `None`. **Example:** ```python from flask import Flask from flask_principal import Principal, Identity app = Flask(__name__) principals = Principal(app) @principals.identity_loader def load_identity_from_session(): # Logic to retrieve user identity, e.g., from session or token user_id = get_user_id_from_session() if user_id: return Identity(user_id) return None ``` ``` -------------------------------- ### Protecting Resources with Flask-Principal Decorator and Context Manager Source: https://pythonhosted.org/Flask-Principal/index This snippet demonstrates how to protect Flask routes using Flask-Principal's decorator and context manager functionalities. It requires users to have an 'admin' role to access protected views. This functionality is specific to Python and Flask. ```python from flask import Flask, Response from flask.ext.principal import Principal, Permission, RoleNeed app = Flask(__name__) # load the extension principals = Principal(app) # Create a permission with a single Need, in this case a RoleNeed. admin_permission = Permission(RoleNeed('admin')) # protect a view with a principal for that need @app.route('/admin') @admin_permission.require() def do_admin_index(): return Response('Only if you are an admin') # this time protect with a context manager @app.route('/articles') def do_articles(): with admin_permission.require(): return Response('Only if you are admin') ``` -------------------------------- ### Identity Saver Decorator Source: https://pythonhosted.org/Flask-Principal/index Documentation for the `@principals.identity_saver` decorator used to define a function for persisting user identities. ```APIDOC ## Identity Saver ### `identity_saver(f)` **Description:** A decorator used to define a function that saves the current identity. This function is called when the identity needs to be persisted for future requests, typically when using session-based identification. **Usage:** Apply this decorator to a function that accepts an `Identity` object and handles its storage. **Example:** ```python from flask import Flask from flask_principal import Principal, Identity app = Flask(__name__) principals = Principal(app) @principals.identity_saver def save_identity_to_cookie(identity): # Logic to save the identity, e.g., to a secure cookie set_cookie('user_identity', identity.id) ``` ``` -------------------------------- ### Protecting a Flask Route with Custom Resource Permissions Source: https://pythonhosted.org/Flask-Principal/index This Python code snippet demonstrates how to protect a Flask route for editing blog posts. It creates an instance of a custom permission class, `EditBlogPostPermission`, on the fly using the post ID and checks if the current user has the necessary permissions before allowing the edit operation. This requires Flask and Flask-Principal. ```python @app.route('/posts/', methods=['PUT', 'PATCH']) def edit_post(post_id): permission = EditBlogPostPermission(post_id) if permission.can(): # Save the edits ... return render_template('edit_post.html') abort(403) # HTTP Forbidden ``` -------------------------------- ### Set Identity Method Source: https://pythonhosted.org/Flask-Principal/index Details on the `set_identity` method used to manually set the current user's identity. ```APIDOC ## Set Identity ### `set_identity(identity)` **Description:** Manually sets the current user's identity. This method is useful in scenarios where identity loading might not be automatic or needs to be overridden. **Parameters:** * **identity** (*Identity*): The `Identity` object to set as the current identity. **Example:** ```python from flask_principal import Identity # Assuming 'identity' is an Identity object obtained elsewhere current_identity = Identity('specific_user_id') principals.set_identity(current_identity) ``` ``` -------------------------------- ### Flask-Principal Signals Source: https://pythonhosted.org/Flask-Principal/index Flask-Principal provides signals for managing identity changes and loading. 'identity_changed' is sent when the request's identity is modified, and 'identity_loaded' is sent after the identity has been initialized for a request. ```python identity_changed Signal sent when the identity for a request has been changed. identity_loaded Signal sent when the identity has been initialised for a request. ``` -------------------------------- ### Flask-Principal IdentityContext Class Source: https://pythonhosted.org/Flask-Principal/index The IdentityContext class provides the context for an identity in relation to a specific permission. It's typically created by Permission.require and acts as a context manager or decorator to check if the identity meets the permission requirements. ```python class flask_principal.IdentityContext(_permission_ , _http_exception=None_) The context of an identity for a permission. Note The principal is usually created by the flaskext.Permission.require method call for normal use-cases. The principal behaves as either a context manager or a decorator. The permission is checked for provision in the identity, and if available the flow is continued (context manager) or the function is executed (decorator). `can`() Whether the identity has access to the permission `http_exception` _= None_¶ The permission of this principal `identity`¶ The identity of this principal ``` -------------------------------- ### Flask-Principal Permission Class Source: https://pythonhosted.org/Flask-Principal/index The Permission class represents a set of needs required to access a resource. It provides methods for checking access (allows, can, test), manipulating permissions (difference, union, reverse), and creating context managers or decorators (require). ```python class flask_principal.Permission(_needs_) Represents needs, any of which must be present to access a resource Parameters:| **needs** – The needs for this permission ---|--- `allows`(_identity_) Whether the identity can access this permission. Parameters:| **identity** – The identity ---|--- `can`() Whether the required context for this permission has access This creates an identity context and tests whether it can access this permission `difference`(_other_) Create a new permission consisting of requirements in this permission and not in the other. `issubset`(_other_) Whether this permission needs are a subset of another Parameters:| **other** – The other permission ---|--- `require`(_http_exception=None_) Create a principal for this permission. The principal may be used as a context manager, or a decroator. If `http_exception` is passed then `abort()` will be called with the HTTP exception code. Otherwise a `PermissionDenied` exception will be raised if the identity does not meet the requirements. Parameters:| **http_exception** – the HTTP exception code (403, 401 etc) ---|--- `reverse`() Returns reverse of current state (needs->excludes, excludes->needs) `test`(_http_exception=None_) Checks if permission available and raises relevant exception if not. This is useful if you just want to check permission without wrapping everything in a require() block. This is equivalent to: ``` with permission.require(): pass ``` `union`(_other_) Create a new permission with the requirements of the union of this and other. Parameters:| **other** – The other permission ---|--- ``` -------------------------------- ### Flask-Principal Need Types Source: https://pythonhosted.org/Flask-Principal/index Flask-Principal defines several Need types for specifying requirements: Need (base class), RoleNeed, UserNeed, and ItemNeed. ItemNeed is a more specific type for item-level permissions, allowing for flexible conventions in defining access control. ```python class flask_principal.Need A required need This is just a named tuple, and practically any tuple will do. The `method` attribute can be used to look up element 0, and the `value` attribute can be used to look up element 1. flask_principal.RoleNeed flask_principal.UserNeed class flask_principal.ItemNeed A required item need An item need is just a named tuple, and practically any tuple will do. In addition to other Needs, there is a type, for example this could be specified as: ``` ItemNeed('update', 27, 'posts') ('update', 27, 'posts') # or like this ``` And that might describe the permission to update a particular blog post. In reality, the developer is free to choose whatever convention the permissions are. ``` -------------------------------- ### Flask-Principal AnonymousIdentity Class Source: https://pythonhosted.org/Flask-Principal/index The AnonymousIdentity class represents an unauthenticated user. It's a predefined identity type used when a user is not logged in. ```python class flask_principal.AnonymousIdentity An anonymous identity ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.