Compare commits

...

38 Commits

Author SHA1 Message Date
Basraah
debd6ef2b9 Version bump to v2.2.2 2019-12-05 02:37:22 +00:00
Basraah
58e9c21e4f Merge branch 'issue-1176' into 'master'
Fix issue #1176: Prevent Django 3 installation

Closes #1176

See merge request allianceauth/allianceauth!1142
2019-12-05 02:36:03 +00:00
ErikKalkoken
c7c3083e3e Fix issue #1176: Prevent Django 3 installation 2019-12-04 14:02:03 +01:00
Basraah
63d061e9f2 Merge branch 'bug-1165' into 'master'
add fix and unittest for issue #1165

See merge request allianceauth/allianceauth!1137
2019-09-12 09:53:05 +00:00
ErikKalkoken
1887bdb90a add fix and unittest for issue #1165 2019-09-08 23:09:20 +02:00
Basraah
69addb068a Merge branch 'patch-3' into 'master'
Add discord warning for tasks

See merge request allianceauth/allianceauth!1136
2019-08-30 03:22:49 +00:00
Aaron Kable
a62c3ce0f9 Add discord warning for tasks 2019-08-30 03:22:49 +00:00
Basraah
aecc94bdb3 Version bump to v2.2.1 2019-08-25 03:20:45 +00:00
Basraah
fcb7f2905a Merge branch 'url_group' into 'master'
urlize group descriptions to hyperlink if required

See merge request allianceauth/allianceauth!1132
2019-08-24 22:48:57 +00:00
Basraah
34c7169ca3 Merge branch 'local_settings_update' into 'master'
Enable utf8mb4 charset option in local.py by default

See merge request allianceauth/allianceauth!1131
2019-08-24 22:47:25 +00:00
Basraah
6e450061f4 Merge branch 'group-rework' into 'master'
Make group joins a bit clearer

See merge request allianceauth/allianceauth!1134
2019-08-24 22:46:46 +00:00
Basraah
fc3d7e9f43 Merge branch 'auto-group' into 'master'
Fix Autogroups, Add Autogroups to admin

Closes #1087

See merge request allianceauth/allianceauth!1133
2019-08-24 22:45:25 +00:00
Aaron Kable
514db4f9a2 Make group joins a bit clearer 2019-08-23 03:54:24 -04:00
Aaron Kable
23a8b65ce2 Fix Autogroups, Add Autogroups to admin 2019-08-22 20:37:55 -04:00
Aaron Kable
f8e6662bc8 urlize group descriptions to hyperlink if required 2019-07-26 00:35:59 -04:00
Col Crunch
89be2456fb Update local.py to have the utf8mb4 charset option enabled in the database settings. This brings the settings inline with the documentation update. 2019-06-30 22:58:13 -04:00
Basraah
bfd3451717 Merge branch 'db_doc' into 'master'
Use utf8mb4 When Creating Auth DB

See merge request allianceauth/allianceauth!1130
2019-06-20 00:49:30 +00:00
Col Crunch
0b759d6a32 Use utf8mb4 when creating auth db rather than utf8 2019-06-19 16:27:18 -04:00
Basraah
65e05084e6 Merge branch 'master' into 'master'
Show "Help" link only to superuser

See merge request allianceauth/allianceauth!1129
2019-06-17 00:56:28 +00:00
Peter Pfeufer
f25a4ed386 Show "Help" lnk only to superuser 2019-06-15 23:44:36 +02:00
Basraah
b2a1d41829 Merge branch 'patch-1' into 'master'
Add Ariel Rin and Col Crunch as developers to readme

See merge request allianceauth/allianceauth!1128
2019-05-29 09:21:51 +00:00
Basraah
2741a92d31 Version bump to v2.2.0 2019-04-14 03:07:22 +00:00
Ariel Rin
3570ce86d7 Add Ariel Rin and Col Crunch as developers to readme 2019-03-17 05:39:43 +00:00
Basraah
d809902d1e Merge branch 'issue-templates' into 'master'
Create Issue Templates

See merge request allianceauth/allianceauth!1111
2019-03-12 22:16:00 +00:00
Ariel Rin
ec4232c00a Create Issue Templates 2019-03-12 22:16:00 +00:00
Basraah
dec793bfac Merge branch 'dependencies' into 'master'
Depencies fix

Closes #1150

See merge request allianceauth/allianceauth!1127
2019-03-12 20:50:00 +10:00
Basraah
fe3fe0527a Merge branch 'timer-change' into 'master'
Rename Citadels and FLEX Structures

See merge request allianceauth/allianceauth!1126
2019-03-12 10:06:53 +00:00
colcrunch
a8855e86ed Change Type [SIZE] notation for Citadels/EC/Refineries to structure names to reduce ambiguity.
Also, Added "Brand names" for the Beacon, Jammer, and Gate.
2019-03-12 10:06:53 +00:00
Basraah
179d1c38e6 Merge branch 'dj-2.1' into 'master'
Django 2.1 Compatibility

See merge request allianceauth/allianceauth!1124
2019-03-12 10:05:05 +00:00
colcrunch
287da73a4f Update StateBackend.authenticate to match ModelBackend
Also, change setup to no longer include Django 1.11
2019-03-12 10:05:05 +00:00
Basraah
e9ed917888 Merge branch 'fix_discourse_usernames' into 'master'
Send usernames as string instead of array

Closes #1149

See merge request allianceauth/allianceauth!1123
2019-03-12 10:00:52 +00:00
Basraah
70d842c971 Merge branch 'jokke_ilujo/Issue1146' into 'master'
Precent encode mumble username for connect link

See merge request allianceauth/allianceauth!1121
2019-03-12 09:58:07 +00:00
Basraah
bcda228e05 Merge branch 'mysql-docs-fix' into 'master'
Add Time Zone table instructions to Install Docs

See merge request allianceauth/allianceauth!1119
2019-03-12 09:56:20 +00:00
colcrunch
000dafc5e6 Add Time Zone table instructions to Install Docs 2019-03-12 09:56:20 +00:00
Basraah
4ea824fe71 Merge branch 'audit-log-update' into 'master'
Add datetime to Audit Log entries.

Closes #1134

See merge request allianceauth/allianceauth!1115
2019-03-12 09:53:43 +00:00
colcrunch
f72f539516 Add datetime to auditlog entries.
Also, change ordering, add pagination, and stripe the table for increased readability.

Action column now also reads "Removed" when a user is removed from a group. Note that this does not change anything on the back-end, so if you use this data for anything else, be aware that while the template is explicit, the data isn't as explicit.
2019-03-12 09:53:43 +00:00
Stephen Shirley
1b192a184f Send usernames as string instead of array
Fixes https://gitlab.com/allianceauth/allianceauth/issues/1149
2019-02-09 11:10:34 +01:00
Erno Kuvaja
0edf896b4c Precent encode mumble username for connect link
This change wraps mumble username on connect link forming with
urllib.parse.quote() to ensure that the username does not contain
unsafe reserved characters and gets passed properly to mumble.

