mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-09 20:40:17 +02:00
Group system overhaul (#588)
* Add open/hidden group membership display and remove * Include requestable groups other than open * Prevent users requesting or leaving non-joinable groups I have not prevented users joining hidden groups however, as there may be some use cases where the direct link is provided for users to request access to the group. Also prevent users generating leave requests for groups they are not a member of. * Refactor Group extension models into a single OneToOne model Added group leader field * Add blankable fields * Switched to use navactive for menu highlighting * Consolidate member state checking for easier code reuse * Added support for group leaders to manage groups * Added info log when a user removes someone from a group * Add ordering to group member list
This commit is contained in:
parent
959e167987
commit
4ae450f963
@ -111,6 +111,7 @@ TEMPLATES = [
|
|||||||
'authentication.context_processors.states',
|
'authentication.context_processors.states',
|
||||||
'authentication.context_processors.membership_state',
|
'authentication.context_processors.membership_state',
|
||||||
'authentication.context_processors.sso',
|
'authentication.context_processors.sso',
|
||||||
|
'groupmanagement.context_processors.can_manage_groups',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -190,6 +190,12 @@ urlpatterns += i18n_patterns(
|
|||||||
url(_(r'^groups/'), groupmanagement.views.groups_view, name='auth_groups'),
|
url(_(r'^groups/'), groupmanagement.views.groups_view, name='auth_groups'),
|
||||||
url(_(r'^group/management/'), groupmanagement.views.group_management,
|
url(_(r'^group/management/'), groupmanagement.views.group_management,
|
||||||
name='auth_group_management'),
|
name='auth_group_management'),
|
||||||
|
url(_(r'^group/membership/$'), groupmanagement.views.group_membership,
|
||||||
|
name='auth_group_membership'),
|
||||||
|
url(_(r'^group/membership/(\w+)/$'), groupmanagement.views.group_membership_list,
|
||||||
|
name='auth_group_membership_list'),
|
||||||
|
url(_(r'^group/membership/(\w+)/remove/(\w+)/$'), groupmanagement.views.group_membership_remove,
|
||||||
|
name='auth_group_membership_remove'),
|
||||||
url(_(r'^group/request_add/(\w+)'), groupmanagement.views.group_request_add,
|
url(_(r'^group/request_add/(\w+)'), groupmanagement.views.group_request_add,
|
||||||
name='auth_group_request_add'),
|
name='auth_group_request_add'),
|
||||||
url(_(r'^group/request/accept/(\w+)'), groupmanagement.views.group_accept_request,
|
url(_(r'^group/request/accept/(\w+)'), groupmanagement.views.group_accept_request,
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from authentication.models import AuthServicesInfo
|
|
||||||
from authentication.states import NONE_STATE, BLUE_STATE, MEMBER_STATE
|
from authentication.states import NONE_STATE, BLUE_STATE, MEMBER_STATE
|
||||||
|
from authentication.managers import UserState
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
def membership_state(request):
|
def membership_state(request):
|
||||||
if request.user.is_authenticated:
|
return UserState.get_membership_state(request)
|
||||||
auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
|
|
||||||
return {'STATE': auth.state}
|
|
||||||
return {'STATE': NONE_STATE}
|
|
||||||
|
|
||||||
|
|
||||||
def states(request):
|
def states(request):
|
||||||
@ -19,6 +16,7 @@ def states(request):
|
|||||||
'MEMBER_BLUE_STATE': [MEMBER_STATE, BLUE_STATE],
|
'MEMBER_BLUE_STATE': [MEMBER_STATE, BLUE_STATE],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def sso(request):
|
def sso(request):
|
||||||
return {
|
return {
|
||||||
'EVE_SSO_CALLBACK_URL': settings.EVE_SSO_CALLBACK_URL,
|
'EVE_SSO_CALLBACK_URL': settings.EVE_SSO_CALLBACK_URL,
|
||||||
|
@ -1,33 +1,23 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from authentication.models import AuthServicesInfo
|
from authentication.managers import UserState
|
||||||
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
def _state_required(states, *args, **kwargs):
|
def _state_required(state_test, *args, **kwargs):
|
||||||
def test_func(user):
|
return user_passes_test(state_test, *args, **kwargs)
|
||||||
if user.is_superuser and settings.SUPERUSER_STATE_BYPASS:
|
|
||||||
return True
|
|
||||||
if user.is_authenticated:
|
|
||||||
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
|
|
||||||
return auth.state in states
|
|
||||||
return False
|
|
||||||
|
|
||||||
return user_passes_test(test_func, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def members(*args, **kwargs):
|
def members(*args, **kwargs):
|
||||||
return _state_required([MEMBER_STATE], *args, **kwargs)
|
return _state_required(UserState.member_state, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def blues(*args, **kwargs):
|
def blues(*args, **kwargs):
|
||||||
return _state_required([BLUE_STATE], *args, **kwargs)
|
return _state_required(UserState.blue_state, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def members_and_blues(*args, **kwargs):
|
def members_and_blues(*args, **kwargs):
|
||||||
return _state_required([MEMBER_STATE, BLUE_STATE], *args, **kwargs)
|
return _state_required(UserState.member_or_blue_state, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def none_state(*args, **kwargs):
|
def none_state(*args, **kwargs):
|
||||||
return _state_required([NONE_STATE], *args, **kwargs)
|
return _state_required(UserState.none_state, *args, **kwargs)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.conf import settings
|
||||||
|
from authentication.states import NONE_STATE, BLUE_STATE, MEMBER_STATE
|
||||||
from authentication.models import AuthServicesInfo
|
from authentication.models import AuthServicesInfo
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@ -143,3 +144,44 @@ class AuthServicesInfoManager:
|
|||||||
logger.info("Updated user %s market info in authservicesinfo model." % user)
|
logger.info("Updated user %s market info in authservicesinfo model." % user)
|
||||||
else:
|
else:
|
||||||
logger.error("Failed to update user %s market info: user does not exist." % user)
|
logger.error("Failed to update user %s market info: user does not exist." % user)
|
||||||
|
|
||||||
|
|
||||||
|
class UserState:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
MEMBER_STATE = MEMBER_STATE
|
||||||
|
BLUE_STATE = BLUE_STATE
|
||||||
|
NONE_STATE = NONE_STATE
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def member_state(cls, user):
|
||||||
|
return cls.state_required(user, [cls.MEMBER_STATE])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def member_or_blue_state(cls, user):
|
||||||
|
return cls.state_required(user, [cls.MEMBER_STATE, cls.BLUE_STATE])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def blue_state(cls, user):
|
||||||
|
return cls.state_required(user, [cls.BLUE_STATE])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def none_state(cls, user):
|
||||||
|
return cls.state_required(user, [cls.NONE_STATE])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_membership_state(cls, request):
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
|
||||||
|
return {'STATE': auth.state}
|
||||||
|
return {'STATE': cls.NONE_STATE}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def state_required(user, states):
|
||||||
|
if user.is_superuser and settings.SUPERUSER_STATE_BYPASS:
|
||||||
|
return True
|
||||||
|
if user.is_authenticated:
|
||||||
|
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
|
||||||
|
return auth.state in states
|
||||||
|
return False
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from groupmanagement.models import GroupDescription
|
|
||||||
from groupmanagement.models import GroupRequest
|
from groupmanagement.models import GroupRequest
|
||||||
from groupmanagement.models import HiddenGroup
|
from groupmanagement.models import AuthGroup
|
||||||
from groupmanagement.models import OpenGroup
|
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(GroupDescription)
|
class AuthGroupAdmin(admin.ModelAdmin):
|
||||||
|
"""
|
||||||
|
Admin model for AuthGroup
|
||||||
|
"""
|
||||||
|
filter_horizontal = ('group_leaders',)
|
||||||
|
|
||||||
admin.site.register(GroupRequest)
|
admin.site.register(GroupRequest)
|
||||||
admin.site.register(HiddenGroup)
|
admin.site.register(AuthGroup, AuthGroupAdmin)
|
||||||
admin.site.register(OpenGroup)
|
|
||||||
|
5
groupmanagement/context_processors.py
Normal file
5
groupmanagement/context_processors.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from groupmanagement.managers import GroupManager
|
||||||
|
|
||||||
|
|
||||||
|
def can_manage_groups(request):
|
||||||
|
return {'can_manage_groups': GroupManager.can_manage_groups(request.user)}
|
56
groupmanagement/managers.py
Normal file
56
groupmanagement/managers.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from django.contrib.auth.models import Group
|
||||||
|
from django.conf import settings
|
||||||
|
from authentication.managers import UserState
|
||||||
|
|
||||||
|
class GroupManager:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_joinable_groups():
|
||||||
|
return Group.objects.exclude(authgroup__internal=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_group_leaders_groups(user):
|
||||||
|
return Group.objects.filter(authgroup__group_leaders__in=[user])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def joinable_group(group):
|
||||||
|
"""
|
||||||
|
Check if a group is a user joinable group, i.e.
|
||||||
|
not an internal group for Corp, Alliance, Members etc
|
||||||
|
:param group: django.contrib.auth.models.Group object
|
||||||
|
:return: bool True if its joinable, False otherwise
|
||||||
|
"""
|
||||||
|
return not group.authgroup.internal
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def has_management_permission(user):
|
||||||
|
return user.has_perm('auth.group_management')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_manage_groups(cls, user):
|
||||||
|
"""
|
||||||
|
For use with user_passes_test decorator.
|
||||||
|
Check if the user can manage groups. Either has the
|
||||||
|
auth.group_management permission or is a leader of at least one group
|
||||||
|
and is also a Member.
|
||||||
|
:param user: django.contrib.auth.models.User for the request
|
||||||
|
:return: bool True if user can manage groups, False otherwise
|
||||||
|
"""
|
||||||
|
if user.is_authenticated:
|
||||||
|
return cls.has_management_permission(user) or (user.leads_groups.all() and UserState.member_state(user))
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def can_manage_group(cls, user, group):
|
||||||
|
"""
|
||||||
|
Check user has permission to manage the given group
|
||||||
|
:param user: User object to test permission of
|
||||||
|
:param group: Group object the user is attempting to manage
|
||||||
|
:return: True if the user can manage the group
|
||||||
|
"""
|
||||||
|
if user.is_authenticated:
|
||||||
|
return cls.has_management_permission(user) or (
|
||||||
|
user.leads_groups.filter(group=group).exists() and UserState.member_state(user))
|
||||||
|
return False
|
112
groupmanagement/migrations/0004_authgroup.py
Normal file
112
groupmanagement/migrations/0004_authgroup.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.2 on 2016-12-04 10:25
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
def internal_group(group):
|
||||||
|
return (
|
||||||
|
"Corp_" in group.name or
|
||||||
|
"Alliance_" in group.name or
|
||||||
|
settings.DEFAULT_AUTH_GROUP in group.name or
|
||||||
|
settings.DEFAULT_BLUE_GROUP in group.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def combine_group_models(apps, schema_editor):
|
||||||
|
Group = apps.get_model("auth", "Group")
|
||||||
|
AuthGroup = apps.get_model("groupmanagement", "AuthGroup")
|
||||||
|
|
||||||
|
for group in Group.objects.all():
|
||||||
|
authgroup = AuthGroup(group=group)
|
||||||
|
if not hasattr(group, 'hiddengroup'):
|
||||||
|
authgroup.hidden = False
|
||||||
|
if hasattr(group, 'opengroup'):
|
||||||
|
authgroup.open = True
|
||||||
|
|
||||||
|
if hasattr(group, 'groupdescription'):
|
||||||
|
authgroup.description = group.groupdescription.description
|
||||||
|
|
||||||
|
authgroup.internal = internal_group(group)
|
||||||
|
authgroup.save()
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_group_models(apps, schema_editor):
|
||||||
|
Group = apps.get_model("auth", "Group")
|
||||||
|
GroupDescription = apps.get_model("groupmanagement", "GroupDescription")
|
||||||
|
OpenGroup = apps.get_model("groupmanagement", "OpenGroup")
|
||||||
|
HiddenGroup = apps.get_model("groupmanagement", "HiddenGroup")
|
||||||
|
|
||||||
|
for group in Group.objects.all():
|
||||||
|
if not hasattr(group, 'authgroup') or group.authgroup is None:
|
||||||
|
continue
|
||||||
|
if group.authgroup.open:
|
||||||
|
OpenGroup.objects.get_or_create(group=group)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
OpenGroup.objects.get(group=group).delete()
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if group.authgroup.hidden:
|
||||||
|
HiddenGroup.objects.get_or_create(group=group)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
HiddenGroup.objects.get(group=group).delete()
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if len(group.authgroup.description):
|
||||||
|
GroupDescription.objects.update_or_create(group=group,
|
||||||
|
defaults={'description': group.authgroup.description})
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0008_alter_user_username_max_length'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('groupmanagement', '0003_default_groups'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='AuthGroup',
|
||||||
|
fields=[
|
||||||
|
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True,
|
||||||
|
serialize=False, to='auth.Group')),
|
||||||
|
('internal', models.BooleanField(default=True, help_text='Internal group, users cannot see, join or request to join this group.<br>Used for groups such as Members, Corp_*, Alliance_* etc.<br><b>Overrides Hidden and Open options when selected.</b>')),
|
||||||
|
('hidden', models.BooleanField(default=True, help_text='Group is hidden from users but can still join with the correct link.')),
|
||||||
|
('open', models.BooleanField(default=False, help_text='Group is open and users will be automatically added upon request. <br>If the group is not open users will need their request manually approved.')),
|
||||||
|
('description', models.CharField(max_length=512, blank=True, help_text='Description of the group shown to users.', )),
|
||||||
|
|
||||||
|
('group_leaders', models.ManyToManyField(related_name='leads_groups', to=settings.AUTH_USER_MODEL, blank=True, help_text='Group leaders can process group requests for this group specifically. Use the auth.group_management permission to allow a user to manage all groups.',)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(combine_group_models, reverse_group_models),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='groupdescription',
|
||||||
|
name='group',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='hiddengroup',
|
||||||
|
name='group',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='opengroup',
|
||||||
|
name='group',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='GroupDescription',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='HiddenGroup',
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='OpenGroup',
|
||||||
|
),
|
||||||
|
]
|
@ -3,19 +3,12 @@ from django.utils.encoding import python_2_unicode_compatible
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
|
from django.db.models.signals import post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from eveonline.models import EveCharacter
|
from eveonline.models import EveCharacter
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class GroupDescription(models.Model):
|
|
||||||
description = models.CharField(max_length=512)
|
|
||||||
group = models.OneToOneField(Group)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.group.name + " - Description"
|
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class GroupRequest(models.Model):
|
class GroupRequest(models.Model):
|
||||||
status = models.CharField(max_length=254)
|
status = models.CharField(max_length=254)
|
||||||
@ -29,16 +22,57 @@ class GroupRequest(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class HiddenGroup(models.Model):
|
class AuthGroup(models.Model):
|
||||||
group = models.OneToOneField(Group)
|
"""
|
||||||
|
Extends Django Group model with a one-to-one field
|
||||||
|
Attributes are accessible via group as if they were in the model
|
||||||
|
e.g. group.authgroup.internal
|
||||||
|
|
||||||
|
Logic:
|
||||||
|
Internal - not requestable by users, at all. Covers Corp_, Alliance_, Members etc groups.
|
||||||
|
Groups are internal by default
|
||||||
|
|
||||||
|
Not Internal and:
|
||||||
|
Hidden - users cannot view, can request if they have the direct link.
|
||||||
|
Not Hidden - Users can view and request the group
|
||||||
|
Open - Users are automatically accepted into the group
|
||||||
|
Not Open - Users requests must be approved before they are added to the group
|
||||||
|
"""
|
||||||
|
group = models.OneToOneField(Group, on_delete=models.CASCADE, primary_key=True)
|
||||||
|
|
||||||
|
internal = models.BooleanField(default=True,
|
||||||
|
help_text="Internal group, users cannot see, join or request to join this group.<br>"
|
||||||
|
"Used for groups such as Members, Corp_*, Alliance_* etc.<br>"
|
||||||
|
"<b>Overrides Hidden and Open options when selected.</b>")
|
||||||
|
hidden = models.BooleanField(default=True,
|
||||||
|
help_text="Group is hidden from users but can still join with the correct link.")
|
||||||
|
open = models.BooleanField(default=False,
|
||||||
|
help_text="Group is open and users will be automatically added upon request. <br>"
|
||||||
|
"If the group is not open users will need their request manually approved.")
|
||||||
|
# Group leaders have management access to this group
|
||||||
|
group_leaders = models.ManyToManyField(User, related_name='leads_groups', blank=True,
|
||||||
|
help_text="Group leaders can process group requests for this group "
|
||||||
|
"specifically. Use the auth.group_management permission to allow "
|
||||||
|
"a user to manage all groups.")
|
||||||
|
|
||||||
|
description = models.CharField(max_length=512, blank=True, help_text="Description of the group shown to users.")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.group.name + " - Hidden"
|
return self.group.name
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@receiver(post_save, sender=Group)
|
||||||
class OpenGroup(models.Model):
|
def create_auth_group(sender, instance, created, **kwargs):
|
||||||
group = models.OneToOneField(Group)
|
"""
|
||||||
|
Creates the AuthGroup model when a group is created
|
||||||
|
"""
|
||||||
|
if created:
|
||||||
|
AuthGroup.objects.create(group=instance)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.group.name + " - Open"
|
@receiver(post_save, sender=Group)
|
||||||
|
def save_auth_group(sender, instance, **kwargs):
|
||||||
|
"""
|
||||||
|
Ensures AuthGroup model is saved automatically
|
||||||
|
"""
|
||||||
|
instance.authgroup.save()
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.conf import settings
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from notifications import notify
|
from notifications import notify
|
||||||
from groupmanagement.models import GroupDescription
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.db.models import Count
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||||
|
from django.http import Http404
|
||||||
|
from groupmanagement.managers import GroupManager
|
||||||
from groupmanagement.models import GroupRequest
|
from groupmanagement.models import GroupRequest
|
||||||
from groupmanagement.models import HiddenGroup
|
|
||||||
from groupmanagement.models import OpenGroup
|
|
||||||
from authentication.models import AuthServicesInfo
|
from authentication.models import AuthServicesInfo
|
||||||
from eveonline.managers import EveManager
|
from eveonline.managers import EveManager
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -20,17 +20,25 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('auth.group_management')
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
def group_management(request):
|
def group_management(request):
|
||||||
logger.debug("group_management called by user %s" % request.user)
|
logger.debug("group_management called by user %s" % request.user)
|
||||||
acceptrequests = []
|
acceptrequests = []
|
||||||
leaverequests = []
|
leaverequests = []
|
||||||
|
|
||||||
for grouprequest in GroupRequest.objects.all():
|
if GroupManager.has_management_permission(request.user):
|
||||||
|
# Full access
|
||||||
|
group_requests = GroupRequest.objects.all()
|
||||||
|
else:
|
||||||
|
# Group specific leader
|
||||||
|
group_requests = GroupRequest.objects.filter(group__authgroup__group_leaders__in=[request.user])
|
||||||
|
|
||||||
|
for grouprequest in group_requests:
|
||||||
if grouprequest.leave_request:
|
if grouprequest.leave_request:
|
||||||
leaverequests.append(grouprequest)
|
leaverequests.append(grouprequest)
|
||||||
else:
|
else:
|
||||||
acceptrequests.append(grouprequest)
|
acceptrequests.append(grouprequest)
|
||||||
|
|
||||||
logger.debug("Providing user %s with %s acceptrequests and %s leaverequests." % (
|
logger.debug("Providing user %s with %s acceptrequests and %s leaverequests." % (
|
||||||
request.user, len(acceptrequests), len(leaverequests)))
|
request.user, len(acceptrequests), len(leaverequests)))
|
||||||
|
|
||||||
@ -40,12 +48,98 @@ def group_management(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('auth.group_management')
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
|
def group_membership(request):
|
||||||
|
logger.debug("group_membership called by user %s" % request.user)
|
||||||
|
# Get all open and closed groups
|
||||||
|
if GroupManager.has_management_permission(request.user):
|
||||||
|
# Full access
|
||||||
|
groups = GroupManager.get_joinable_groups()
|
||||||
|
else:
|
||||||
|
# Group leader specific
|
||||||
|
groups = GroupManager.get_group_leaders_groups(request.user)
|
||||||
|
|
||||||
|
groups = groups.exclude(authgroup__internal=True).annotate(num_members=Count('user')).order_by('name')
|
||||||
|
|
||||||
|
render_items = {'groups': groups}
|
||||||
|
|
||||||
|
return render(request, 'registered/groupmembership.html', context=render_items)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
|
def group_membership_list(request, group_id):
|
||||||
|
logger.debug("group_membership_list called by user %s for group id %s" % (request.user, group_id))
|
||||||
|
try:
|
||||||
|
group = Group.objects.get(id=group_id)
|
||||||
|
|
||||||
|
# Check its a joinable group i.e. not corp or internal
|
||||||
|
# And the user has permission to manage it
|
||||||
|
if not GroupManager.joinable_group(group) or not GroupManager.can_manage_group(request.user, group):
|
||||||
|
logger.warning("User %s attempted to view the membership of group %s but permission was denied" %
|
||||||
|
(request.user, group_id))
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
raise Http404("Group does not exist")
|
||||||
|
|
||||||
|
members = list()
|
||||||
|
|
||||||
|
for member in group.user_set.all().order_by('username'):
|
||||||
|
authinfo = AuthServicesInfo.objects.get_or_create(user=member)[0]
|
||||||
|
|
||||||
|
members.append({
|
||||||
|
'user': member,
|
||||||
|
'main_char': EveManager.get_character_by_id(authinfo.main_char_id)
|
||||||
|
})
|
||||||
|
|
||||||
|
render_items = {'group': group, 'members': members}
|
||||||
|
|
||||||
|
return render(request, 'registered/groupmembers.html', context=render_items)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
|
def group_membership_remove(request, group_id, user_id):
|
||||||
|
logger.debug("group_membership_remove called by user %s for group id %s on user id %s" %
|
||||||
|
(request.user, group_id, user_id))
|
||||||
|
try:
|
||||||
|
group = Group.objects.get(id=group_id)
|
||||||
|
|
||||||
|
# Check its a joinable group i.e. not corp or internal
|
||||||
|
# And the user has permission to manage it
|
||||||
|
if not GroupManager.joinable_group(group) or not GroupManager.can_manage_group(request.user, group):
|
||||||
|
logger.warning("User %s attempted to remove a user from group %s but permission was denied" % (request.user,
|
||||||
|
group_id))
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = group.user_set.get(id=user_id)
|
||||||
|
# Remove group from user
|
||||||
|
user.groups.remove(group)
|
||||||
|
logger.info("User %s removed user %s from group %s" % (request.user, user, group))
|
||||||
|
messages.success(request, "Removed user %s from group %s" % (user, group))
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
messages.warning(request, "User does not exist in that group")
|
||||||
|
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
messages.warning(request, "Group does not exist")
|
||||||
|
|
||||||
|
return redirect('auth_group_membership_list', group_id)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
def group_accept_request(request, group_request_id):
|
def group_accept_request(request, group_request_id):
|
||||||
logger.debug("group_accept_request called by user %s for grouprequest id %s" % (request.user, group_request_id))
|
logger.debug("group_accept_request called by user %s for grouprequest id %s" % (request.user, group_request_id))
|
||||||
try:
|
try:
|
||||||
group_request = GroupRequest.objects.get(id=group_request_id)
|
group_request = GroupRequest.objects.get(id=group_request_id)
|
||||||
group, created = Group.objects.get_or_create(name=group_request.group.name)
|
group, created = Group.objects.get_or_create(name=group_request.group.name)
|
||||||
|
|
||||||
|
if not GroupManager.joinable_group(group_request.group) or \
|
||||||
|
not GroupManager.can_manage_group(request.user, group_request.group):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
group_request.user.groups.add(group)
|
group_request.user.groups.add(group)
|
||||||
group_request.user.save()
|
group_request.user.save()
|
||||||
group_request.delete()
|
group_request.delete()
|
||||||
@ -55,6 +149,11 @@ def group_accept_request(request, group_request_id):
|
|||||||
message="Your application to %s has been accepted." % group_request.group)
|
message="Your application to %s has been accepted." % group_request.group)
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
'Accepted application from %s to %s.' % (group_request.main_char, group_request.group))
|
'Accepted application from %s to %s.' % (group_request.main_char, group_request.group))
|
||||||
|
|
||||||
|
except PermissionDenied as p:
|
||||||
|
logger.warning("User %s attempted to accept group join request %s but permission was denied" %
|
||||||
|
(request.user, group_request_id))
|
||||||
|
raise p
|
||||||
except:
|
except:
|
||||||
messages.error(request, 'An unhandled error occurred while processing the application from %s to %s.' % (
|
messages.error(request, 'An unhandled error occurred while processing the application from %s to %s.' % (
|
||||||
group_request.main_char, group_request.group))
|
group_request.main_char, group_request.group))
|
||||||
@ -66,12 +165,15 @@ def group_accept_request(request, group_request_id):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('auth.group_management')
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
def group_reject_request(request, group_request_id):
|
def group_reject_request(request, group_request_id):
|
||||||
logger.debug("group_reject_request called by user %s for group request id %s" % (request.user, group_request_id))
|
logger.debug("group_reject_request called by user %s for group request id %s" % (request.user, group_request_id))
|
||||||
try:
|
try:
|
||||||
group_request = GroupRequest.objects.get(id=group_request_id)
|
group_request = GroupRequest.objects.get(id=group_request_id)
|
||||||
|
|
||||||
|
if not GroupManager.can_manage_group(request.user, group_request.group):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
if group_request:
|
if group_request:
|
||||||
logger.info("User %s rejected group request from user %s to group %s" % (
|
logger.info("User %s rejected group request from user %s to group %s" % (
|
||||||
request.user, group_request.user, group_request.group.name))
|
request.user, group_request.user, group_request.group.name))
|
||||||
@ -80,6 +182,11 @@ def group_reject_request(request, group_request_id):
|
|||||||
message="Your application to %s has been rejected." % group_request.group)
|
message="Your application to %s has been rejected." % group_request.group)
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
'Rejected application from %s to %s.' % (group_request.main_char, group_request.group))
|
'Rejected application from %s to %s.' % (group_request.main_char, group_request.group))
|
||||||
|
|
||||||
|
except PermissionDenied as p:
|
||||||
|
logger.warning("User %s attempted to reject group join request %s but permission was denied" %
|
||||||
|
(request.user, group_request_id))
|
||||||
|
raise p
|
||||||
except:
|
except:
|
||||||
messages.error(request, 'An unhandled error occured while processing the application from %s to %s.' % (
|
messages.error(request, 'An unhandled error occured while processing the application from %s to %s.' % (
|
||||||
group_request.main_char, group_request.group))
|
group_request.main_char, group_request.group))
|
||||||
@ -91,12 +198,16 @@ def group_reject_request(request, group_request_id):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('auth.group_management')
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
def group_leave_accept_request(request, group_request_id):
|
def group_leave_accept_request(request, group_request_id):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"group_leave_accept_request called by user %s for group request id %s" % (request.user, group_request_id))
|
"group_leave_accept_request called by user %s for group request id %s" % (request.user, group_request_id))
|
||||||
try:
|
try:
|
||||||
group_request = GroupRequest.objects.get(id=group_request_id)
|
group_request = GroupRequest.objects.get(id=group_request_id)
|
||||||
|
|
||||||
|
if not GroupManager.can_manage_group(request.user, group_request.group):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
group, created = Group.objects.get_or_create(name=group_request.group.name)
|
group, created = Group.objects.get_or_create(name=group_request.group.name)
|
||||||
group_request.user.groups.remove(group)
|
group_request.user.groups.remove(group)
|
||||||
group_request.user.save()
|
group_request.user.save()
|
||||||
@ -107,6 +218,10 @@ def group_leave_accept_request(request, group_request_id):
|
|||||||
message="Your request to leave %s has been accepted." % group_request.group)
|
message="Your request to leave %s has been accepted." % group_request.group)
|
||||||
messages.success(request,
|
messages.success(request,
|
||||||
'Accepted application from %s to leave %s.' % (group_request.main_char, group_request.group))
|
'Accepted application from %s to leave %s.' % (group_request.main_char, group_request.group))
|
||||||
|
except PermissionDenied as p:
|
||||||
|
logger.warning("User %s attempted to accept group leave request %s but permission was denied" %
|
||||||
|
(request.user, group_request_id))
|
||||||
|
raise p
|
||||||
except:
|
except:
|
||||||
messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
|
messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
|
||||||
group_request.main_char, group_request.group))
|
group_request.main_char, group_request.group))
|
||||||
@ -118,13 +233,16 @@ def group_leave_accept_request(request, group_request_id):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('auth.group_management')
|
@user_passes_test(GroupManager.can_manage_groups)
|
||||||
def group_leave_reject_request(request, group_request_id):
|
def group_leave_reject_request(request, group_request_id):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"group_leave_reject_request called by user %s for group request id %s" % (request.user, group_request_id))
|
"group_leave_reject_request called by user %s for group request id %s" % (request.user, group_request_id))
|
||||||
try:
|
try:
|
||||||
group_request = GroupRequest.objects.get(id=group_request_id)
|
group_request = GroupRequest.objects.get(id=group_request_id)
|
||||||
|
|
||||||
|
if not GroupManager.can_manage_group(request.user, group_request.group):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
if group_request:
|
if group_request:
|
||||||
group_request.delete()
|
group_request.delete()
|
||||||
logger.info("User %s rejected group leave request from user %s for group %s" % (
|
logger.info("User %s rejected group leave request from user %s for group %s" % (
|
||||||
@ -133,6 +251,10 @@ def group_leave_reject_request(request, group_request_id):
|
|||||||
message="Your request to leave %s has been rejected." % group_request.group)
|
message="Your request to leave %s has been rejected." % group_request.group)
|
||||||
messages.success(request, 'Rejected application from %s to leave %s.' % (
|
messages.success(request, 'Rejected application from %s to leave %s.' % (
|
||||||
group_request.main_char, group_request.group))
|
group_request.main_char, group_request.group))
|
||||||
|
except PermissionDenied as p:
|
||||||
|
logger.warning("User %s attempted to reject group leave request %s but permission was denied" %
|
||||||
|
(request.user, group_request_id))
|
||||||
|
raise p
|
||||||
except:
|
except:
|
||||||
messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
|
messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
|
||||||
group_request.main_char, group_request.group))
|
group_request.main_char, group_request.group))
|
||||||
@ -146,37 +268,16 @@ def group_leave_reject_request(request, group_request_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def groups_view(request):
|
def groups_view(request):
|
||||||
logger.debug("groups_view called by user %s" % request.user)
|
logger.debug("groups_view called by user %s" % request.user)
|
||||||
paired_list = []
|
groups = []
|
||||||
|
|
||||||
for group in Group.objects.all():
|
for group in GroupManager.get_joinable_groups():
|
||||||
# Check if group is a corp
|
# Exclude hidden
|
||||||
if "Corp_" in group.name:
|
if not group.authgroup.hidden:
|
||||||
pass
|
|
||||||
elif "Alliance_" in group.name:
|
|
||||||
pass
|
|
||||||
elif settings.DEFAULT_AUTH_GROUP in group.name:
|
|
||||||
pass
|
|
||||||
elif settings.DEFAULT_BLUE_GROUP in group.name:
|
|
||||||
pass
|
|
||||||
elif HiddenGroup.objects.filter(group=group).exists():
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# Get the descriptionn
|
|
||||||
group_desc = GroupDescription.objects.filter(group=group)
|
|
||||||
group_request = GroupRequest.objects.filter(user=request.user).filter(group=group)
|
group_request = GroupRequest.objects.filter(user=request.user).filter(group=group)
|
||||||
|
|
||||||
if group_desc:
|
groups.append({'group': group, 'request': group_request[0] if group_request else None})
|
||||||
if group_request:
|
|
||||||
paired_list.append((group, group_desc[0], group_request[0]))
|
|
||||||
else:
|
|
||||||
paired_list.append((group, group_desc[0], ""))
|
|
||||||
else:
|
|
||||||
if group_request:
|
|
||||||
paired_list.append((group, "", group_request[0]))
|
|
||||||
else:
|
|
||||||
paired_list.append((group, "", ""))
|
|
||||||
|
|
||||||
render_items = {'pairs': paired_list}
|
render_items = {'groups': groups}
|
||||||
return render(request, 'registered/groups.html', context=render_items)
|
return render(request, 'registered/groups.html', context=render_items)
|
||||||
|
|
||||||
|
|
||||||
@ -184,7 +285,12 @@ def groups_view(request):
|
|||||||
def group_request_add(request, group_id):
|
def group_request_add(request, group_id):
|
||||||
logger.debug("group_request_add called by user %s for group id %s" % (request.user, group_id))
|
logger.debug("group_request_add called by user %s for group id %s" % (request.user, group_id))
|
||||||
group = Group.objects.get(id=group_id)
|
group = Group.objects.get(id=group_id)
|
||||||
if OpenGroup.objects.filter(group=group).exists():
|
if not GroupManager.joinable_group(group):
|
||||||
|
logger.warning("User %s attempted to join group id %s but it is not a joinable group" %
|
||||||
|
(request.user, group_id))
|
||||||
|
messages.warning(request, "You cannot join that group")
|
||||||
|
return redirect('auth_groups')
|
||||||
|
if group.authgroup.open:
|
||||||
logger.info("%s joining %s as is an open group" % (request.user, group))
|
logger.info("%s joining %s as is an open group" % (request.user, group))
|
||||||
request.user.groups.add(group)
|
request.user.groups.add(group)
|
||||||
return redirect("auth_groups")
|
return redirect("auth_groups")
|
||||||
@ -205,7 +311,17 @@ def group_request_add(request, group_id):
|
|||||||
def group_request_leave(request, group_id):
|
def group_request_leave(request, group_id):
|
||||||
logger.debug("group_request_leave called by user %s for group id %s" % (request.user, group_id))
|
logger.debug("group_request_leave called by user %s for group id %s" % (request.user, group_id))
|
||||||
group = Group.objects.get(id=group_id)
|
group = Group.objects.get(id=group_id)
|
||||||
if OpenGroup.objects.filter(group=group).exists():
|
if not GroupManager.joinable_group(group):
|
||||||
|
logger.warning("User %s attempted to leave group id %s but it is not a joinable group" %
|
||||||
|
(request.user, group_id))
|
||||||
|
messages.warning(request, "You cannot leave that group")
|
||||||
|
return redirect('auth_groups')
|
||||||
|
if group not in request.user.groups.all():
|
||||||
|
logger.debug("User %s attempted to leave group id %s but they are not a member" %
|
||||||
|
(request.user, group_id))
|
||||||
|
messages.warning(request, "You are not a member of that group")
|
||||||
|
return redirect('auth_groups')
|
||||||
|
if group.authgroup.open:
|
||||||
logger.info("%s leaving %s as is an open group" % (request.user, group))
|
logger.info("%s leaving %s as is an open group" % (request.user, group))
|
||||||
request.user.groups.remove(group)
|
request.user.groups.remove(group)
|
||||||
return redirect("auth_groups")
|
return redirect("auth_groups")
|
||||||
|
@ -153,7 +153,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if perms.auth.group_management %}
|
{% if can_manage_groups %}
|
||||||
<li>
|
<li>
|
||||||
<a class="{% navactive request 'auth_group_management' %}" href="{% url 'auth_group_management' %}">
|
<a class="{% navactive request 'auth_group_management' %}" href="{% url 'auth_group_management' %}">
|
||||||
<i class="fa fa-lock fa-sitemap fa-fw grayiconecolor"></i>{% trans " Group Management" %}
|
<i class="fa fa-lock fa-sitemap fa-fw grayiconecolor"></i>{% trans " Group Management" %}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<h3 class="page-header text-center">{% trans "Group Management" %}</h3>
|
{% include 'registered/groupmanagementmenu.html' %}
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="active"><a data-toggle="tab" href="#add">{% trans "Group Add Requests" %}</a></li>
|
<li class="active"><a data-toggle="tab" href="#add">{% trans "Group Add Requests" %}</a></li>
|
||||||
<li><a data-toggle="tab" href="#leave">{% trans "Group Leave Requests" %}</a></li>
|
<li><a data-toggle="tab" href="#leave">{% trans "Group Leave Requests" %}</a></li>
|
||||||
|
27
stock/templates/registered/groupmanagementmenu.html
Normal file
27
stock/templates/registered/groupmanagementmenu.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{% load staticfiles %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load navactive %}
|
||||||
|
|
||||||
|
<nav class="navbar navbar-default">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||||
|
<span class="sr-only">{% trans "Toggle navigation" %}</span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="#">Group Management</a>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li class="{% navactive request 'auth_group_management' %}">
|
||||||
|
<a href="{% url 'auth_group_management' %}">{% trans "Group Requests" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="{% navactive request 'auth_group_membership auth_group_membership_list' %}">
|
||||||
|
<a href="{% url 'auth_group_membership' %}">{% trans "Group Membership" %}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
44
stock/templates/registered/groupmembers.html
Normal file
44
stock/templates/registered/groupmembers.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{% extends "public/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}Alliance Auth{% endblock %}
|
||||||
|
|
||||||
|
{% block page_title %}{% trans "Group Members" %}{% endblock page_title %}
|
||||||
|
{% block extra_css %}{% endblock extra_css %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
{% include 'registered/groupmanagementmenu.html' %}
|
||||||
|
<h3>{{ group.name }} {% trans 'Members' %}</h3>
|
||||||
|
<div id="list" class="">
|
||||||
|
{% if group.user_set %}
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center">{% trans "User" %}</th>
|
||||||
|
<th class="text-center">{% trans "Character" %}</th>
|
||||||
|
<th class="text-center">{% trans "Corp" %}</th>
|
||||||
|
<th class="text-center">{% trans "Alliance" %}</th>
|
||||||
|
<th class="text-center">{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
{% for member in members %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">{{ member.user.username }}</td>
|
||||||
|
<td class="text-center">{{ member.main_char.character_name }}</td>
|
||||||
|
<td class="text-center">{{ member.main_char.corporation_name }}</td>
|
||||||
|
<td class="text-center">{{ member.main_char.alliance_name }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{% url 'auth_group_membership_remove' group.id member.user.id %}" class="btn btn-danger"
|
||||||
|
title="{% trans "Remove from group" %}">
|
||||||
|
<i class="glyphicon glyphicon-remove"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-warning text-center">No group members to list.</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
54
stock/templates/registered/groupmembership.html
Normal file
54
stock/templates/registered/groupmembership.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{% extends "public/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}Alliance Auth{% endblock %}
|
||||||
|
|
||||||
|
{% block page_title %}{% trans "Groups Membership" %}{% endblock page_title %}
|
||||||
|
{% block extra_css %}{% endblock extra_css %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
{% include 'registered/groupmanagementmenu.html' %}
|
||||||
|
<div>
|
||||||
|
{% if groups %}
|
||||||
|
<h3>Groups</h3>
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center">{% trans "Name" %}</th>
|
||||||
|
<th class="text-center">{% trans "Description" %}</th>
|
||||||
|
<th class="text-center">{% trans "Status" %}</th>
|
||||||
|
<th class="text-center">{% trans "Member Count" %}</th>
|
||||||
|
<th class="text-center">{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
{% for group in groups %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">{{ group.name }}</td>
|
||||||
|
<td class="text-center">{{ group.authgroup.description }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{% if group.authgroup.hidden %}
|
||||||
|
<span class="label label-info">{% trans "Hidden" %}</span>
|
||||||
|
{% elif group.authgroup.open %}
|
||||||
|
<span class="label label-success">{% trans "Open" %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="label label-default">{% trans "Requestable" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{{ group.num_members }}
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<a href="{% url 'auth_group_membership_list' group.id %}" class="btn btn-primary"
|
||||||
|
title="{% trans "View Members" %}">
|
||||||
|
<i class="glyphicon glyphicon-eye-open"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-warning text-center">No groups to list.</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -11,36 +11,36 @@
|
|||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<h1 class="page-header text-center">{% trans "Available Groups" %}</h1>
|
<h1 class="page-header text-center">{% trans "Available Groups" %}</h1>
|
||||||
{% if STATE == MEMBER_STATE or user.is_superuser %}
|
{% if STATE == MEMBER_STATE or user.is_superuser %}
|
||||||
{% if pairs %}
|
{% if groups %}
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-center">{% trans "GroupName" %}</th>
|
<th class="text-center">{% trans "Name" %}</th>
|
||||||
<th class="text-center">{% trans "GroupDesc" %}</th>
|
<th class="text-center">{% trans "Description" %}</th>
|
||||||
<th class="text-center">{% trans "Action" %}</th>
|
<th class="text-center">{% trans "Action" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% for pair in pairs %}
|
{% for g in groups %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center">{{ pair.0.name }}</td>
|
<td class="text-center">{{ g.group.name }}</td>
|
||||||
<td class="text-center">{{ pair.1.description }}</td>
|
<td class="text-center">{{ g.group.authgroup.description }}</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
{% if pair.0 in user.groups.all %}
|
{% if g.group in user.groups.all %}
|
||||||
{% if pair.2 == "" %}
|
{% if not g.request %}
|
||||||
<a href="{% url 'auth_group_request_leave' pair.0.id %}" class="btn btn-danger">
|
<a href="{% url 'auth_group_request_leave' g.group.id %}" class="btn btn-danger">
|
||||||
{% trans "Leave" %}
|
{% trans "Leave" %}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="button" class="btn btn-primary" disabled>
|
<button type="button" class="btn btn-primary" disabled>
|
||||||
{{ pair.2.status }}
|
{{ g.request.status }}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% elif pair.2 == "" %}
|
{% elif not g.request %}
|
||||||
<a href="{% url 'auth_group_request_add' pair.0.id %}" class="btn btn-success">
|
<a href="{% url 'auth_group_request_add' g.group.id %}" class="btn btn-success">
|
||||||
{% trans "Request" %}
|
{% trans "Request" %}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="button" class="btn btn-primary" disabled>
|
<button type="button" class="btn btn-primary" disabled>
|
||||||
{{ pair.2.status }}
|
{{ g.request.status }}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user