This commit is contained in:
Ariel Rin 2021-06-23 09:58:25 +10:00
commit ae7cfbff35
14 changed files with 113 additions and 36 deletions

View File

@ -448,6 +448,8 @@ class StateAdmin(admin.ModelAdmin):
elif db_field.name == "member_alliances": elif db_field.name == "member_alliances":
kwargs["queryset"] = EveAllianceInfo.objects.all()\ kwargs["queryset"] = EveAllianceInfo.objects.all()\
.order_by(Lower('alliance_name')) .order_by(Lower('alliance_name'))
elif db_field.name == "permissions":
kwargs["queryset"] = Permission.objects.select_related("content_type").all()
return super().formfield_for_manytomany(db_field, request, **kwargs) return super().formfield_for_manytomany(db_field, request, **kwargs)
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):

View File

@ -32,9 +32,11 @@ class EveCharacterManager(models.Manager):
def update_character(self, character_id): def update_character(self, character_id):
return self.get(character_id=character_id).update_character() return self.get(character_id=character_id).update_character()
def get_character_by_id(self, char_id): def get_character_by_id(self, character_id: int):
if self.filter(character_id=char_id).exists(): """Return character by character ID or None if not found."""
return self.get(character_id=char_id) try:
return self.get(character_id=character_id)
except self.model.DoesNotExist:
return None return None

View File

@ -1,4 +1,5 @@
from django.apps import apps from django.apps import apps
from django.contrib.auth.models import Permission
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.models import Group as BaseGroup, User from django.contrib.auth.models import Group as BaseGroup, User
from django.db.models import Count from django.db.models import Count
@ -122,7 +123,7 @@ class GroupAdmin(admin.ModelAdmin):
qs = super().get_queryset(request) qs = super().get_queryset(request)
if _has_auto_groups: if _has_auto_groups:
qs = qs.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set') qs = qs.prefetch_related('managedalliancegroup_set', 'managedcorpgroup_set')
qs = qs.prefetch_related('authgroup__group_leaders') qs = qs.prefetch_related('authgroup__group_leaders').select_related('authgroup')
qs = qs.annotate( qs = qs.annotate(
member_count=Count('user', distinct=True), member_count=Count('user', distinct=True),
) )
@ -168,6 +169,11 @@ class GroupAdmin(admin.ModelAdmin):
filter_horizontal = ('permissions',) filter_horizontal = ('permissions',)
inlines = (AuthGroupInlineAdmin,) inlines = (AuthGroupInlineAdmin,)
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "permissions":
kwargs["queryset"] = Permission.objects.select_related("content_type").all()
return super().formfield_for_manytomany(db_field, request, **kwargs)
class Group(BaseGroup): class Group(BaseGroup):
class Meta: class Meta:

View File

@ -15,6 +15,7 @@ class Teamspeak3UserAdmin(ServicesUserAdmin):
@admin.register(AuthTS) @admin.register(AuthTS)
class AuthTSgroupAdmin(admin.ModelAdmin): class AuthTSgroupAdmin(admin.ModelAdmin):
change_list_template = 'admin/teamspeak3/authts/change_list.html'
ordering = ('auth_group__name', ) ordering = ('auth_group__name', )
list_select_related = True list_select_related = True

View File

@ -0,0 +1,11 @@
{% extends "admin/change_list.html" %}
{% load i18n static %}
{% block object-tools-items %}
{{ block.super }}
<li>
<a href="{% url 'teamspeak3:admin_update_ts3_groups' %}" class="btn btn-high">
Update TS3 groups
</a>
</li>
{% endblock %}

View File

@ -216,6 +216,24 @@ class Teamspeak3ViewsTestCase(TestCase):
self.assertEqual(ts3_user.perm_key, '123abc') self.assertEqual(ts3_user.perm_key, '123abc')
self.assertTrue(tasks_manager.return_value.__enter__.return_value.update_groups.called) self.assertTrue(tasks_manager.return_value.__enter__.return_value.update_groups.called)
@mock.patch(MODULE_PATH + '.views.Teamspeak3Tasks')
@mock.patch(MODULE_PATH + '.views.messages')
def test_should_update_ts_groups(self, messages, Teamspeak3Tasks):
# given
self.member.is_superuser = True
self.member.is_staff = True
self.member.save()
self.login()
# when
response = self.client.get(urls.reverse('teamspeak3:admin_update_ts3_groups'))
# then
self.assertRedirects(
response, urls.reverse('admin:teamspeak3_authts_changelist'),
target_status_code=200
)
self.assertTrue(messages.info.called)
self.assertTrue(Teamspeak3Tasks.run_ts3_group_update.delay.called)
class Teamspeak3SignalsTestCase(TestCase): class Teamspeak3SignalsTestCase(TestCase):
def setUp(self): def setUp(self):