Fixes Issue: #1146
2019-01-21 14:12:50 +00:00
32 changed files with 638 additions and 504 deletions

4
.gitignore vendored
View File

@@ -62,5 +62,7 @@ celerybeat-schedule
#pycharm #pycharm
.idea/* .idea/*
/nbproject/ /nbproject/
#gitlab configs
.gitlab/

View File

@@ -25,14 +25,6 @@
coverage: '/TOTAL.+ ([0-9]{1,3}%)/' coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
py36-dj111:
<<: *job_definition
image: python:3.6-stretch
script:
- export TOXENV=py36-dj111
- tox
py36-dj20: py36-dj20:
<<: *job_definition <<: *job_definition
image: python:3.6-stretch image: python:3.6-stretch

View File

@@ -0,0 +1,14 @@
# Bug
- I have searched [issues](https://gitlab.com/allianceauth/allianceauth/issues?scope=all&utf8=%E2%9C%93&state=all) (Y/N):
- What Version of Alliance Auth:
- What Operating System:
- Version of other components relevant to issue eg. Service, Database:
Please include a brief description of your issue here.
Please include steps to reproduce the issue
Please include any tracebacks or logs
Please include the results of the command `pip list`

View File

@@ -0,0 +1,7 @@
# Feature Request
- Describe the feature are you requesting.
- Is this a Service (external integration), a Module (Alliance Auth extension) or an enhancement to an existing service/module.
- Describe why its useful to you or others.

View File

@@ -19,6 +19,8 @@ Active Developers:
- [Adarnof](https://gitlab.com/adarnof/) - [Adarnof](https://gitlab.com/adarnof/)
- [Basraah](https://gitlab.com/basraah/) - [Basraah](https://gitlab.com/basraah/)
- [Ariel Rin](https://gitlab.com/soratidus999/)
- [Col Crunch](https://gitlab.com/colcrunch/)
Beta Testers / Bug Fixers: Beta Testers / Bug Fixers:

View File

@@ -1,6 +1,6 @@
# This will make sure the app is always imported when # This will make sure the app is always imported when
# Django starts so that shared_task will use this app. # Django starts so that shared_task will use this app.
__version__ = '2.1.1' __version__ = '2.2.2'
NAME = 'Alliance Auth v%s' % __version__ NAME = 'Alliance Auth v%s' % __version__
default_app_config = 'allianceauth.apps.AllianceAuthConfig' default_app_config = 'allianceauth.apps.AllianceAuthConfig'

View File

@@ -27,7 +27,7 @@ class StateBackend(ModelBackend):
user_obj._perm_cache.update(self.get_state_permissions(user_obj)) user_obj._perm_cache.update(self.get_state_permissions(user_obj))
return user_obj._perm_cache return user_obj._perm_cache
def authenticate(self, token=None): def authenticate(self, request=None, token=None, **credentials):
if not token: if not token:
return None return None
try: try:

View File

@@ -119,7 +119,7 @@ class BackendTestCase(TestCase):
def test_authenticate_character_record(self): def test_authenticate_character_record(self):
t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='4') t = Token(character_id=self.unclaimed_character.character_id, character_name=self.unclaimed_character.character_name, character_owner_hash='4')
record = OwnershipRecord.objects.create(user=self.old_user, character=self.unclaimed_character, owner_hash='4') record = OwnershipRecord.objects.create(user=self.old_user, character=self.unclaimed_character, owner_hash='4')
user = StateBackend().authenticate(t) user = StateBackend().authenticate(token=t)
self.assertEqual(user, self.old_user) self.assertEqual(user, self.old_user)
self.assertTrue(CharacterOwnership.objects.filter(owner_hash='4', user=self.old_user).exists()) self.assertTrue(CharacterOwnership.objects.filter(owner_hash='4', user=self.old_user).exists())
self.assertTrue(user.profile.main_character) self.assertTrue(user.profile.main_character)

View File

@@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from django.db import models from django.db import models
from .models import AutogroupsConfig from .models import AutogroupsConfig, ManagedCorpGroup, ManagedAllianceGroup
import logging import logging
@@ -37,3 +37,6 @@ class AutogroupsConfigAdmin(admin.ModelAdmin):
admin.site.register(AutogroupsConfig, AutogroupsConfigAdmin) admin.site.register(AutogroupsConfig, AutogroupsConfigAdmin)
admin.site.register(ManagedCorpGroup)
admin.site.register(ManagedAllianceGroup)

View File

@@ -179,15 +179,13 @@ class AutogroupsConfig(models.Model):
@transaction.atomic @transaction.atomic
def create_alliance_group(self, alliance: EveAllianceInfo) -> Group: def create_alliance_group(self, alliance: EveAllianceInfo) -> Group:
group, created = Group.objects.get_or_create(name=self.get_alliance_group_name(alliance)) group, created = Group.objects.get_or_create(name=self.get_alliance_group_name(alliance))
if created: ManagedAllianceGroup.objects.get_or_create(group=group, config=self, alliance=alliance)
ManagedAllianceGroup.objects.create(group=group, config=self, alliance=alliance)
return group return group
@transaction.atomic @transaction.atomic
def create_corp_group(self, corp: EveCorporationInfo) -> Group: def create_corp_group(self, corp: EveCorporationInfo) -> Group:
group, created = Group.objects.get_or_create(name=self.get_corp_group_name(corp)) group, created = Group.objects.get_or_create(name=self.get_corp_group_name(corp))
if created: ManagedCorpGroup.objects.get_or_create(group=group, config=self, corp=corp)
ManagedCorpGroup.objects.create(group=group, config=self, corp=corp)
return group return group
def delete_alliance_managed_groups(self): def delete_alliance_managed_groups(self):
@@ -240,6 +238,8 @@ class ManagedGroup(models.Model):
class Meta: class Meta:
abstract = True abstract = True
def __str__(self):
return "Managed Group: %s" % self.group.name
class ManagedCorpGroup(ManagedGroup): class ManagedCorpGroup(ManagedGroup):
corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE) corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE)

View File

@@ -1,254 +1,254 @@
{% extends "allianceauth/base.html" %} {% extends "allianceauth/base.html" %}
{% load bootstrap %} {% load bootstrap %}
{% load staticfiles %} {% load staticfiles %}
{% load i18n %} {% load i18n %}
{% block page_title %}FleetUp{% endblock page_title %} {% block page_title %}FleetUp{% endblock page_title %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
{% include "fleetup/menu.html" %} {% include "fleetup/menu.html" %}
<div> <div>
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#operations">{% trans "Operations" %}</a></li> <li class="active"><a data-toggle="tab" href="#operations">{% trans "Operations" %}</a></li>
<li><a data-toggle="tab" href="#timers">{% trans "Timers" %}</a></li> <li><a data-toggle="tab" href="#timers">{% trans "Timers" %}</a></li>
</ul> </ul>
<div class="tab-content row"> <div class="tab-content row">
<div id="operations" class="tab-pane fade in active"> <div id="operations" class="tab-pane fade in active">
<div class="col-lg-8"> <div class="col-lg-8">
{% if operations_list %} {% if operations_list %}
{% for subject, start in operations_list %} {% for subject, start in operations_list %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title"><b>{{ start.subject }}</b></h3> <h3 class="panel-title"><b>{{ start.subject }}</b></h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<table class="table table-condensed"> <table class="table table-condensed">
<tr> <tr>
<th class="col-md-6">{% trans "Start" %}</th> <th class="col-md-6">{% trans "Start" %}</th>
<th class="col-md-6">{% trans "End" %}</th> <th class="col-md-6">{% trans "End" %}</th>
</tr> </tr>
<tr> <tr>
<td class="col-md-6">{{ start.start|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td> <td class="col-md-6">{{ start.start|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td>
<td class="col-md-6">{{ start.end|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td> <td class="col-md-6">{{ start.end|date:"l d M H:i" }} <span class="label label-success">{% trans "Eve Time" %}</span></td>
</tr> </tr>
<tr> <tr>
<td class="col-md-6"> <td class="col-md-6">
<span id="localtime{{ start.operation_id }}"></span>&nbsp;<span class='label label-success'>Local time</span><br> <span id="localtime{{ start.operation_id }}"></span>&nbsp;<span class='label label-success'>Local time</span><br>
<div id="countdown{{ start.operation_id }}"></div> <div id="countdown{{ start.operation_id }}"></div>
</td> </td>
<td class="col-md-6"></td> <td class="col-md-6"></td>
</tr> </tr>
</table> </table>
{{ start.details|linebreaks }} {{ start.details|linebreaks }}
<table class="table table-condensed table-striped"> <table class="table table-condensed table-striped">
<tr> <tr>
<th class="col-md-4">{% trans "Location" %}</th> <th class="col-md-4">{% trans "Location" %}</th>
<th class="col-md-4">{% trans "Doctrine" %}</th> <th class="col-md-4">{% trans "Doctrine" %}</th>
<th class="col-md-2">{% trans "Organizer" %}</th> <th class="col-md-2">{% trans "Organizer" %}</th>
<th class="col-md-2">{% trans "URL" %}</th> <th class="col-md-2">{% trans "URL" %}</th>
</tr> </tr>
<tr> <tr>
<td> <td>
{{ start.location }} - {{ start.location_info }} <a href="http://evemaps.dotlan.net/system/{{ start.location }}" target="_blank" class="label label-success">Dotlan</a> {{ start.location }} - {{ start.location_info }} <a href="http://evemaps.dotlan.net/system/{{ start.location }}" target="_blank" class="label label-success">Dotlan</a>
</td> </td>
<td> <td>
{% if start.doctrine %} {% if start.doctrine %}
{% for doctrine in start.doctrine %} {% for doctrine in start.doctrine %}
<a href="{% url 'fleetup:doctrine' doctrine.Id %}" class="label label-success">{{ doctrine.Name }}</a> <a href="{% url 'fleetup:doctrine' doctrine.Id %}" class="label label-success">{{ doctrine.Name }}</a>
{% endfor %} {% endfor %}
{% else %} {% else %}
<span class="label label-danger">{% trans "TBA" %}</span> <span class="label label-danger">{% trans "TBA" %}</span>
{% endif %} {% endif %}
</td> </td>
<td> <td>
{{ start.organizer }} {{ start.organizer }}
</td> </td>
<td> <td>
{% ifequal start.url "" %} {% ifequal start.url "" %}
<div class="label label-danger">{% trans "No link" %}</div> <div class="label label-danger">{% trans "No link" %}</div>
{% else %} {% else %}
<a href="{{ start.url }}" target="_blank" class="label label-success">{% trans "External link" %}</a> <a href="{{ start.url }}" target="_blank" class="label label-success">{% trans "External link" %}</a>
{% endifequal %} {% endifequal %}
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
{% else %} {% else %}
<h3>{% trans "There seems to be no Operations in the near future." %}</h3> <h3>{% trans "There seems to be no Operations in the near future." %}</h3>
{% endif %} {% endif %}
</div> </div>
<div class="col-lg-4"> <div class="col-lg-4">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">{% trans "Current Eve Time:" %}</h2> <h2 class="panel-title">{% trans "Current Eve Time:" %}</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id="current-time"></div> <div id="current-time"></div>
</div> </div>
</div> </div>
{% if timers_list %} {% if timers_list %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">{% trans "Timers" %}</h2> <h2 class="panel-title">{% trans "Timers" %}</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<table class="table table-condensed table-hover table-striped"> <table class="table table-condensed table-hover table-striped">
{% for notes, type in timers_list %} {% for notes, type in timers_list %}
<tr> <tr>
<td> <td>
{{ type.solarsystem }} {{ type.solarsystem }}
</td> </td>
<td> <td>
{{ type.expires|date:"l d M H:i" }} {{ type.expires|date:"l d M H:i" }}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div id="timers" class="tab-pane fade in"> <div id="timers" class="tab-pane fade in">
<div class="col-lg-12"> <div class="col-lg-12">
{% if timers_list %} {% if timers_list %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title">{% trans "Timers" %}</h2> <h2 class="panel-title">{% trans "Timers" %}</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="col-lg-12"> <div class="col-lg-12">
<table class="table table-condensed table-hover table-striped"> <table class="table table-condensed table-hover table-striped">
<tr> <tr>
<th class="col-lg-1">{% trans "Type" %}</th> <th class="col-lg-1">{% trans "Type" %}</th>
<th class="col-lg-1">{% trans "Structure" %}</th> <th class="col-lg-1">{% trans "Structure" %}</th>
<th class="col-lg-2">{% trans "Location" %}</th> <th class="col-lg-2">{% trans "Location" %}</th>
<th class="col-lg-2">{% trans "Expires(EVE-time)" %}</th> <th class="col-lg-2">{% trans "Expires(EVE-time)" %}</th>
<th class="col-lg-1">{% trans "Owner" %}</th> <th class="col-lg-1">{% trans "Owner" %}</th>
<th class="col-lg-2">{% trans "Note" %}</th> <th class="col-lg-2">{% trans "Note" %}</th>
</tr> </tr>
{% for notes, type in timers_list %} {% for notes, type in timers_list %}
<tr> <tr>
<td> <td>
{% ifequal type.type "Final" %} {% ifequal type.type "Final" %}
<span class="label label-danger"> <span class="label label-danger">
{{ type.type }}</span>{% else %}{{ type.type }}{% endifequal %} {{ type.type }}</span>{% else %}{{ type.type }}{% endifequal %}
</td> </td>
<td> <td>
{{ type.timer_type }} {{ type.timer_type }}
</td> </td>
<td> <td>
{{ type.solarsystem }} - Planet:{{ type.planet }} Moon:{{ type.moon }} {{ type.solarsystem }} - Planet:{{ type.planet }} Moon:{{ type.moon }}
</td> </td>
<td> <td>
{{ type.expires|date:"l d M H:i" }} {{ type.expires|date:"l d M H:i" }}
</td> </td>
<td> <td>
{{ type.owner }} {{ type.owner }}
</td> </td>
<td> <td>
{{ type.notes }} {{ type.notes }}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</div> </div>
</div> </div>
</div> </div>
{% else %} {% else %}
<h3>{% trans "There seems to be no Timers in the near future." %}</h3> <h3>{% trans "There seems to be no Timers in the near future." %}</h3>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% include 'bundles/moment-js.html' with locale=True %} {% include 'bundles/moment-js.html' with locale=True %}
<script src="{% static 'js/timers.js' %}"></script> <script src="{% static 'js/timers.js' %}"></script>
<script type="text/javascript"> <script type="text/javascript">
// Data // Data
var timers = [ var timers = [
{% for start, op in operations_list %} {% for start, op in operations_list %}
{ {
'id': {{ op.operation_id }}, 'id': {{ op.operation_id }},
'start': moment("{{ op.start | date:"c" }}"), 'start': moment("{{ op.start | date:"c" }}"),
'end': moment("{{ op.end | date:"c" }}"), 'end': moment("{{ op.end | date:"c" }}"),
'expired': false 'expired': false
}, },
{% endfor %} {% endfor %}
] ]
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
timedUpdate(); timedUpdate();
setAllLocalTimes(); setAllLocalTimes();
// Start timed updates // Start timed updates
setInterval(timedUpdate, 1000); setInterval(timedUpdate, 1000);
function timedUpdate() { function timedUpdate() {
updateClock(); updateClock();
updateAllTimers(); updateAllTimers();
} }
function updateAllTimers () { function updateAllTimers () {
var l = timers.length; var l = timers.length;
for (var i=0; i < l; ++i) { for (var i=0; i < l; ++i) {
if (timers[i].expired) continue; if (timers[i].expired) continue;
updateTimer(timers[i]); updateTimer(timers[i]);
} }
} }
/** /**
* Update a timer * Update a timer
* @param timer Timer information * @param timer Timer information
* @param timer.start Date of the timer * @param timer.start Date of the timer
* @param timer.id Id number of the timer * @param timer.id Id number of the timer
* @param timer.expired * @param timer.expired
*/ */
function updateTimer(timer) { function updateTimer(timer) {
if (timer.start.isAfter(Date.now())) { if (timer.start.isAfter(Date.now())) {
var duration = moment.duration(timer.start - moment(), 'milliseconds'); var duration = moment.duration(timer.start - moment(), 'milliseconds');
document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration); document.getElementById("countdown" + timer.id).innerHTML = getDurationString(duration);
} else { } else {
timer.expired = true; timer.expired = true;
document.getElementById("countdown" + timer.id).innerHTML = ""; document.getElementById("countdown" + timer.id).innerHTML = "";
} }
} }
/** /**
* Set all local time fields * Set all local time fields
*/ */
function setAllLocalTimes() { function setAllLocalTimes() {
var l = timers.length; var l = timers.length;
for (var i=0; i < l; ++i) { for (var i=0; i < l; ++i) {
setLocalTime(timers[i]); setLocalTime(timers[i]);
} }
} }
/** /**
* Set the local time info for the timer * Set the local time info for the timer
* @param timer Timer information * @param timer Timer information
* @param timer.start Date of the timer * @param timer.start Date of the timer
* @param timer.id Id number of the timer * @param timer.id Id number of the timer
*/ */
function setLocalTime(timer) { function setLocalTime(timer) {
document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT"); document.getElementById("localtime" + timer.id).innerHTML = timer.start.format("ddd @ LT");
} }
function updateClock() { function updateClock() {
document.getElementById("current-time").innerHTML = "<b>" + moment.utc().format('ddd, ll HH:mm:ss z') + "</b>"; document.getElementById("current-time").innerHTML = "<b>" + moment.utc().format('ddd, ll HH:mm:ss z') + "</b>";
} }
</script> </script>
{% endblock content %} {% endblock content %}

