Apps
We have the following models:
Note
This app now requires a Contact app (see get_contact_model)
so we can exclude (soft) deleted contacts.
Permissions
Does a user have access to an app e.g. the MyApps.CRM app:
from apps.models import App
from example_apps.models import MyApps
App.objects.has_access(user, MyApps.CRM)
Note
Created 11/06/2023, There may be a better way to do this!
For the tests, see example_apps/tests/test_app.py.
Models
App
The App model contains the properties of the apps in a project
e.g. name, icon…
Tip
The user_apps method is used to display a list of apps for a user.
e.g. AppListView
Useful methods include:
admin_apps: List of apps where the user is an administrator.admin_app_groups: List of apps where the user is a group administrator.app_menu: Can be used to control the main menu in the projectcurrent_app_admincan be used to enable menu options for a user who is an administrator for the current app.show_app_menuwill tell you if the user has access to just one app i.e. no need to show the app menu unless they have access to several apps.
app_perms: Check the source code for documentation.create_app: Create a new app…is_administrator: Is the user an administrator for this app?is_administrator_for_any_app: Is the user an administrator for any app?user_apps: Apps available to this user.user_dash_url: Dashboard URL for this user (if there is a single one).
This model includes a slug, name, menu caption and icon for the
app.
administrators(many to many): Users who can administer the app.app_group(many to many): Users belonging to these groups (AppGroup) have permission to access the app.global_group(many to many): Users belonging to these groups (DjangoGroup) have permission to access the app.hide_app_groups(boolean): Does the app useapp_group(or not)?url_contact_editandurl_dashare URLs for the dashboard and contact edit pages for the app.
AppSettings
app_superusers(many to many): Users who can set the administrator for an app.contact_administrators(many to many): Users who can create / update / delete users (or contacts).
AppGroup and AppGroupUser
List of groups for an application. These are different to the Django Group.
Templates
You can add the following to your base.html template:
{% block menu %}
{% if user.is_authenticated %}
{% if app_menu and app_menu.show_app_menu %}
<li class="pure-menu-item{% if 'apps' in path %} pure-menu-selected{% endif %}">
<a href="{% url 'apps.list' %}" class="pure-menu-link">
<i class="fa fa-bullseye fa-fw"></i>
Apps
</a>
</li>
{% endif %}
{% if app_menu and app_menu.current_app %}
<li class="pure-menu-item{% if app_menu.current_app.url_dash == request.build_absolute_uri %} pure-menu-selected{% endif %}">
<a href="{{ app_menu.current_app.url_dash }}" class="pure-menu-link">
<i class="fa fa-dashboard fa-fw"></i>
Dashboard
</a>
</li>
{% endif %}
{% if app_menu and app_menu.show_settings %}
<li class="pure-menu-item{% if 'settings' in path %} pure-menu-selected{% endif %}">
<a href="{% url 'project.settings' %}" class="pure-menu-link">
<i class="fa fa-cog fa-fw"></i>
Settings
</a>
</li>
{% endif %}
{% endif %}
{% endblock menu %}
Views
To add details of the app_menu to the context of BaseMixin, we use
the BASE_MIXIN_CONTEXT_PLUGIN system:
Add the following to settings/base.py:
# See 'base/view_utils.py'
BASE_MIXIN_CONTEXT_PLUGIN = ["apps.plugin.AppBaseMixin"]
Set the current_app_slug if your template is for a particular app e.g:
class DashView(LoginRequiredMixin, BaseMixin, TemplateView):
current_app_slug = MyApps.REPORT
template_name = "example/dash.html"
Settings
The Settings view needs access to various permissions:
from braces.views import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DetailView
from apps.views import is_contact_or_app_admin, SettingsBaseMixin
class SettingsView(
LoginRequiredMixin, UserPassesTestMixin, SettingsBaseMixin, TemplateView
):
template_name = "example/settings.html"
def test_func(self, user):
return is_contact_or_app_admin(user)
The permissions returned by SettingsBaseMixin will work with the following:
{% block content %}
<div class="pure-g">
{% include 'apps/_settings_apps.html' %}
{% include 'apps/_settings_groups.html' %}
</div>
{% endblock content %}