#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# This file is part of Mentat system (https://mentat.cesnet.cz/).
#
# Copyright (C) since 2011 CESNET, z.s.p.o (http://www.ces.net/)
# Use of this source is governed by the MIT license, see LICENSE file.
# -------------------------------------------------------------------------------
"""
This file contains pluggable module for Hawat web interface containing features
related to user group management. These features include:
* general group listing
* detailed group view
* creating new groups
* updating existing groups
* deleting existing groups
* enabling existing groups
* disabling existing groups
* adding group members
* removing group members
* rejecting group membership requests
"""
__author__ = "Jan Mach <jan.mach@cesnet.cz>"
__credits__ = "Pavel Kácha <pavel.kacha@cesnet.cz>, Andrea Kropáčová <andrea.kropacova@cesnet.cz>"
import markupsafe
import flask
import flask_login
import flask_principal
from flask_babel import gettext, lazy_gettext
from sqlalchemy import and_, or_
from mentat.datatype.sqldb import SettingsReportingModel, FilterModel, NetworkModel, ItemChangeLogModel
from mentat.const import tr_
import hawat.const
import hawat.acl
import hawat.menu
from hawat.utils import URLParamsBuilder
from hawat.base import HawatBlueprint
from hawat.view import ItemListView, ItemShowView, ItemCreateView, ItemUpdateView, ItemDeleteView, ItemEnableView, \
ItemDisableView, ItemObjectRelationView
from hawat.view.mixin import HTMLMixin, SQLAlchemyMixin
from hawat.blueprints.groups.forms import AdminCreateGroupForm, AdminUpdateGroupForm, UpdateGroupForm, GroupSearchForm
BLUEPRINT_NAME = 'groups'
"""Name of the blueprint as module global constant."""
[docs]class ListView(HTMLMixin, SQLAlchemyMixin, ItemListView):
"""
General group listing.
"""
methods = ['GET']
authentication = True
authorization = [hawat.acl.PERMISSION_POWER]
[docs] @classmethod
def get_view_title(cls, **kwargs):
return lazy_gettext('Group management')
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
[docs] @staticmethod
def build_query(query, model, form_args):
# Adjust query based on text search string.
if 'search' in form_args and form_args['search']:
query = query \
.filter(
or_(
model.name.ilike('%{}%'.format(form_args['search'])),
model.description.ilike('%{}%'.format(form_args['search'])),
)
)
# Adjust query based on lower time boundary selection.
if 'dt_from' in form_args and form_args['dt_from']:
query = query.filter(model.createtime >= form_args['dt_from'])
# Adjust query based on upper time boundary selection.
if 'dt_to' in form_args and form_args['dt_to']:
query = query.filter(model.createtime <= form_args['dt_to'])
# Adjust query based on user state selection.
if 'state' in form_args and form_args['state']:
if form_args['state'] == 'enabled':
query = query.filter(model.enabled)
elif form_args['state'] == 'disabled':
query = query.filter(not model.enabled)
# Adjust query based on record source selection.
if 'source' in form_args and form_args['source']:
query = query \
.filter(model.source == form_args['source'])
# Adjust query based on user membership selection.
if 'member' in form_args and form_args['member']:
query = query \
.join(model.members) \
.filter(model.members.any(id=form_args['member'].id))
# Adjust query based on user membership selection.
if 'manager' in form_args and form_args['manager']:
query = query \
.join(model.managers) \
.filter(model.managers.any(id=form_args['managers'].id))
if 'sortby' in form_args and form_args['sortby']:
sortmap = {
'createtime.desc': lambda x, y: x.order_by(y.createtime.desc()),
'createtime.asc': lambda x, y: x.order_by(y.createtime.asc()),
'name.desc': lambda x, y: x.order_by(y.name.desc()),
'name.asc': lambda x, y: x.order_by(y.name.asc())
}
query = sortmap[form_args['sortby']](query, model)
return query
[docs]class ShowView(HTMLMixin, SQLAlchemyMixin, ItemShowView):
"""
Detailed group view.
"""
methods = ['GET']
authentication = True
[docs] @classmethod
def get_view_title(cls, **kwargs):
return lazy_gettext('Show group details')
[docs] @classmethod
def get_view_url(cls, **kwargs):
if isinstance(kwargs['item'], cls.get_model(hawat.const.MODEL_GROUP)):
return flask.url_for(
cls.get_view_endpoint(),
item_id=kwargs['item'].get_id()
)
return flask.url_for(
cls.get_view_endpoint(),
item_id=kwargs['item'].group.get_id()
)
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_mm = flask_principal.Permission(
hawat.acl.MembershipNeed(kwargs['item'].id),
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_mm.can()
[docs] def do_before_response(self, **kwargs): # pylint: disable=locally-disabled,unused-argument
action_menu = hawat.menu.Menu()
action_menu.add_entry(
'endpoint',
'show',
endpoint='users.show',
hidetitle=True,
)
action_menu.add_entry(
'submenu',
'more',
align_right=True,
legend=gettext('More actions')
)
action_menu.add_entry(
'endpoint',
'more.add_membership',
endpoint='users.addmembership'
)
action_menu.add_entry(
'endpoint',
'more.reject_membership',
endpoint='users.rejectmembership'
)
action_menu.add_entry(
'endpoint',
'more.remove_membership',
endpoint='users.removemembership'
)
action_menu.add_entry(
'endpoint',
'more.add_management',
endpoint='users.addmanagement'
)
action_menu.add_entry(
'endpoint',
'more.remove_management',
endpoint='users.removemanagement'
)
action_menu.add_entry(
'endpoint',
'more.enable',
endpoint='users.enable'
)
action_menu.add_entry(
'endpoint',
'more.disable',
endpoint='users.disable'
)
action_menu.add_entry(
'endpoint',
'more.update',
endpoint='users.update'
)
self.response_context.update(context_action_menu_users=action_menu)
action_menu = hawat.menu.Menu()
action_menu.add_entry(
'endpoint',
'show',
endpoint='networks.show',
hidetitle=True,
)
self.response_context.update(context_action_menu_networks=action_menu)
action_menu = hawat.menu.Menu()
action_menu.add_entry(
'endpoint',
'show',
endpoint='filters.show',
hidetitle=True,
)
self.response_context.update(context_action_menu_filters=action_menu)
item = self.response_context['item']
if self.can_access_endpoint('groups.update', item=item) and self.has_endpoint('changelogs.search'):
self.response_context.update(
context_action_menu_changelogs=self.get_endpoint_class(
'changelogs.search'
).get_context_action_menu()
)
item_changelog = self.dbsession.query(ItemChangeLogModel). \
filter(
or_(
# Changelogs related directly to group item.
and_(
ItemChangeLogModel.model == item.__class__.__name__,
ItemChangeLogModel.model_id == item.id
),
# Changelogs related to group reporting settings item.
and_(
ItemChangeLogModel.model == SettingsReportingModel.__name__,
ItemChangeLogModel.model_id.in_(
self.dbsession.query(SettingsReportingModel.id).filter(
SettingsReportingModel.group_id == item.id)
)
),
# Changelogs related to all group reporting filters.
and_(
ItemChangeLogModel.model == FilterModel.__name__,
ItemChangeLogModel.model_id.in_(
self.dbsession.query(FilterModel.id).filter(FilterModel.group_id == item.id)
)
),
# Changelogs related to all group network records.
and_(
ItemChangeLogModel.model == NetworkModel.__name__,
ItemChangeLogModel.model_id.in_(
self.dbsession.query(NetworkModel.id).filter(NetworkModel.group_id == item.id)
)
)
)
). \
order_by(ItemChangeLogModel.createtime.desc()). \
limit(100). \
all()
self.response_context.update(item_changelog=item_changelog)
[docs]class ShowByNameView(ShowView): # pylint: disable=locally-disabled,too-many-ancestors
"""
Detailed group view by group name.
"""
[docs] @classmethod
def get_view_name(cls):
return 'show_by_name'
[docs] @classmethod
def get_view_template(cls):
return '{}/show.html'.format(cls.module_name)
@property
def search_by(self):
return self.dbmodel.name
[docs]class CreateView(HTMLMixin, SQLAlchemyMixin, ItemCreateView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for creating new groups.
"""
methods = ['GET', 'POST']
authentication = True
authorization = [hawat.acl.PERMISSION_POWER]
[docs] @classmethod
def get_view_title(cls, **kwargs):
return lazy_gettext('Create new group')
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'Group <strong>%(item_id)s</strong> was successfully created.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext('Unable to create new group.')
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext('Canceled creating new group.')
[docs] def do_before_action(self, item):
# Create empty reporting settings object and assign it to the group.
SettingsReportingModel(group=item)
[docs]class UpdateView(HTMLMixin, SQLAlchemyMixin, ItemUpdateView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for updating existing groups.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_title(cls, **kwargs):
return lazy_gettext('Update group details')
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'Group <strong>%(item_id)s</strong> was successfully updated.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to update group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled updating group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class AddMemberView(HTMLMixin, SQLAlchemyMixin,
ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for adding group members.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_name(cls):
return 'addmember'
[docs] @classmethod
def get_view_title(cls, **kwargs):
return gettext('Add group member')
[docs] @classmethod
def get_view_icon(cls):
return 'action-add-member'
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
@property
def dbmodel_other(self):
return self.get_model(hawat.const.MODEL_USER)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
# Reject item change in case given item is already enabled.
if kwargs['other'] in kwargs['item'].members:
return False
return True
[docs] @classmethod
def change_item(cls, **kwargs):
kwargs['item'].members.append(kwargs['other'])
if kwargs['other'].is_state_disabled():
kwargs['other'].set_state_enabled()
flask.current_app.send_infomail(
'users.enable',
account=kwargs['other']
)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'User <strong>%(user_id)s</strong> was successfully added as a member to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to add user <strong>%(user_id)s</strong> as a member to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled adding user <strong>%(user_id)s</strong> as a member to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class RejectMemberView(HTMLMixin, SQLAlchemyMixin,
ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for rejecting group membership reuests.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_name(cls):
return 'rejectmember'
[docs] @classmethod
def get_view_title(cls, **kwargs):
return gettext('Reject group member')
[docs] @classmethod
def get_view_icon(cls):
return 'action-rej-member'
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
@property
def dbmodel_other(self):
return self.get_model(hawat.const.MODEL_USER)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
# Reject item change in case given item is already enabled.
if kwargs['other'] not in kwargs['item'].members_wanted:
return False
return True
[docs] @classmethod
def change_item(cls, **kwargs):
kwargs['item'].members_wanted.remove(kwargs['other'])
# ---------------------------------------------------------------------------
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'User`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong> was successfully rejected.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to reject user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled rejecting user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class RemoveMemberView(HTMLMixin, SQLAlchemyMixin,
ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for removing group members.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_name(cls):
return 'removemember'
[docs] @classmethod
def get_view_title(cls, **kwargs):
return gettext('Remove group member')
[docs] @classmethod
def get_view_icon(cls):
return 'action-rem-member'
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
@property
def dbmodel_other(self):
return self.get_model(hawat.const.MODEL_USER)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
# Reject item change in case given item is already enabled.
if kwargs['other'] not in kwargs['item'].members:
return False
return True
[docs] @classmethod
def change_item(cls, **kwargs):
kwargs['item'].members.remove(kwargs['other'])
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'User <strong>%(user_id)s</strong> was successfully removed as a member from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to remove user <strong>%(user_id)s</strong> as a member from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled removing user <strong>%(user_id)s</strong> as a member from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class AddManagerView(HTMLMixin, SQLAlchemyMixin,
ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for adding group managers.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_name(cls):
return 'addmanager'
[docs] @classmethod
def get_view_title(cls, **kwargs):
return gettext('Add group manager')
[docs] @classmethod
def get_view_icon(cls):
return 'action-add-manager'
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
@property
def dbmodel_other(self):
return self.get_model(hawat.const.MODEL_USER)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
# Reject item change in case given item is already manager.
if kwargs['other'] in kwargs['item'].managers:
return False
return True
[docs] @classmethod
def change_item(cls, **kwargs):
kwargs['item'].managers.append(kwargs['other'])
if kwargs['other'].is_state_disabled():
kwargs['other'].set_state_enabled()
flask.current_app.send_infomail(
'users.enable',
account=kwargs['other']
)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'User <strong>%(user_id)s</strong> was successfully added as a manager to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to add user <strong>%(user_id)s</strong> as a manager to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled adding user <strong>%(user_id)s</strong> as a manager to group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class RemoveManagerView(HTMLMixin, SQLAlchemyMixin,
ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for removing group managers.
"""
methods = ['GET', 'POST']
authentication = True
[docs] @classmethod
def get_view_name(cls):
return 'removemanager'
[docs] @classmethod
def get_view_title(cls, **kwargs):
return gettext('Remove group manager')
[docs] @classmethod
def get_view_icon(cls):
return 'action-rem-manager'
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
@property
def dbmodel_other(self):
return self.get_model(hawat.const.MODEL_USER)
[docs] @classmethod
def authorize_item_action(cls, **kwargs):
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
[docs] @classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
# Reject item change in case given item is not already manager.
if kwargs['other'] not in kwargs['item'].managers:
return False
return True
[docs] @classmethod
def change_item(cls, **kwargs):
try:
kwargs['item'].managers.remove(kwargs['other'])
except ValueError:
pass
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'User <strong>%(user_id)s</strong> was successfully removed as a manager from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to remove user <strong>%(user_id)s</strong> as a manager from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled removing user <strong>%(user_id)s</strong> as a manager from group <strong>%(group_id)s</strong>.',
user_id=markupsafe.escape(str(kwargs['other'])),
group_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class EnableView(HTMLMixin, SQLAlchemyMixin, ItemEnableView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for enabling existing groups.
"""
methods = ['GET', 'POST']
authentication = True
authorization = [hawat.acl.PERMISSION_POWER]
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'Group <strong>%(item_id)s</strong> was successfully enabled.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to enable group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled enabling group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class DisableView(HTMLMixin, SQLAlchemyMixin, ItemDisableView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for disabling groups.
"""
methods = ['GET', 'POST']
authentication = True
authorization = [hawat.acl.PERMISSION_POWER]
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'Group <strong>%(item_id)s</strong> was successfully disabled.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to disable group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled disabling group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs]class DeleteView(HTMLMixin, SQLAlchemyMixin, ItemDeleteView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for deleting existing groups.
"""
methods = ['GET', 'POST']
authentication = True
authorization = [hawat.acl.PERMISSION_ADMIN]
@property
def dbmodel(self):
return self.get_model(hawat.const.MODEL_GROUP)
@property
def dbchlogmodel(self):
return self.get_model(hawat.const.MODEL_ITEM_CHANGELOG)
[docs] @staticmethod
def get_message_success(**kwargs):
return gettext(
'Group <strong>%(item_id)s</strong> was successfully and permanently deleted.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_failure(**kwargs):
return gettext(
'Unable to delete group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
[docs] @staticmethod
def get_message_cancel(**kwargs):
return gettext(
'Canceled deleting group <strong>%(item_id)s</strong>.',
item_id=markupsafe.escape(str(kwargs['item']))
)
# -------------------------------------------------------------------------------
[docs]class GroupsBlueprint(HawatBlueprint):
"""Pluggable module - user groups (*groups*)."""
[docs] @classmethod
def get_module_title(cls):
return lazy_gettext('Group management')
[docs] def register_app(self, app):
def _fetch_my_groups():
groups = {}
for i in list(flask_login.current_user.memberships) + list(flask_login.current_user.managements):
groups[str(i)] = i
return list(sorted(groups.values(), key=str))
app.menu_main.add_entry(
'view',
'admin.{}'.format(BLUEPRINT_NAME),
position=50,
view=ListView
)
app.menu_auth.add_entry(
'submenudb',
'my_groups',
position=20,
title=lazy_gettext('My groups'),
resptitle=True,
icon='module-groups',
align_right=True,
entry_fetcher=_fetch_my_groups,
entry_builder=lambda x, y: hawat.menu.EndpointEntry(x, endpoint='groups.show', params={'item': y}, title=x,
icon='module-groups')
)
# Register context actions provided by this module.
app.set_csag(
hawat.const.CSAG_ABUSE,
tr_('View details of abuse group <strong>%(name)s</strong>'),
ShowByNameView,
URLParamsBuilder().add_rule('item_id')
)
# -------------------------------------------------------------------------------
[docs]def get_blueprint():
"""
Mandatory interface for :py:mod:`hawat.Hawat` and factory function. This function
must return a valid instance of :py:class:`hawat.app.HawatBlueprint` or
:py:class:`flask.Blueprint`.
"""
hbp = GroupsBlueprint(
BLUEPRINT_NAME,
__name__,
template_folder='templates',
url_prefix='/{}'.format(BLUEPRINT_NAME)
)
hbp.register_view_class(ListView, '/list')
hbp.register_view_class(CreateView, '/create')
hbp.register_view_class(ShowView, '/<int:item_id>/show')
hbp.register_view_class(ShowByNameView, '/<item_id>/show_by_name')
hbp.register_view_class(UpdateView, '/<int:item_id>/update')
hbp.register_view_class(AddMemberView, '/<int:item_id>/add_member/<int:other_id>')
hbp.register_view_class(RejectMemberView, '/<int:item_id>/reject_member/<int:other_id>')
hbp.register_view_class(RemoveMemberView, '/<int:item_id>/remove_member/<int:other_id>')
hbp.register_view_class(AddManagerView, '/<int:item_id>/add_manager/<int:other_id>')
hbp.register_view_class(RemoveManagerView, '/<int:item_id>/remove_manager/<int:other_id>')
hbp.register_view_class(EnableView, '/<int:item_id>/enable')
hbp.register_view_class(DisableView, '/<int:item_id>/disable')
hbp.register_view_class(DeleteView, '/<int:item_id>/delete')
return hbp