View File

@@ -0,0 +1,19 @@
# Generated by Django 2.0.8 on 2018-12-07 08:56
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('groupmanagement', '0010_authgroup_states'),
]
operations = [
migrations.AddField(
model_name='requestlog',
name='date',
field=models.DateTimeField(default=datetime.datetime(2018, 12, 7, 8, 56, 33, 846342)),
),
]

View File

@@ -4,6 +4,7 @@ from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from allianceauth.authentication.models import State from allianceauth.authentication.models import State
from datetime import datetime
class GroupRequest(models.Model): class GroupRequest(models.Model):
@@ -30,6 +31,7 @@ class RequestLog(models.Model):
request_info = models.CharField(max_length=254) request_info = models.CharField(max_length=254)
action = models.BooleanField(default=0) action = models.BooleanField(default=0)
request_actor = models.ForeignKey(User, on_delete=models.CASCADE) request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=datetime.utcnow())
def requestor(self): def requestor(self):
return self.request_info.split(":")[0] return self.request_info.split(":")[0]

View File

@@ -3,38 +3,60 @@
{% load i18n %} {% load i18n %}
{% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %} {% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div> <div>
{% if entries %}
<h3>{{ group }} Audit Log</h3> <h3>{{ group }} Audit Log</h3>
<table class="table"> <p> All times displayed are EVE/UTC.</p>
<tr> {% if entries %}
<th class="text-center">{% trans "Requestor" %}</th> <div class="table-responsive">
<th class="text-center">{% trans "Main Character" %}</th> <table class="table table-striped" id="log-entries">
<th class="text-center">{% trans "Group" %}</th> <thead>
<th class="text-center">{% trans "Type" %}</th> <th class="text-center" scope="col">{% trans "Date/Time" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th class="text-center" scope="col">{% trans "Requestor" %}</th>
<th class="text-center">{% trans "Actor" %}</th> <th class="text-center" scope="col">{% trans "Main Character" %}</th>
</tr> <th class="text-center" scope="col">{% trans "Group" %}</th>
{% for entry in entries %} <th class="text-center" scope="col">{% trans "Type" %}</th>
<tr> <th class="text-center" scope="col">{% trans "Action" %}</th>
<td class="text-center">{{ entry.requestor }}</td> <th class="text-center" scope="col">{% trans "Actor" %}</th>
<td class="text-center">{{ entry.req_char }}</td> </thead>
<td class="text-center">{{ entry.group }}</td> <tbody>
<td class="text-center">{{ entry.type_to_str }}</td> {% for entry in entries %}
<td class="text-center">{{ entry.action_to_str }}</td> <tr>
<td class="text-center">{{ entry.request_actor }}</td> <td class="text-center">{{ entry.date }}</td>
</tr> <td class="text-center">{{ entry.requestor }}</td>
{% endfor %} <td class="text-center">{{ entry.req_char }}</td>
</table> <td class="text-center">{{ entry.group }}</td>
<td class="text-center">{{ entry.type_to_str }}</td>
{% if entry.request_type is None %}
<td class="text-center"> Removed</td>
{% else %}
<td class="text-center">{{ entry.action_to_str }}</td>
{% endif %}
<td class="text-center">{{ entry.request_actor }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %} {% else %}
<div class="alert alert-warning text-center">{% trans "No entries found." %}</div> <div class="alert alert-warning text-center">{% trans "No entries found for this group." %}</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock content %} {% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function(){
$('#log-entries').DataTable();
});
{% endblock %}

View File

@@ -19,7 +19,7 @@ url
{% for g in groups %} {% for g in groups %}
<tr> <tr>
<td class="text-center">{{ g.group.name }}</td> <td class="text-center">{{ g.group.name }}</td>
<td class="text-center">{{ g.group.authgroup.description }}</td> <td class="text-center">{{ g.group.authgroup.description|urlize }}</td>
<td class="text-center"> <td class="text-center">
{% if g.group in user.groups.all %} {% if g.group in user.groups.all %}
{% if not g.request %} {% if not g.request %}
@@ -32,9 +32,15 @@ url
</button> </button>
{% endif %} {% endif %}
{% elif not g.request %} {% elif not g.request %}
<a href="{% url 'groupmanagement:request_add' g.group.id %}" class="btn btn-success"> {% if g.group.authgroup.open %}
{% trans "Request" %} <a href="{% url 'groupmanagement:request_add' g.group.id %}" class="btn btn-success">
</a> {% trans "Join" %}
</a>
{% else %}
<a href="{% url 'groupmanagement:request_add' g.group.id %}" class="btn btn-primary">
{% trans "Request" %}
</a>
{% endif %}
{% else %} {% else %}
<button type="button" class="btn btn-primary" disabled> <button type="button" class="btn btn-primary" disabled>
{{ g.request.status }} {{ g.request.status }}

View File

@@ -12,7 +12,7 @@ urlpatterns = [
name='membership'), name='membership'),
url(r'^membership/(\w+)/$', views.group_membership_list, url(r'^membership/(\w+)/$', views.group_membership_list,
name='membership_list'), name='membership_list'),
url(r'^membership/(\w+)/audit/', views.group_membership_audit, name="audit_log"), url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"),
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove, url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove,
name='membership_remove'), name='membership_remove'),
url(r'^request_add/(\w+)', views.group_request_add, url(r'^request_add/(\w+)', views.group_request_add,

View File

@@ -5,6 +5,7 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test 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.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Count from django.db.models import Count
from django.http import Http404 from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
@@ -83,10 +84,9 @@ def group_membership_audit(request, group_id):
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("Group does not exist") raise Http404("Group does not exist")
render_items = {'group': group.name}
entries = RequestLog.objects.filter(group=group) entries = RequestLog.objects.filter(group=group).order_by('-date')
render_items['entries'] = entries
render_items = {'entries': entries, 'group': group.name}
return render(request, 'groupmanagement/audit.html', context=render_items) return render(request, 'groupmanagement/audit.html', context=render_items)

View File

@@ -30,6 +30,7 @@ DATABASES['default'] = {
'PASSWORD': '', 'PASSWORD': '',
'HOST': '127.0.0.1', 'HOST': '127.0.0.1',
'PORT': '3306', 'PORT': '3306',
'OPTIONS': {'charset': 'utf8mb4'},
} }
# Register an application at https://developers.eveonline.com for Authentication # Register an application at https://developers.eveonline.com for Authentication

View File

@@ -235,7 +235,7 @@ class DiscourseManager:
@staticmethod @staticmethod
def __add_user_to_group(g_id, username): def __add_user_to_group(g_id, username):
endpoint = ENDPOINTS['groups']['add_user'] endpoint = ENDPOINTS['groups']['add_user']
DiscourseManager.__exc(endpoint, g_id, usernames=[username]) DiscourseManager.__exc(endpoint, g_id, usernames=username)
@staticmethod @staticmethod
def __remove_user_from_group(g_id, username): def __remove_user_from_group(g_id, username):

View File

@@ -1,4 +1,5 @@
import logging import logging
import urllib
from django.conf import settings from django.conf import settings
from django.template.loader import render_to_string from django.template.loader import render_to_string
@@ -61,7 +62,7 @@ class MumbleService(ServicesHook):
'service_name': self.title, 'service_name': self.title,
'urls': urls, 'urls': urls,
'service_url': self.service_url, 'service_url': self.service_url,
'connect_url': request.user.mumble.username + '@' + self.service_url if MumbleTasks.has_account(request.user) else self.service_url, 'connect_url': urllib.parse.quote(request.user.mumble.username, safe="") + '@' + self.service_url if MumbleTasks.has_account(request.user) else self.service_url,
'username': request.user.mumble.username if MumbleTasks.has_account(request.user) else '', 'username': request.user.mumble.username if MumbleTasks.has_account(request.user) else '',
}, request=request) }, request=request)

