Skip to content
Snippets Groups Projects
Commit 456b47ed authored by Jan Mach's avatar Jan Mach
Browse files

Added the ability to reject group membership requests.

Group managers must have the ability to reject unwanted group membership requests. (Redmine issue: #5832)
parent ff552477
No related branches found
No related tags found
No related merge requests found
...@@ -28,7 +28,6 @@ features include: ...@@ -28,7 +28,6 @@ features include:
__author__ = "Jan Mach <jan.mach@cesnet.cz>" __author__ = "Jan Mach <jan.mach@cesnet.cz>"
__credits__ = "Pavel Kácha <pavel.kacha@cesnet.cz>, Andrea Kropáčová <andrea.kropacova@cesnet.cz>" __credits__ = "Pavel Kácha <pavel.kacha@cesnet.cz>, Andrea Kropáčová <andrea.kropacova@cesnet.cz>"
import pprint
# #
# Flask related modules. # Flask related modules.
# #
...@@ -248,6 +247,11 @@ class ShowView(HTMLMixin, SQLAlchemyMixin, ItemShowView): ...@@ -248,6 +247,11 @@ class ShowView(HTMLMixin, SQLAlchemyMixin, ItemShowView):
'more.add_membership', 'more.add_membership',
endpoint = 'users.addmembership' endpoint = 'users.addmembership'
) )
action_menu.add_entry(
'endpoint',
'more.reject_membership',
endpoint = 'users.rejectmembership'
)
action_menu.add_entry( action_menu.add_entry(
'endpoint', 'endpoint',
'more.remove_membership', 'more.remove_membership',
...@@ -591,6 +595,108 @@ class AddMemberView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pyli ...@@ -591,6 +595,108 @@ class AddMemberView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pyli
) )
class RejectMemberView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for rejecting group membership reuests.
"""
methods = ['GET','POST']
authentication = True
@classmethod
def get_view_name(cls):
return 'rejectmember'
@classmethod
def get_view_title(cls, **kwargs):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_view_title`."""
return gettext('Reject group member')
@classmethod
def get_view_icon(cls):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_view_icon`."""
return 'action-rej-member'
@classmethod
def get_menu_legend(cls, **kwargs):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_menu_title`."""
return lazy_gettext(
'Reject user`s &quot;%(user_id)s&quot; membership request for group &quot;%(group_id)s&quot;',
user_id = str(kwargs['other']),
group_id = str(kwargs['item'])
)
#---------------------------------------------------------------------------
@property
def dbmodel(self):
"""*Implementation* of :py:func:`hawat.base.SQLAlchemyMixin.dbmodel`."""
return GroupModel
@property
def dbmodel_other(self):
"""*Implementation* of :py:func:`hawat.base.AddMemberView.dbmodel_other`."""
return UserModel
#---------------------------------------------------------------------------
@classmethod
def authorize_item_action(cls, **kwargs):
"""
Perform access authorization for current user to particular item.
"""
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['item'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
@classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
"""
Perform validation of particular change to given item.
"""
# Reject item change in case given item is already enabled.
if kwargs['other'] not in kwargs['item'].members_wanted:
return False
return True
@classmethod
def change_item(cls, **kwargs):
"""
*Interface implementation* of :py:func:`hawat.base.ItemChangeView.change_item`.
"""
kwargs['item'].members_wanted.remove(kwargs['other'])
#---------------------------------------------------------------------------
@staticmethod
def get_message_success(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_success`."""
return gettext(
'User`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong> was successfully rejected.',
user_id = str(kwargs['other']),
group_id = str(kwargs['item'])
)
@staticmethod
def get_message_failure(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_failure`."""
return gettext(
'Unable to reject user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id = str(kwargs['other']),
group_id = str(kwargs['item'])
)
@staticmethod
def get_message_cancel(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_cancel`."""
return gettext(
'Canceled rejecting user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id = str(kwargs['other']),
group_id = str(kwargs['item'])
)
class RemoveMemberView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors class RemoveMemberView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
""" """
View for removing users from existing groups. View for removing users from existing groups.
...@@ -895,6 +1001,7 @@ def get_blueprint(): ...@@ -895,6 +1001,7 @@ def get_blueprint():
hbp.register_view_class(ShowByNameView, '/<item_id>/show_by_name') hbp.register_view_class(ShowByNameView, '/<item_id>/show_by_name')
hbp.register_view_class(UpdateView, '/<int:item_id>/update') 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(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(RemoveMemberView, '/<int:item_id>/remove_member/<int:other_id>')
hbp.register_view_class(EnableView, '/<int:item_id>/enable') hbp.register_view_class(EnableView, '/<int:item_id>/enable')
hbp.register_view_class(DisableView, '/<int:item_id>/disable') hbp.register_view_class(DisableView, '/<int:item_id>/disable')
......
...@@ -225,6 +225,11 @@ class ShowView(HTMLMixin, SQLAlchemyMixin, ItemShowView): ...@@ -225,6 +225,11 @@ class ShowView(HTMLMixin, SQLAlchemyMixin, ItemShowView):
'more.add_member', 'more.add_member',
endpoint = 'groups.addmember' endpoint = 'groups.addmember'
) )
action_menu.add_entry(
'endpoint',
'more.reject_member',
endpoint = 'groups.rejectmember'
)
action_menu.add_entry( action_menu.add_entry(
'endpoint', 'endpoint',
'more.remove_member', 'more.remove_member',
...@@ -616,6 +621,108 @@ class AddMembershipView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # ...@@ -616,6 +621,108 @@ class AddMembershipView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): #
) )
class RejectMembershipView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
"""
View for enabling existing groups.
"""
methods = ['GET','POST']
authentication = True
@classmethod
def get_view_name(cls):
return 'rejectmembership'
@classmethod
def get_view_title(cls, **kwargs):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_view_title`."""
return gettext('Reject group membership')
@classmethod
def get_view_icon(cls):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_view_icon`."""
return 'action-rej-member'
@classmethod
def get_menu_legend(cls, **kwargs):
"""*Implementation* of :py:func:`hawat.base.BaseView.get_menu_title`."""
return lazy_gettext(
'Reject user`s &quot;%(user_id)s&quot; membership request for group &quot;%(group_id)s&quot;',
user_id = str(kwargs['item']),
group_id = str(kwargs['other'])
)
#---------------------------------------------------------------------------
@property
def dbmodel(self):
"""*Implementation* of :py:func:`hawat.base.SQLAlchemyMixin.dbmodel`."""
return UserModel
@property
def dbmodel_other(self):
"""*Implementation* of :py:func:`hawat.base.AddMemberView.dbmodel_other`."""
return GroupModel
#---------------------------------------------------------------------------
@classmethod
def authorize_item_action(cls, **kwargs):
"""
Perform access authorization for current user to particular item.
"""
permission_m = flask_principal.Permission(
hawat.acl.ManagementNeed(kwargs['other'].id)
)
return hawat.acl.PERMISSION_POWER.can() or permission_m.can()
@classmethod
def validate_item_change(cls, **kwargs): # pylint: disable=locally-disabled,unused-argument
"""
Perform validation of particular change to given item.
"""
# Reject item change in case given item is already enabled.
if kwargs['other'] not in kwargs['item'].memberships_wanted:
return False
return True
@classmethod
def change_item(cls, **kwargs):
"""
*Interface implementation* of :py:func:`hawat.base.ItemChangeView.change_item`.
"""
kwargs['item'].memberships_wanted.remove(kwargs['other'])
#---------------------------------------------------------------------------
@staticmethod
def get_message_success(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_success`."""
return gettext(
'User`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong> was successfully rejected.',
user_id = str(kwargs['item']),
group_id = str(kwargs['other'])
)
@staticmethod
def get_message_failure(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_failure`."""
return gettext(
'Unable to reject user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id = str(kwargs['item']),
group_id = str(kwargs['other'])
)
@staticmethod
def get_message_cancel(**kwargs):
"""*Implementation* of :py:func:`hawat.base.ItemActionView.get_message_cancel`."""
return gettext(
'Canceled rejecting user`s <strong>%(user_id)s</strong> membership request for group <strong>%(group_id)s</strong>.',
user_id = str(kwargs['item']),
group_id = str(kwargs['other'])
)
class RemoveMembershipView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors class RemoveMembershipView(HTMLMixin, SQLAlchemyMixin, ItemObjectRelationView): # pylint: disable=locally-disabled,too-many-ancestors
""" """
View for removing users from existing groups. View for removing users from existing groups.
...@@ -948,6 +1055,7 @@ def get_blueprint(): ...@@ -948,6 +1055,7 @@ def get_blueprint():
hbp.register_view_class(UpdateView, '/<int:item_id>/update') hbp.register_view_class(UpdateView, '/<int:item_id>/update')
hbp.register_view_class(AddMembershipView, '/<int:item_id>/add_membership/<int:other_id>') hbp.register_view_class(AddMembershipView, '/<int:item_id>/add_membership/<int:other_id>')
hbp.register_view_class(RemoveMembershipView, '/<int:item_id>/remove_membership/<int:other_id>') hbp.register_view_class(RemoveMembershipView, '/<int:item_id>/remove_membership/<int:other_id>')
hbp.register_view_class(RejectMembershipView, '/<int:item_id>/reject_membership/<int:other_id>')
hbp.register_view_class(EnableView, '/<int:item_id>/enable') hbp.register_view_class(EnableView, '/<int:item_id>/enable')
hbp.register_view_class(DisableView, '/<int:item_id>/disable') hbp.register_view_class(DisableView, '/<int:item_id>/disable')
hbp.register_view_class(DeleteView, '/<int:item_id>/delete') hbp.register_view_class(DeleteView, '/<int:item_id>/delete')
......
...@@ -228,6 +228,7 @@ FA_ICONS = { ...@@ -228,6 +228,7 @@ FA_ICONS = {
'action-delete': '<i class="fas fa-fw fa-trash"></i>', 'action-delete': '<i class="fas fa-fw fa-trash"></i>',
'action-delete-user': '<i class="fas fa-fw fa-user-slash"></i>', 'action-delete-user': '<i class="fas fa-fw fa-user-slash"></i>',
'action-add-member': '<i class="fas fa-fw fa-user-plus"></i>', 'action-add-member': '<i class="fas fa-fw fa-user-plus"></i>',
'action-rej-member': '<i class="fas fa-fw fa-user-minus"></i>',
'action-rem-member': '<i class="fas fa-fw fa-user-times"></i>', 'action-rem-member': '<i class="fas fa-fw fa-user-times"></i>',
'action-save': '<i class="fas fa-fw fa-save"></i>', 'action-save': '<i class="fas fa-fw fa-save"></i>',
'action-download': '<i class="fas fa-fw fa-file-download"></i>', 'action-download': '<i class="fas fa-fw fa-file-download"></i>',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment