diff options
author | Alejandro Sirgo Rica <asirgo@soleta.eu> | 2024-06-25 17:29:02 +0200 |
---|---|---|
committer | Alejandro Sirgo Rica <asirgo@soleta.eu> | 2024-06-27 10:03:14 +0200 |
commit | 977b457d5ce7661e8b4680d5543ad4d31063dcf1 (patch) | |
tree | b978944834f149c3aea9083c166fc2ba7b1d950f /ogcp/templates/auth | |
parent | 25bb1ff73b537c53b07c7d41c28e1b52c149c026 (diff) |
ogcp: add user permission mechanism
Add a new user permission system to control the allowed operations
accessible from each account.
Add a permission matrix editable through the user/add and user/edit
views. The permission matrix has client, center, room, folder, image
and repository as permission targets and add, update and delete as
permission types.
Restrict each view based on the user permissions, hide all actions
from not autheticated users.
permissions defined in the class UserForm.
Serialize each user permissions into ogcp.json as:
{
...
"USERS" [
{
"USER": "admin"
...
"PERMISSIONS": {
"CLIENT": {
"ADD": true,
"UPDATE": true,
"DELETE": true,
},
... <- same structure for "CENTER", "ROOM", "FOLDER", "IMAGE"
and "REPOSITORY"
}
},
...
],
...
}
Grant all the permissions to old user configuration to not disrupt their
workflow. The administrator will need to assign the permissions for each
user.
Ignore scope and permission restrictions for admin users.
Save permissions and scopes even if the user is admin to account for the
case of a temporal admin promotion without losing the previous
configuration.
Use template inheritance for add_user.html and edit_user.html to prevent
big code duplication with the new HTML code to render the permission
matrix.
Make user administration an admin only feature.
Define methods get_permission and target_is_disabled to improve readability
in template conditionals that disable features based on user permissions.
Diffstat (limited to 'ogcp/templates/auth')
-rw-r--r-- | ogcp/templates/auth/add_user.html | 54 | ||||
-rw-r--r-- | ogcp/templates/auth/edit_user.html | 54 | ||||
-rw-r--r-- | ogcp/templates/auth/user_form.html | 126 |
3 files changed, 134 insertions, 100 deletions
diff --git a/ogcp/templates/auth/add_user.html b/ogcp/templates/auth/add_user.html index cc5ed09..4661236 100644 --- a/ogcp/templates/auth/add_user.html +++ b/ogcp/templates/auth/add_user.html @@ -1,53 +1,5 @@ -{% extends 'users.html' %} -{% import "bootstrap/wtf.html" as wtf %} +{% extends 'auth/user_form.html' %} -{% set sidebar_state = 'disabled' %} -{% set btn_back = true %} +{% block subhead_heading %}{{_('Add user')}}{% endblock %} -{% block nav_user_add %}active{% endblock %} -{% block content %} - -<h1 class="m-5">{{_('Add a user')}}</h1> - -<form action="{{ url_for('user_add_post') }}" method="post" class="form"> - {{ form.hidden_tag() }} - - <div class="form-group"> - {{ form.username.label(class_='form-label') }} - {{ form.username(class_='form-control') }} - </div> - - <div class="form-group"> - {{ form.pwd.label(class_='form-label') }} - {{ form.pwd(class_='form-control') }} - </div> - - <div class="form-group"> - {{ form.pwd_confirm.label(class_='form-label') }} - {{ form.pwd_confirm(class_='form-control') }} - </div> - - <div class="form-group form-check"> - {{ form.admin(class_='form-check-input') }} - {{ form.admin.label(class_='form-check-label') }} - </div> - - <div class="form-group"> - {{ form.scopes.label(class_='form-label') }} - <div class="form-text text-muted">{{ form.scopes.description }}</div> - <div> - {% for value, label, checked in form.scopes.iter_choices() %} - <div class="form-check"> - <input class="form-check-input" type="checkbox" name="{{ form.scopes.name }}" value="{{ value }}" {% if checked %} checked {% endif %}> - <label class="form-check-label">{{ label }}</label> - </div> - {% endfor %} - </div> - </div> - - <div class="form-group"> - {{ form.submit_btn(class_='btn btn-primary') }} - </div> -</form> - -{% endblock %} +{% block form_action %}{{ url_for('user_add_post') }}{% endblock %} diff --git a/ogcp/templates/auth/edit_user.html b/ogcp/templates/auth/edit_user.html index 3b10508..42ba5aa 100644 --- a/ogcp/templates/auth/edit_user.html +++ b/ogcp/templates/auth/edit_user.html @@ -1,53 +1,9 @@ -{% extends 'users.html' %} -{% import "bootstrap/wtf.html" as wtf %} +{% extends 'auth/user_form.html' %} -{% set sidebar_state = 'disabled' %} -{% set btn_back = true %} +{% block subhead_heading %}{{_('Edit user {}').format(form.username.data)}}{% endblock %} -{% block nav_user_edit %}active{% endblock %} -{% block content %} +{% block form_action %}{{ url_for('user_edit_post') }}{% endblock %} -<h1 class="m-5">{{_('Edit user {}').format(form.username.data)}}</h1> +{% block pwd_field %}<input type="password" name="pwd" class="form-control" placeholder="{{ _('Leave blank if not changing') }}">{% endblock %} -<form action="{{ url_for('user_edit_post') }}" method="post" class="form"> - {{ form.hidden_tag() }} - - <div class="form-group"> - {{ form.username.label(class_='form-label') }} - {{ form.username(class_='form-control') }} - </div> - - <div class="form-group"> - {{ form.pwd.label(class_='form-label') }} - <input type="password" name="pwd" class="form-control" placeholder="{{ _('Leave blank if not changing') }}"> - </div> - - <div class="form-group"> - {{ form.pwd_confirm.label(class_='form-label') }} - <input type="password" name="pwd_confirm" class="form-control" placeholder="{{ _('Leave blank if not changing') }}"> - </div> - - <div class="form-group form-check"> - {{ form.admin(class_='form-check-input') }} - {{ form.admin.label(class_='form-check-label') }} - </div> - - <div class="form-group"> - {{ form.scopes.label(class_='form-label') }} - <div class="form-text text-muted">{{ form.scopes.description }}</div> - <div> - {% for value, label, checked in form.scopes.iter_choices() %} - <div class="form-check"> - <input class="form-check-input" type="checkbox" name="{{ form.scopes.name }}" value="{{ value }}" {% if checked %} checked {% endif %}> - <label class="form-check-label">{{ label }}</label> - </div> - {% endfor %} - </div> - </div> - - <div class="form-group"> - {{ form.submit_btn(class_='btn btn-primary') }} - </div> -</form> - -{% endblock %} +{% block pwd_confirm_field %}<input type="password" name="pwd_confirm" class="form-control" placeholder="{{ _('Leave blank if not changing') }}">{% endblock %} diff --git a/ogcp/templates/auth/user_form.html b/ogcp/templates/auth/user_form.html new file mode 100644 index 0000000..7b6b338 --- /dev/null +++ b/ogcp/templates/auth/user_form.html @@ -0,0 +1,126 @@ +{% extends 'users.html' %} +{% import "bootstrap/wtf.html" as wtf %} + +{% set sidebar_state = 'disabled' %} +{% set btn_back = true %} + +{% block nav_user_add %}active{% endblock %} +{% block content %} + +<h1 class="m-5">{% block subhead_heading %}{% endblock %}</h1> + +<form action="{% block form_action %}{% endblock %}" method="post" class="form"> + {{ form.hidden_tag() }} + + <div class="form-group"> + {{ form.username.label(class_='form-label') }} + {{ form.username(class_='form-control') }} + </div> + + <div class="form-group"> + {{ form.pwd.label(class_='form-label') }} + {% block pwd_field %}{{ form.pwd(class_='form-control') }}{% endblock %} + </div> + + <div class="form-group"> + {{ form.pwd_confirm.label(class_='form-label') }} + {% block pwd_confirm_field %}{{ form.pwd_confirm(class_='form-control') }}{% endblock %} + </div> + + <div class="form-group"> + <div class="custom-control custom-switch"> + {{ form.admin(class_="custom-control-input", id="adminToggle") }} + <label class="custom-control-label" for="adminToggle">{{ form.admin.label.text }}</label> + </div> + </div> + + <!-- jQuery --> + <script src="{{ url_for('static', filename='AdminLTE/plugins/jquery/jquery.min.js') }}"></script> + <script> + $(document).ready(function(){ + + var isAdminEnabled = $('#adminToggle').is(':checked'); + if(isAdminEnabled) { + $('#PermissionSection').hide(); + } + + $('#adminToggle').change(function() { + isAdminEnabled = $(this).is(':checked'); + $('#PermissionSection').toggle(!isAdminEnabled); + }); + }); + </script> + + <div id="PermissionSection"> + <div class="form-group"> + <label class="form-label">{{ _('Permissions') }}</label> + <table class="text-center table"> + <thead> + <tr> + <th></th> + <th>{{ form.client_permissions.add.label.text }}</th> + <th>{{ form.client_permissions.update.label.text }}</th> + <th>{{ form.client_permissions.delete.label.text }}</th> + </tr> + </thead> + <tbody> + <tr> + <th>{{ form.client_permissions.label }}</th> + <td>{{ form.client_permissions.add() }}</td> + <td>{{ form.client_permissions.update() }}</td> + <td>{{ form.client_permissions.delete() }}</td> + </tr> + <tr> + <th>{{ form.center_permissions.label }}</th> + <td>{{ form.center_permissions.add() }}</td> + <td>{{ form.center_permissions.update() }}</td> + <td>{{ form.center_permissions.delete() }}</td> + </tr> + <tr> + <th>{{ form.room_permissions.label }}</th> + <td>{{ form.room_permissions.add() }}</td> + <td>{{ form.room_permissions.update() }}</td> + <td>{{ form.room_permissions.delete() }}</td> + </tr> + <tr> + <th>{{ form.folder_permissions.label }}</th> + <td>{{ form.folder_permissions.add() }}</td> + <td>{{ form.folder_permissions.update() }}</td> + <td>{{ form.folder_permissions.delete() }}</td> + </tr> + <tr> + <th>{{ form.image_permissions.label }}</th> + <td>{{ form.image_permissions.add() }}</td> + <td>{{ form.image_permissions.update() }}</td> + <td>{{ form.image_permissions.delete() }}</td> + </tr> + <tr> + <th>{{ form.repository_permissions.label }}</th> + <td>{{ form.repository_permissions.add() }}</td> + <td>{{ form.repository_permissions.update() }}</td> + <td>{{ form.repository_permissions.delete() }}</td> + </tr> + </tbody> + </table> + </div> + + <div class="form-group"> + {{ form.scopes.label(class_='form-label') }} + <div class="form-text text-muted">{{ form.scopes.description }}</div> + <div> + {% for value, label, checked in form.scopes.iter_choices() %} + <div class="form-check"> + <input class="form-check-input" type="checkbox" name="{{ form.scopes.name }}" value="{{ value }}" {% if checked %} checked {% endif %}> + <label class="form-check-label">{{ label }}</label> + </div> + {% endfor %} + </div> + </div> + </div> + + <div class="form-group"> + {{ form.submit_btn(class_='btn btn-primary') }} + </div> +</form> + +{% endblock %} |