View File

@@ -199,7 +199,7 @@ class Teamspeak3Manager:
'tokendescription': username_clean, 'tokendescription': username_clean,
'tokencustomset': "ident=sso_uid value=%s" % username_clean}) 'tokencustomset': "ident=sso_uid value=%s" % username_clean})
except TeamspeakError as e: except TeamspeakError as e:
logger.error("Failed to add teamspeak user %s: %s" % (username, str(e))) logger.error("Failed to add teamspeak user %s: %s" % (username_clean, str(e)))
return "","" return "",""
try: try:

View File

@@ -12,6 +12,10 @@ from .models import Teamspeak3User, AuthTS, TSgroup, StateGroup
from .tasks import Teamspeak3Tasks from .tasks import Teamspeak3Tasks
from .signals import m2m_changed_authts_group, post_save_authts, post_delete_authts from .signals import m2m_changed_authts_group, post_save_authts, post_delete_authts
from .manager import Teamspeak3Manager
from .util.ts3 import TeamspeakError
from allianceauth.authentication.models import State
MODULE_PATH = 'allianceauth.services.modules.teamspeak3' MODULE_PATH = 'allianceauth.services.modules.teamspeak3'
DEFAULT_AUTH_GROUP = 'Member' DEFAULT_AUTH_GROUP = 'Member'
@@ -290,3 +294,31 @@ class Teamspeak3SignalsTestCase(TestCase):
self.member.profile.save() self.member.profile.save()
self.assertTrue(update_groups.called) self.assertTrue(update_groups.called)
class Teamspeak3ManagerTestCase(TestCase):
@staticmethod
def my_side_effect(*args, **kwargs):
raise TeamspeakError(1)
@mock.patch.object(Teamspeak3Manager, '_group_list')
@mock.patch.object(Teamspeak3Manager, '_group_id_by_name')
def test_add_user_exception(self, _group_id_by_name, _group_list):
"""test 1st exception occuring in add_user()"""
# set mocks in Teamspeak3Manager class
_group_list.return_value = ['Member', 'Guest']
_group_id_by_name.return_value = 99
manager = Teamspeak3Manager()
server = mock.MagicMock()
server._connected.return_value = True
server.send_command = mock.Mock(side_effect=Teamspeak3ManagerTestCase.my_side_effect)
manager._server = server
# create test data
user = User.objects.create_user("dummy")
user.profile.state = State.objects.filter(name="Member").first()
# perform test
manager.add_user(user, "Dummy User")