View File

@ -6,12 +6,14 @@ app_name = 'teamspeak3'
module_urls = [ module_urls = [
# Teamspeak3 service control # Teamspeak3 service control
url(r'^activate/$', views.activate_teamspeak3, url(r'^activate/$', views.activate_teamspeak3, name='activate'),
name='activate'), url(r'^deactivate/$', views.deactivate_teamspeak3, name='deactivate'),
url(r'^deactivate/$', views.deactivate_teamspeak3, url(r'^reset_perm/$', views.reset_teamspeak3_perm, name='reset_perm'),
name='deactivate'), url(
url(r'^reset_perm/$', views.reset_teamspeak3_perm, r'^admin_update_ts3_groups/$',
name='reset_perm'), views.admin_update_ts3_groups,
name='admin_update_ts3_groups'
),
# Teamspeak Urls # Teamspeak Urls
url(r'^verify/$', views.verify_teamspeak3, name='verify'), url(r'^verify/$', views.verify_teamspeak3, name='verify'),

View File

@ -1,6 +1,7 @@
import logging import logging
from django.contrib import messages from django.contrib import messages
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.conf import settings from django.conf import settings
@ -98,3 +99,11 @@ def reset_teamspeak3_perm(request):
logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user) logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user)
messages.error(request, _('An error occurred while processing your TeamSpeak3 account.')) messages.error(request, _('An error occurred while processing your TeamSpeak3 account.'))
return redirect("services:services") return redirect("services:services")
@login_required
@staff_member_required
def admin_update_ts3_groups(request):
Teamspeak3Tasks.run_ts3_group_update.delay()
messages.info(request, "Started updating TS3 server groups...")
return redirect("admin:teamspeak3_authts_changelist")

View File

@ -30,15 +30,7 @@
<div class="row" id="site-body-wrapper"> <div class="row" id="site-body-wrapper">
{% include 'allianceauth/side-menu.html' %} {% include 'allianceauth/side-menu.html' %}
<div class="col-sm-10"> <div class="col-sm-10">
{% if messages %} {% include 'allianceauth/messages.html' %}
<br>
{% for message in messages %}
<div class="alert alert-{{ message.level_tag }}">{{ message }}</div>
{% if not forloop.last %}
<br>
{% endif %}
{% endfor %}
{% endif %}
{% block content %} {% block content %}
{% endblock content %} {% endblock content %}
</div> </div>

View File

@ -0,0 +1,20 @@
{% if messages %}
<br>
{% for message in messages %}
<div class="alert alert-{{ message.level_tag }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
{% if message.level_tag == "info" %}
<i class="fas fa-info-circle"></i>
{% elif message.level_tag == "success" %}
<i class="fas fa-check-circle"></i>
{% elif message.level_tag == "warning" %}
<i class="fas fa-exclamation-circle"></i>
{% elif message.level_tag == "danger" %}
<i class="fas fa-exclamation-triangle"></i>
{% endif %}
&nbsp;{{ message }}
</div>
{% endfor %}
{% endif %}

View File

@ -23,7 +23,7 @@ Within your auth project exists two folders named `static` and `templates`. Thes
You can add extra static or templates by putting files in these folders. Note that changes to static requires running the `python manage.py collectstatic` command to copy to the web server directory. You can add extra static or templates by putting files in these folders. Note that changes to static requires running the `python manage.py collectstatic` command to copy to the web server directory.
It is possible to overload static and templates shipped with Django or Alliance Auth by including a file with the exact path of the one you wish to overload. For instance if you wish to add extra links to the menu bar by editing the template, you would make a copy of the `allianceauth/templates/allianceauth/base.html` file to `myauth/templates/allinceauth/base.html` and edit it there. Notice the paths are identical after the `templates/` directory - this is critical for it to be recognized. Your custom template would be used instead of the one included with Alliance Auth when Django renders the web page. Similar idea for static: put CSS or images at an identical path after the `static/` directory and they will be copied to the web server directory instead of the ones included. It is possible to overload static and templates shipped with Django or Alliance Auth by including a file with the exact path of the one you wish to overload. For instance if you wish to add extra links to the menu bar by editing the template, you would make a copy of the `allianceauth/templates/allianceauth/base.html` file to `myauth/templates/allianceauth/base.html` and edit it there. Notice the paths are identical after the `templates/` directory - this is critical for it to be recognized. Your custom template would be used instead of the one included with Alliance Auth when Django renders the web page. Similar idea for static: put CSS or images at an identical path after the `static/` directory and they will be copied to the web server directory instead of the ones included.
## Custom URLs and Views ## Custom URLs and Views