View File

@@ -4,8 +4,8 @@ from celery import shared_task
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .hooks import ServicesHook from .hooks import ServicesHook
from celery_once import QueueOnce as BaseTask, AlreadyQueued from celery_once import QueueOnce as BaseTask, AlreadyQueued
from celery_once.helpers import now_unix
from django.core.cache import cache from django.core.cache import cache
from time import time
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -22,7 +22,7 @@ class DjangoBackend:
@staticmethod @staticmethod
def raise_or_lock(key, timeout): def raise_or_lock(key, timeout):
now = now_unix() now = int(time())
result = cache.get(key) result = cache.get(key)
if result: if result:
remaining = int(result) - now remaining = int(result) - now

View File

@@ -27,12 +27,14 @@
{% menu_items %} {% menu_items %}
<li> {% if user.is_superuser %}
<a class="{% navactive request 'authentication:help' %}" <li>
href="{% url 'authentication:help' %}"> <a class="{% navactive request 'authentication:help' %}"
<i class="fa fa-question fa-fw"></i> {% trans "Help" %} href="{% url 'authentication:help' %}">
</a> <i class="fa fa-question fa-fw"></i> {% trans "Help" %}
</li> </a>
</li>
{% endif %}
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -38,17 +38,17 @@ class TimerForm(forms.ModelForm):
('POS[S]', 'POS[S]'), ('POS[S]', 'POS[S]'),
('POS[M]', 'POS[M]'), ('POS[M]', 'POS[M]'),
('POS[L]', 'POS[L]'), ('POS[L]', 'POS[L]'),
('Citadel[M]', 'Citadel[M]'), ('Astrahus', 'Astrahus'),
('Citadel[L]', 'Citadel[L]'), ('Fortizar', 'Fortizar'),
('Citadel[XL]', 'Citadel[XL]'), ('Keepstar', 'Keepstar'),
('Engineering Complex[M]', 'Engineering Complex[M]'), ('Raitaru', 'Raitaru'),
('Engineering Complex[L]', 'Engineering Complex[L]'), ('Azbel', 'Azbel'),
('Engineering Complex[XL]', 'Engineering Complex[XL]'), ('Sotiyo', 'Sotiyo'),
('Refinery[M]', 'Refinery[M]'), ('Athanor', 'Athanor'),
('Refinery[L]', 'Refinery[L]'), ('Tatara', 'Tatara'),
('Cyno Beacon','Cyno Beacon'), ('Pharolux Cyno Beacon', 'Pharolux Cyno Beacon'),
('Cyno Jammer','Cyno Jammer'), ('Tenebrex Cyno Jammer', 'Tenebrex Cyno Jammer'),
('Jump Gate','Jump Gate'), ('Ansiblex Jump Gate', 'Ansiblex Jump Gate'),
('Moon Mining Cycle', 'Moon Mining Cycle'), ('Moon Mining Cycle', 'Moon Mining Cycle'),
(_('Other'), _('Other'))] (_('Other'), _('Other'))]
objective_choices = [('Friendly', _('Friendly')), objective_choices = [('Friendly', _('Friendly')),

View File

@@ -37,128 +37,128 @@
{% endif %} {% endif %}
</tr> </tr>
{% for timer in corp_timers %} {% for timer in corp_timers %}
{% ifequal timer.important True %} {% if timer.important == True %}
<tr class="danger"> <tr class="danger">
{% else %} {% else %}
<tr class="info"> <tr class="info">
{% endifequal %} {% endif %}
<td style="width:150px" class="text-center">{{ timer.details }}</td> <td style="width:150px" class="text-center">{{ timer.details }}</td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.objective "Hostile" %} {% if timer.objective == "Hostile" %}
<div class="label label-danger"> <div class="label label-danger">
{% trans "Hostile" %} {% trans "Hostile" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Friendly" %} {% if timer.objective == "Friendly" %}
<div class="label label-primary"> <div class="label label-primary">
{% trans "Friendly" %} {% trans "Friendly" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Neutral" %} {% if timer.objective == "Neutral" %}
<div class="label label-default"> <div class="label label-default">
{% trans "Neutral" %} {% trans "Neutral" %}
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center"><a <td class="text-center"><a
href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }} </a> href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }} </a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.structure "POCO" %} {% if timer.structure == "POCO" %}
<div class="label label-info"> <div class="label label-info">
POCO POCO
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "I-HUB" %} {% if timer.structure == "I-HUB" %}
<div class="label label-warning"> <div class="label label-warning">
I-HUB I-HUB
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "TCU" %} {% if timer.structure == "TCU" %}
<div class="label label-danger"> <div class="label label-danger">
TCU TCU
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[S]" %} {% if timer.structure == "POS[S]" %}
<div class="label label-info"> <div class="label label-info">
POS [S] POS [S]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[M]" %} {% if timer.structure == "POS[M]" %}
<div class="label label-info"> <div class="label label-info">
POS [M] POS [M]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[L]" %} {% if timer.structure == "POS[L]" %}
<div class="label label-info"> <div class="label label-info">
POS [L] POS [L]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[M]" %} {% if timer.structure == "Citadel[M]" or timer.structure == "Astrahus" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [M] Astrahus
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[L]" %} {% if timer.structure == "Citadel[L]" or timer.structure == "Fortizar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [L] Fortizar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[XL]" %} {% if timer.structure == "Citadel[XL]" or timer.structure == "Keepstar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [XL] Keepstar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[M]" %} {% if timer.structure == "Engineering Complex[M]" or timer.structure == "Raitaru" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [M] Raitaru
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[L]" %} {% if timer.structure == "Engineering Complex[L]" or timer.structure == "Azbel" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [L] Azbel
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[XL]" %} {% if timer.structure == "Engineering Complex[XL]" or timer.structure == "Sotiyo" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [XL] Sotiyo
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[M]" %} {% if timer.structure == "Refinery[M]" or timer.structure == "Athanor" %}
<div class="label label-warning"> <div class="label label-warning">
Refinery [M] Athanor
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[L]" %} {% if timer.structure == "Refinery[L]" or timer.structure == "Tatara"%}
<div class="label label-warning"> <div class="label label-warning">
Refinery [L] Tatara
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Beacon" %} {% if timer.structure == "Cyno Beacon" or timer.structure == "Pharolux Cyno Beacon" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Beacon Cyno Beacon
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Jammer" %} {% if timer.structure == "Cyno Jammer" or timer.structure == "Tenebrex Cyno Jammer" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Jammer Tenebrex Cyno Jammer
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Jump Gate" %} {% if timer.structure == "Jump Gate" or timer.structure == "Ansiblex Jump Gate" %}
<div class="label label-warning"> <div class="label label-warning">
Jump Gate Ansiblex Jump Gate
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Moon Mining Cycle" %} {% if timer.structure == "Moon Mining Cycle" %}
<div class="label label-success"> <div class="label label-success">
Moon Mining Cycle Moon Mining Cycle
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Other" %} {% if timer.structure == "Other" %}
<div class="label label-default"> <div class="label label-default">
Other Other
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td> <td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
<td class="text-center" nowrap> <td class="text-center" nowrap>
@@ -196,128 +196,128 @@
{% endif %} {% endif %}
</tr> </tr>
{% for timer in future_timers %} {% for timer in future_timers %}
{% ifequal timer.important True %} {% if timer.important == True %}
<tr class="danger"> <tr class="danger">
{% else %} {% else %}
<tr class="info"> <tr class="info">
{% endifequal %} {% endif %}
<td style="width:150px" class="text-center">{{ timer.details }}</td> <td style="width:150px" class="text-center">{{ timer.details }}</td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.objective "Hostile" %} {% if timer.objective == "Hostile" %}
<div class="label label-danger"> <div class="label label-danger">
{% trans "Hostile" %} {% trans "Hostile" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Friendly" %} {% if timer.objective == "Friendly" %}
<div class="label label-primary"> <div class="label label-primary">
{% trans "Friendly" %} {% trans "Friendly" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Neutral" %} {% if timer.objective == "Neutral" %}
<div class="label label-default"> <div class="label label-default">
{% trans "Neutral" %} {% trans "Neutral" %}
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a> <a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.structure "POCO" %} {% if timer.structure == "POCO" %}
<div class="label label-info"> <div class="label label-info">
POCO POCO
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "I-HUB" %} {% if timer.structure == "I-HUB" %}
<div class="label label-warning"> <div class="label label-warning">
I-HUB I-HUB
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "TCU" %} {% if timer.structure == "TCU" %}
<div class="label label-danger"> <div class="label label-danger">
TCU TCU
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[S]" %} {% if timer.structure == "POS[S]" %}
<div class="label label-info"> <div class="label label-info">
POS [S] POS [S]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[M]" %} {% if timer.structure == "POS[M]" %}
<div class="label label-info"> <div class="label label-info">
POS [M] POS [M]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[L]" %} {% if timer.structure == "POS[L]" %}
<div class="label label-info"> <div class="label label-info">
POS [L] POS [L]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[M]" %} {% if timer.structure == "Citadel[M]" or timer.structure == "Astrahus" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [M] Astrahus
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[L]" %} {% if timer.structure == "Citadel[L]" or timer.structure == "Fortizar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [L] Fortizar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[XL]" %} {% if timer.structure == "Citadel[XL]" or timer.structure == "Keepstar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [XL] Keepstar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[M]" %} {% if timer.structure == "Engineering Complex[M]" or timer.structure == "Raitaru" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [M] Raitaru
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[L]" %} {% if timer.structure == "Engineering Complex[L]" or timer.structure == "Azbel" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [L] Azbel
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[XL]" %} {% if timer.structure == "Engineering Complex[XL]" or timer.structure == "Sotiyo" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [XL] Sotiyo
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[M]" %} {% if timer.structure == "Refinery[M]" or timer.structure == "Athanor" %}
<div class="label label-warning"> <div class="label label-warning">
Refinery [M] Athanor
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[L]" %} {% if timer.structure == "Refinery[L]" or timer.structure == "Tatara" %}
<div class="label label-warning"> <div class="label label-warning">
Refinery [L] Tatara
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Beacon" %} {% if timer.structure == "Cyno Beacon" or timer.structure == "Pharolux Cyno Beacon" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Beacon Pharolux Cyno Beacon
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Jammer" %} {% if timer.structure == "Cyno Jammer" or timer.structure == "Tenebrex Cyno Jammer" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Jammer Tenebrex Cyno Jammer
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Jump Gate" %} {% if timer.structure == "Jump Gate" or timer.structure == "Ansiblex Jump Gate" %}
<div class="label label-warning"> <div class="label label-warning">
Jump Gate Ansiblex Jump Gate
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Moon Mining Cycle" %} {% if timer.structure == "Moon Mining Cycle" %}
<div class="label label-success"> <div class="label label-success">
Moon Mining Cycle Moon Mining Cycle
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Other" %} {% if timer.structure == "Other" %}
<div class="label label-default"> <div class="label label-default">
Other Other
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td> <td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
<td class="text-center" nowrap> <td class="text-center" nowrap>
@@ -357,128 +357,128 @@
{% endif %} {% endif %}
</tr> </tr>
{% for timer in past_timers %} {% for timer in past_timers %}
{% ifequal timer.important True %} {% if timer.important == True %}
<tr class="danger"> <tr class="danger">
{% else %} {% else %}
<tr class="info"> <tr class="info">
{% endifequal %} {% endif %}
<td style="width:150px" class="text-center">{{ timer.details }}</td> <td style="width:150px" class="text-center">{{ timer.details }}</td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.objective "Hostile" %} {% if timer.objective == "Hostile" %}
<div class="label label-danger"> <div class="label label-danger">
{% trans "Hostile" %} {% trans "Hostile" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Friendly" %} {% if timer.objective == "Friendly" %}
<div class="label label-primary"> <div class="label label-primary">
{% trans "Friendly" %} {% trans "Friendly" %}
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.objective "Neutral" %} {% if timer.objective == "Neutral" %}
<div class="label label-default"> <div class="label label-default">
{% trans "Neutral" %} {% trans "Neutral" %}
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center"> <td class="text-center">
<a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a> <a href="http://evemaps.dotlan.net/system/{{ timer.system }}">{{ timer.system }} {{ timer.planet_moon }}</a>
</td> </td>
<td class="text-center"> <td class="text-center">
{% ifequal timer.structure "POCO" %} {% if timer.structure == "POCO" %}
<div class="label label-info"> <div class="label label-info">
POCO POCO
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "I-HUB" %} {% if timer.structure == "I-HUB" %}
<div class="label label-warning"> <div class="label label-warning">
I-HUB I-HUB
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "TCU" %} {% if timer.structure == "TCU" %}
<div class="label label-danger"> <div class="label label-danger">
TCU TCU
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[S]" %} {% if timer.structure == "POS[S]" %}
<div class="label label-info"> <div class="label label-info">
POS [S] POS [S]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[M]" %} {% if timer.structure == "POS[M]" %}
<div class="label label-info"> <div class="label label-info">
POS [M] POS [M]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "POS[L]" %} {% if timer.structure == "POS[L]" %}
<div class="label label-info"> <div class="label label-info">
POS [L] POS [L]
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[M]" %} {% if timer.structure == "Citadel[M]" or timer.structure == "Astrahus" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [M] Astrahus
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[L]" %} {% if timer.structure == "Citadel[L]" or timer.structure == "Fortizar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [L] Fortizar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Citadel[XL]" %} {% if timer.structure == "Citadel[XL]" or timer.structure == "Keepstar" %}
<div class="label label-danger"> <div class="label label-danger">
Citadel [XL] Keepstar
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[M]" %} {% if timer.structure == "Engineering Complex[M]" or timer.structure == "Raitaru" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [M] Raitaru
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[L]" %} {% if timer.structure == "Engineering Complex[L]" or timer.structure == "Azbel" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [L] Azbel
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Engineering Complex[XL]" %} {% if timer.structure == "Engineering Complex[XL]" or timer.structure == "Sotiyo" %}
<div class="label label-warning"> <div class="label label-warning">
Engineering Complex [XL] Sotiyo
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[M]" %} {% if timer.structure == "Refinery[M]" or timer.structure == "Athanor" %}
<div class="label label-warning"> <div class="label label-warning">
Refinery [M] Athanor
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Refinery[L]" %} {% if timer.structure == "Refinery[L]" or timer.structure == "Tatara" %}
<div class="label label-warning"> <div class="label label-warning">
Refinery [L] Tatara
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Beacon" %} {% if timer.structure == "Cyno Beacon" or timer.structure == "Pharolux Cyno Beacon" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Beacon Pharolux Cyno Beacon
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Cyno Jammer" %} {% if timer.structure == "Cyno Jammer" or timer.structure == "Tenebrex Cyno Jammer" %}
<div class="label label-warning"> <div class="label label-warning">
Cyno Jammer Tenebrex Cyno Jammer
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Jump Gate" %} {% if timer.structure == "Jump Gate" or timer.structure == "Ansiblex Jump Gate" %}
<div class="label label-warning"> <div class="label label-warning">
Jump Gate Ansiblex Jump Gate
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Moon Mining Cycle" %} {% if timer.structure == "Moon Mining Cycle" %}
<div class="label label-success"> <div class="label label-success">
Moon Mining Cycle Moon Mining Cycle
</div> </div>
{% endifequal %} {% endif %}
{% ifequal timer.structure "Other" %} {% if timer.structure == "Other" %}
<div class="label label-default"> <div class="label label-default">
Other Other
</div> </div>
{% endifequal %} {% endif %}
</td> </td>
<td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td> <td class="text-center" nowrap>{{ timer.eve_time | date:"Y-m-d H:i" }}</td>
<td class="text-center" nowrap> <td class="text-center" nowrap>

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -66,6 +66,17 @@ Clicking on the blue eye will take you to the group member management screen. He
![Group overview](/_static/images/features/group-member-management.png) ![Group overview](/_static/images/features/group-member-management.png)
### Group Audit Log
Whenever a user Joins, Leaves, or is Removed from a group, this is logged. To find the audit log for a given group, click the light-blue button to the right of the Group Member Management (blue eye) button.
These logs contain the Date and Time the action was taken (in EVE/UTC), the user which submitted the request being acted upon (requestor), the user's main character, the type of request (join, leave or removed), the action taken (accept, reject or remove), and the user that took the action (actor).
![Audit Log Example](/_static/images/features/group_audit_log.png)
```eval_rst
.. note::
There is no tracking for "Open" groups as members are able to freely join/leave these groups.
```
## Group Leaders ## Group Leaders

View File

@@ -71,9 +71,22 @@ CentOS:
Alliance Auth needs a MySQL user account and database. Open an SQL shell with `mysql -u root -p` and create them as follows, replacing `PASSWORD` with an actual secure password: Alliance Auth needs a MySQL user account and database. Open an SQL shell with `mysql -u root -p` and create them as follows, replacing `PASSWORD` with an actual secure password:
CREATE USER 'allianceserver'@'localhost' IDENTIFIED BY 'PASSWORD'; CREATE USER 'allianceserver'@'localhost' IDENTIFIED BY 'PASSWORD';
CREATE DATABASE alliance_auth CHARACTER SET utf8; 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';
Add timezone tables to your mysql installation:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
```eval_rst
.. note::
You may see errors when you add the timezone tables. To make sure that they were correctly added run the following commands and check for the ``time_zone`` tables::
mysql -u root -p
use mysql;
show tables;
```
Close the SQL shell and secure your database server with the `mysql_secure_installation` command. Close the SQL shell and secure your database server with the `mysql_secure_installation` command.
## Auth Install ## Auth Install

View File

@@ -6,6 +6,11 @@ Discord is very popular amongst ad-hoc small groups and larger organizations see
## Setup ## Setup
```eval_rst
.. warning::
Do not run the `discord.update_*` periodic tasks on a regular schedule, doing so can cause your discord service to stop syncing completely.
```
### Prepare Your Settings File ### Prepare Your Settings File
In your auth project's settings file, do the following: In your auth project's settings file, do the following:
- Add `'allianceauth.services.modules.discord',` to your `INSTALLED_APPS` list - Add `'allianceauth.services.modules.discord',` to your `INSTALLED_APPS` list