View File

@ -105,7 +105,9 @@ Click the URL provided to automatically connect to our server. It will prompt yo
Now we need to make groups. AllianceAuth handles groups in teamspeak differently: instead of creating groups it creates an association between groups in TeamSpeak and groups in AllianceAuth. Go ahead and make the groups you want to associate with auth groups, keeping in mind multiple TeamSpeak groups can be associated with a single auth group. Now we need to make groups. AllianceAuth handles groups in teamspeak differently: instead of creating groups it creates an association between groups in TeamSpeak and groups in AllianceAuth. Go ahead and make the groups you want to associate with auth groups, keeping in mind multiple TeamSpeak groups can be associated with a single auth group.
Navigate back to the AllianceAuth admin interface (example.com/admin) and under `Services`, select `Auth / TS Groups`. In the top-right corner click `Add`. Navigate back to the AllianceAuth admin interface (example.com/admin) and under `Teamspeak3`, select `Auth / TS Groups`.
In the top-right corner click, first click on `Update TS3 Groups` to fetch the newly created server groups from TS3 (this may take a minute to complete). Then click on `Add Auth / TS Group` to link Auth groups with TS3 server groups.
The dropdown box provides all auth groups. Select one and assign TeamSpeak groups from the panels below. If these panels are empty, wait a minute for the database update to run, or see the [troubleshooting section](#ts-group-models-not-populating-on-admin-site) below. The dropdown box provides all auth groups. Select one and assign TeamSpeak groups from the panels below. If these panels are empty, wait a minute for the database update to run, or see the [troubleshooting section](#ts-group-models-not-populating-on-admin-site) below.
@ -119,13 +121,23 @@ To enable advanced permissions, on your client go to the `Tools` menu, `Applicat
### TS group models not populating on admin site ### TS group models not populating on admin site
The method which populates these runs every 30 minutes. To populate manually, start a django shell: The method which populates these runs every 30 minutes. To populate manually you start the process from the admin site or from the Django shell.
#### Admin Site
Navigate to the AllianceAuth admin interface and under `Teamspeak3`, select `Auth / TS Groups`.
Then, in the top-right corner click, click on `Update TS3 Groups` to start the process of fetching the server groups from TS3 (this may take a minute to complete).
#### Django Shell
Start a django shell with:
```bash ```bash
python manage.py shell python manage.py shell
``` ```
And execute the update: And execute the update as follows:
```python ```python
from allianceauth.services.modules.teamspeak3.tasks import Teamspeak3Tasks from allianceauth.services.modules.teamspeak3.tasks import Teamspeak3Tasks

View File

@ -104,6 +104,8 @@ CREATE DATABASE alliance_auth CHARACTER SET utf8mb4;
GRANT ALL PRIVILEGES ON alliance_auth . * TO 'allianceserver'@'localhost'; GRANT ALL PRIVILEGES ON alliance_auth . * TO 'allianceserver'@'localhost';
``` ```
Once your database is set up, you can leave the SQL shell with `exit`.
Add timezone tables to your mysql installation: Add timezone tables to your mysql installation:
```bash ```bash
@ -177,7 +179,7 @@ source /home/allianceserver/venv/auth/bin/activate
You need to have a dedicated Eve SSO app for Alliance auth. Please go to [EVE Developer](https://developers.eveonline.com/applications) to create one. You need to have a dedicated Eve SSO app for Alliance auth. Please go to [EVE Developer](https://developers.eveonline.com/applications) to create one.
For **scopes** your SSO app needs to have at least `publicData`. Additional scopes depends on which Alliance Auth apps you will be using. For convenience we recommend adding all available ESO scopes to your SSO app. Note that Alliance Auth will always ask the users to approve specific scopes before they are used. For **scopes** your SSO app needs to have at least `publicData`. Additional scopes depends on which Alliance Auth apps you will be using. For convenience, we recommend adding all available ESO scopes to your SSO app. Note that Alliance Auth will always ask the users to approve specific scopes before they are used.
As **callback URL** you want to define the URL of your Alliance Auth site plus the route: `/sso/callback`. Example for a valid callback URL: `https://auth.example.com/sso/callback` As **callback URL** you want to define the URL of your Alliance Auth site plus the route: `/sso/callback`. Example for a valid callback URL: `https://auth.example.com/sso/callback`
@ -236,7 +238,7 @@ Check to ensure your settings are valid.
python /home/allianceserver/myauth/manage.py check python /home/allianceserver/myauth/manage.py check
``` ```
And finally ensure the allianceserver user has read/write permissions to this directory before proceeding. Finally, ensure the allianceserver user has read/write permissions to this directory before proceeding.
```bash ```bash
chown -R allianceserver:allianceserver /home/allianceserver/myauth chown -R allianceserver:allianceserver /home/allianceserver/myauth
@ -275,7 +277,7 @@ systemctl enable supervisord.service
systemctl start supervisord.service systemctl start supervisord.service
``` ```
Once installed it needs a configuration file to know which processes to watch. Your Alliance Auth project comes with a ready-to-use template which will ensure the Celery workers, Celery task scheduler and Gunicorn are all running. Once installed, it needs a configuration file to know which processes to watch. Your Alliance Auth project comes with a ready-to-use template which will ensure the Celery workers, Celery task scheduler and Gunicorn are all running.
Ubuntu: Ubuntu:
@ -289,7 +291,7 @@ CentOS:
ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini ln -s /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
``` ```
And activate it with `supervisorctl reload`. Activate it with `supervisorctl reload`.
You can check the status of the processes with `supervisorctl status`. Logs from these processes are available in `/home/allianceserver/myauth/log` named by process. You can check the status of the processes with `supervisorctl status`. Logs from these processes are available in `/home/allianceserver/myauth/log` named by process.
@ -304,11 +306,11 @@ You can check the status of the processes with `supervisorctl status`. Logs from
Once installed, decide on whether you're going to use [NGINX](nginx.md) or [Apache](apache.md) and follow the respective guide. Once installed, decide on whether you're going to use [NGINX](nginx.md) or [Apache](apache.md) and follow the respective guide.
Note that Alliance Auth is designed to run with web servers on HTTPS. While running on HTTP is technically possible, it is not recommended for production use and some functions (e.g. Email confirmation links) will not work properly. Note that Alliance Auth is designed to run with web servers on HTTPS. While running on HTTP is technically possible, it is not recommended for production use, and some functions (e.g. Email confirmation links) will not work properly.
## Superuser ## Superuser
Before using your auth site it is essential to create a superuser account. This account will have all permissions in Alliance Auth. It's OK to use this as your personal auth account. Before using your auth site, it is essential to create a superuser account. This account will have all permissions in Alliance Auth. It's OK to use this as your personal auth account.
```bash ```bash
python /home/allianceserver/myauth/manage.py createsuperuser python /home/allianceserver/myauth/manage.py createsuperuser
@ -316,7 +318,7 @@ python /home/allianceserver/myauth/manage.py createsuperuser
The superuser account is accessed by logging in via the admin site at `https://example.com/admin`. The superuser account is accessed by logging in via the admin site at `https://example.com/admin`.
If you intend to use this account as your personal auth account you need to add a main character. Navigate to the normal user dashboard (at `https://example.com`) after logging in via the admin site and select `Change Main`. Once a main character has been added it is possible to use SSO to login to this account. If you intend to use this account as your personal auth account you need to add a main character. Navigate to the normal user dashboard (at `https://example.com`) after logging in via the admin site and select `Change Main`. Once a main character has been added, it is possible to use SSO to login to this account.
## Updating ## Updating
@ -340,7 +342,7 @@ Some releases come with new or changed models. Update your database to reflect t
python /home/allianceserver/myauth/manage.py migrate python /home/allianceserver/myauth/manage.py migrate
``` ```
Finally some releases come with new or changed static files. Run the following command to update your static files folder: Finally, some releases come with new or changed static files. Run the following command to update your static files folder:
```bash ```bash
python /home/allianceserver/myauth/manage.py collectstatic python /home/allianceserver/myauth/manage.py collectstatic

View File

@ -17,7 +17,7 @@ Mature Alliance Auth installations, or those with actively developed extensions
This can make it confusing for admins to apply the right permissions, contribute to larger queries in backend management or simply look unsightly. This can make it confusing for admins to apply the right permissions, contribute to larger queries in backend management or simply look unsightly.
```python ```shell
python manage.py remove_stale_contenttypes --include-stale-apps python manage.py remove_stale_contenttypes --include-stale-apps
``` ```