View File

@@ -13,20 +13,21 @@ install_requires = [
'semantic_version', 'semantic_version',
'redis<=2.10.6', 'redis<=2.10.6',
'celery>=4.0.2', 'celery>=4.0.2,<4.3.0',
'celery_once', 'celery_once',
'django>=1.11,<=2.0.8', 'django>=2.0,<3.0',
'django-bootstrap-form', 'django-bootstrap-form',
'django-registration==2.4', 'django-registration==2.4',
'django-sortedm2m', 'django-sortedm2m',
'django-redis-cache>=1.7.1', 'django-redis-cache==1.8.1',
'django-celery-beat<=1.1.1', 'django-celery-beat<=1.1.1',
'openfire-restapi', 'openfire-restapi',
'sleekxmpp', 'sleekxmpp',
'adarnauth-esi>=1.4.10,<2.0', 'adarnauth-esi>=1.4.10,<2.0',
'kombu<=4.3.0',
] ]
testing_extras = [ testing_extras = [

View File

@@ -1,7 +1,7 @@
[tox] [tox]
skipsdist = True skipsdist = True
usedevelop = True usedevelop = True
envlist = py{34,35,36,37}-dj{111,20} envlist = py{34,35,36,37}-dj{20}
[testenv] [testenv]
setenv = setenv =
@@ -11,9 +11,8 @@ basepython =
py35: python3.5 py35: python3.5
py36: python3.6 py36: python3.6
py37: python3.7 py37: python3.7
deps= deps=
dj111: Django>=1.11.1,<2.0 dj20: Django>=2.0,<3.0
dj20: Django>=2.0
py37: https://github.com/yaml/pyyaml/zipball/master#egg=pyyaml py37: https://github.com/yaml/pyyaml/zipball/master#egg=pyyaml
py37: https://github.com/celery/kombu/zipball/master#egg=kombu py37: https://github.com/celery/kombu/zipball/master#egg=kombu
install_command = pip install -e ".[testing]" -U {opts} {packages} install_command = pip install -e ".[testing]" -U {opts} {packages}