Compare commits

...

29 Commits

Author SHA1 Message Date
Basraah
f70987de09 Version bump 2018-01-09 12:38:49 +10:00
Basraah
9d02b1530c Update contributors 2018-01-09 12:34:21 +10:00
Basraah
3d532dae01 Fix celery in tests
There's actually a better way to structure tests involving celery since
4.0, but that can wait for some time in the future.
2018-01-09 12:11:54 +10:00
Adarnof
02247b067f Include INSTALLED_APPS setting
Clean up section headers and add a few more.
2018-01-08 10:50:24 -05:00
Basraah
63c2668171 Change static path to match default install 2018-01-08 21:15:19 +10:00
Basraah
5575039126 Remove obsolete section on automatic groups 2018-01-08 21:07:29 +10:00
Basraah
f97c8f2ce4 Fix issue causing queue length query to hang 2018-01-08 18:20:29 +10:00
Adarnof
6baab1d006 New apache guide for proxying to wsgi worker 2018-01-08 00:52:10 -05:00
Adarnof
17adf04860 Correct CentOS supervisor config folder.
Install gunicorn before starting auth project.
2018-01-08 00:14:17 -05:00
Adarnof
f871ecb425 Namespace celery settings to correct broker issues 2018-01-07 19:50:34 -05:00
Adarnof
4a425cde78 Set the email from address for SparkPost
Thanks @colcrunch
2018-01-07 19:39:27 -05:00
Basraah
f56252b0cc Fix celery broker url config 2018-01-06 12:16:30 +10:00
Basraah
7ae6c66beb Fix registration of services signals 2018-01-06 12:08:53 +10:00
Basraah
be90fb96ea Remove unnecessary param 2017-12-28 10:18:50 +10:00
Basraah
dd3350b169 Fix field name 2017-12-28 09:20:11 +10:00
Basraah
cdd1ba1fe3 Use coerce to allow PEP440 to partially work 2017-12-23 15:05:51 +10:00
Basraah
10ea12c867 Prevent error on bad version 2017-12-23 14:44:26 +10:00
Basraah
e6358d948a Fix bug preventing users being added to alliance autogroups
Will need `python manage.py migrate eve_autogroups zero` before updating
2017-12-23 14:43:05 +10:00
Adarnof
1101572f78 Set token user to allow ownership creation 2017-12-22 12:20:55 -05:00
Adarnof
0cf8836832 Use primary key for FK assignment 2017-12-22 11:32:45 -05:00
Adarnof
6e4562b0e6 Don't rely on manager in migration 2017-12-22 11:19:53 -05:00
Basraah
856f1e176a Fix copy paste error, add extra debug output 2017-12-22 11:35:49 +10:00
Adarnof
1653a57e7b Do not set request main character
Thanks @GhostMB
2017-12-21 19:28:39 -05:00
Adarnof
5f03e580c2 Make manager available in migrations
Thanks @mmolitor87
2017-12-21 15:37:54 -05:00
Adarnof
d370ae48a2 Full import path
Python doesn't want to play nice.
2017-12-21 15:32:42 -05:00
Adarnof
38baeba254 Load signals with app 2017-12-21 15:25:53 -05:00
Adarnof
478f9b9390 Fix typo
Thanks @mmolitor87
2017-12-21 15:20:20 -05:00
Adarnof
82ad3821c4 Avoid using model property in migration
https://stackoverflow.com/a/3315547

Thanks @mmolitor87
2017-12-21 15:15:01 -05:00
Adarnof
07afaf12d5 Fix bracket.
Thanks @mmolitor87
2017-12-21 14:13:16 -05:00
25 changed files with 166 additions and 185 deletions

View File

@@ -24,6 +24,7 @@ Active Developers:
Beta Testers / Bug Fixers: Beta Testers / Bug Fixers:
- [ghoti](https://github.com/ghoti) - [ghoti](https://github.com/ghoti)
- [mmolitor87](https://github.com/mmolitor87)
Past Beta Testers / Bug Fixers: Past Beta Testers / Bug Fixers:

View File

@@ -1,7 +1,7 @@
# 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.0-dev' __version__ = '2.0b2'
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

@@ -39,6 +39,7 @@ class StateBackend(ModelBackend):
# insecure legacy main check for pre-sso registration auth installs # insecure legacy main check for pre-sso registration auth installs
profile = UserProfile.objects.get(main_character__character_id=token.character_id) profile = UserProfile.objects.get(main_character__character_id=token.character_id)
# attach an ownership # attach an ownership
token.user = profile.user
CharacterOwnership.objects.create_by_token(token) CharacterOwnership.objects.create_by_token(token)
return profile.user return profile.user
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist:

View File

@@ -103,16 +103,16 @@ def populate_ownerships(apps, schema_editor):
unique_character_owners = [t['character_id'] for t in unique_character_owners = [t['character_id'] for t in
Token.objects.all().values('character_id').annotate(n=models.Count('user')) if Token.objects.all().values('character_id').annotate(n=models.Count('user')) if
t['n'] == 1 and EveCharacter.objects.filter(character_id=t['character_id'].exists())] t['n'] == 1 and EveCharacter.objects.filter(character_id=t['character_id']).exists()]
tokens = Token.objects.filter(character_id__in=unique_character_owners) tokens = Token.objects.filter(character_id__in=unique_character_owners)
for c_id in unique_character_owners: for c_id in unique_character_owners:
ts = tokens.filter(character_id=c_id).order_by('created') # find newest refreshable token and use it as basis for CharacterOwnership
for t in ts: ts = tokens.filter(character_id=c_id).exclude(refresh_token__isnull=True).order_by('created')
if t.can_refresh: if ts.exists():
# find newest refreshable token and use it as basis for CharacterOwnership token = ts[0]
CharacterOwnership.objecs.create_by_token(t) char = EveCharacter.objects.get(character_id=token.character_id)
break CharacterOwnership.objects.create(user_id=token.user_id, character_id=char.id, owner_hash=token.character_owner_hash)
def create_profiles(apps, schema_editor): def create_profiles(apps, schema_editor):

View File

@@ -4,3 +4,6 @@ from django.apps import AppConfig
class EveAutogroupsConfig(AppConfig): class EveAutogroupsConfig(AppConfig):
name = 'allianceauth.eveonline.autogroups' name = 'allianceauth.eveonline.autogroups'
label = 'eve_autogroups' label = 'eve_autogroups'
def ready(self):
import allianceauth.eveonline.autogroups.signals

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2017-09-29 14:44 # Generated by Django 1.11.6 on 2017-12-23 04:30
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
@@ -29,40 +29,31 @@ class Migration(migrations.Migration):
('alliance_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)), ('alliance_name_source', models.CharField(choices=[('ticker', 'Ticker'), ('name', 'Full name')], default='name', max_length=20)),
('replace_spaces', models.BooleanField(default=False)), ('replace_spaces', models.BooleanField(default=False)),
('replace_spaces_with', models.CharField(blank=True, default='', help_text='Any spaces in the group name will be replaced with this.', max_length=10)), ('replace_spaces_with', models.CharField(blank=True, default='', help_text='Any spaces in the group name will be replaced with this.', max_length=10)),
('states', models.ManyToManyField(related_name='autogroups', to='authentication.State')),
],
),
migrations.CreateModel(
name='ManagedGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='ManagedAllianceGroup', name='ManagedAllianceGroup',
fields=[ fields=[
('managedgroup_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='eve_autogroups.ManagedGroup')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('alliance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveAllianceInfo')), ('alliance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveAllianceInfo')),
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig')),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
], ],
bases=('eve_autogroups.managedgroup',), options={
'abstract': False,
},
), ),
migrations.CreateModel( migrations.CreateModel(
name='ManagedCorpGroup', name='ManagedCorpGroup',
fields=[ fields=[
('managedgroup_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='eve_autogroups.ManagedGroup')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig')),
('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')), ('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
], ],
bases=('eve_autogroups.managedgroup',), options={
), 'abstract': False,
migrations.AddField( },
model_name='managedgroup',
name='config',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eve_autogroups.AutogroupsConfig'),
),
migrations.AddField(
model_name='managedgroup',
name='group',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
), ),
migrations.AddField( migrations.AddField(
model_name='autogroupsconfig', model_name='autogroupsconfig',
@@ -74,4 +65,9 @@ class Migration(migrations.Migration):
name='corp_managed_groups', name='corp_managed_groups',
field=models.ManyToManyField(help_text="A list of corporation groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='corp_managed_config', through='eve_autogroups.ManagedCorpGroup', to='auth.Group'), field=models.ManyToManyField(help_text="A list of corporation groups created and maintained by this AutogroupConfig. You should not edit this list unless you know what you're doing.", related_name='corp_managed_config', through='eve_autogroups.ManagedCorpGroup', to='auth.Group'),
), ),
migrations.AddField(
model_name='autogroupsconfig',
name='states',
field=models.ManyToManyField(related_name='autogroups', to='authentication.State'),
),
] ]

View File

@@ -110,11 +110,12 @@ class AutogroupsConfig(models.Model):
group = None group = None
try: try:
if not self.alliance_groups or not self.user_entitled_to_groups(user): if not self.alliance_groups or not self.user_entitled_to_groups(user):
logger.debug('User {} does not have required state'.format(user)) logger.debug('User {} does not have required state for alliance group membership'.format(user))
return return
else: else:
alliance = user.profile.main_character.alliance alliance = user.profile.main_character.alliance
if alliance is None: if alliance is None:
logger.debug('User {} alliance is None, cannot update group membership'.format(user))
return return
group = self.get_alliance_group(alliance) group = self.get_alliance_group(alliance)
except EveAllianceInfo.DoesNotExist: except EveAllianceInfo.DoesNotExist:
@@ -123,8 +124,9 @@ class AutogroupsConfig(models.Model):
except AttributeError: except AttributeError:
logger.warning('User {} does not have a main character. Group membership not updated'.format(user)) logger.warning('User {} does not have a main character. Group membership not updated'.format(user))
finally: finally:
self.remove_user_from_corp_groups(user, except_group=group) self.remove_user_from_alliance_groups(user, except_group=group)
if group is not None: if group is not None:
logger.debug('Adding user {} to alliance group {}'.format(user, group))
user.groups.add(group) user.groups.add(group)
@transaction.atomic @transaction.atomic
@@ -132,7 +134,7 @@ class AutogroupsConfig(models.Model):
group = None group = None
try: try:
if not self.corp_groups or not self.user_entitled_to_groups(user): if not self.corp_groups or not self.user_entitled_to_groups(user):
logger.debug('User {} does not have required state'.format(user)) logger.debug('User {} does not have required state for corp group membership'.format(user))
else: else:
corp = user.profile.main_character.corporation corp = user.profile.main_character.corporation
group = self.get_corp_group(corp) group = self.get_corp_group(corp)
@@ -144,6 +146,7 @@ class AutogroupsConfig(models.Model):
finally: finally:
self.remove_user_from_corp_groups(user, except_group=group) self.remove_user_from_corp_groups(user, except_group=group)
if group is not None: if group is not None:
logger.debug('Adding user {} to corp group {}'.format(user, group))
user.groups.add(group) user.groups.add(group)
@transaction.atomic @transaction.atomic
@@ -184,13 +187,15 @@ class AutogroupsConfig(models.Model):
""" """
Deletes ALL managed alliance groups Deletes ALL managed alliance groups
""" """
self.alliance_managed_groups.all().delete() for g in self.alliance_managed_groups.all():
g.delete()
def delete_corp_managed_groups(self): def delete_corp_managed_groups(self):
""" """
Deletes ALL managed corp groups Deletes ALL managed corp groups
""" """
self.corp_managed_groups.all().delete() for g in self.corp_managed_groups.all():
g.delete()
def get_alliance_group_name(self, alliance: EveAllianceInfo) -> str: def get_alliance_group_name(self, alliance: EveAllianceInfo) -> str:
if self.alliance_name_source == self.OPT_TICKER: if self.alliance_name_source == self.OPT_TICKER:
@@ -225,6 +230,9 @@ class ManagedGroup(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE)
config = models.ForeignKey(AutogroupsConfig, on_delete=models.CASCADE) config = models.ForeignKey(AutogroupsConfig, on_delete=models.CASCADE)
class Meta:
abstract = True
class ManagedCorpGroup(ManagedGroup): class ManagedCorpGroup(ManagedGroup):
corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE) corp = models.ForeignKey(EveCorporationInfo, on_delete=models.CASCADE)

View File

@@ -82,6 +82,7 @@ class AutogroupsConfigTestCase(TestCase):
# Act # Act
obj.update_alliance_group_membership(self.member) obj.update_alliance_group_membership(self.member)
obj.update_corp_group_membership(self.member) # check for no side effects
group = obj.create_alliance_group(self.alliance) group = obj.create_alliance_group(self.alliance)
group_qs = Group.objects.filter(pk=group.pk) group_qs = Group.objects.filter(pk=group.pk)

View File

@@ -4,8 +4,6 @@ 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.eveonline.models import EveCharacter
class GroupRequest(models.Model): class GroupRequest(models.Model):
status = models.CharField(max_length=254) status = models.CharField(max_length=254)

View File

@@ -303,7 +303,6 @@ def group_request_add(request, group_id):
grouprequest.status = _('Pending') grouprequest.status = _('Pending')
grouprequest.group = group grouprequest.group = group
grouprequest.user = request.user grouprequest.user = request.user
grouprequest.main_char = request.user.profile.main_character
grouprequest.leave_request = False grouprequest.leave_request = False
grouprequest.save() grouprequest.save()
logger.info("Created group request for user %s to group %s" % (request.user, Group.objects.get(id=group_id))) logger.info("Created group request for user %s to group %s" % (request.user, Group.objects.get(id=group_id)))
@@ -333,7 +332,6 @@ def group_request_leave(request, group_id):
grouprequest.status = _('Pending') grouprequest.status = _('Pending')
grouprequest.group = group grouprequest.group = group
grouprequest.user = request.user grouprequest.user = request.user
grouprequest.main_char = request.user.profile.main_character
grouprequest.leave_request = True grouprequest.leave_request = True
grouprequest.save() grouprequest.save()
logger.info("Created group leave request for user %s to group %s" % (request.user, Group.objects.get(id=group_id))) logger.info("Created group leave request for user %s to group %s" % (request.user, Group.objects.get(id=group_id)))

View File

@@ -0,0 +1 @@
from .celery import app as celery_app

View File

@@ -10,7 +10,7 @@ app = Celery('{{ project_name }}')
# Using a string here means the worker don't have to serialize # Using a string here means the worker don't have to serialize
# the configuration object to child processes. # the configuration object to child processes.
app.config_from_object('django.conf:settings') app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

View File

@@ -39,7 +39,7 @@ INSTALLED_APPS = [
] ]
# Celery configuration # Celery configuration
BROKER_URL = 'redis://localhost:6379/0' CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERYBEAT_SCHEDULER = "django_celery_beat.schedulers.DatabaseScheduler" CELERYBEAT_SCHEDULER = "django_celery_beat.schedulers.DatabaseScheduler"
CELERYBEAT_SCHEDULE = { CELERYBEAT_SCHEDULE = {
'esi_cleanup_callbackredirect': { 'esi_cleanup_callbackredirect': {

View File

@@ -10,12 +10,33 @@ STATIC_ROOT = "/var/www/{{ project_name }}/static/"
TEMPLATES[0]['DIRS'] += [os.path.join(PROJECT_DIR, 'templates')] TEMPLATES[0]['DIRS'] += [os.path.join(PROJECT_DIR, 'templates')]
SECRET_KEY = '{{ secret_key }}' SECRET_KEY = '{{ secret_key }}'
# Change this to change the name of the auth site #######################################
# Site Name #
#######################################
# Change this to change the name of the
# auth site displayed in page titles
# and the site header.
#######################################
SITE_NAME = '{{ project_name }}' SITE_NAME = '{{ project_name }}'
# Change this to enable/disable debug mode #######################################
# Debug Mode #
#######################################
# Change this to enable/disable debug
# mode, which displays useful error
# messages but can leak sensitive data.
#######################################
DEBUG = False DEBUG = False
#######################################
# Additional Applications #
#######################################
# Add any additional apps to this list.
#######################################
INSTALLED_APPS += [
]
####################################### #######################################
# Database Settings # # Database Settings #
####################################### #######################################
@@ -27,42 +48,45 @@ DEBUG = False
DATABASES['default'] = { DATABASES['default'] = {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_auth', 'NAME': 'alliance_auth',
'USER': os.environ.get('AA_DB_DEFAULT_USER', ''), 'USER': '',
'PASSWORD': os.environ.get('AA_DB_DEFAULT_PASSWORD', ''), 'PASSWORD': '',
'HOST': os.environ.get('AA_DB_DEFAULT_HOST', '127.0.0.1'), 'HOST': '127.0.0.1',
'PORT': os.environ.get('AA_DB_DEFAULT_PORT', '3306'), 'PORT': '3306',
} }
""" """
###################################### #######################################
# SSO Settings # # SSO Settings #
###################################### #######################################
# Register an application at # Register an application at
# https://developers.eveonline.com # https://developers.eveonline.com
# and fill out these settings. # and fill out these settings.
# Be sure to set the callback URL to # Be sure to set the callback URL to
# https://example.com/sso/callback # https://example.com/sso/callback
# substituting your domain for example.com # substituting your domain for example.com
###################################### #######################################
ESI_SSO_CLIENT_ID = '' ESI_SSO_CLIENT_ID = ''
ESI_SSO_CLIENT_SECRET = '' ESI_SSO_CLIENT_SECRET = ''
ESI_SSO_CALLBACK_URL = '' ESI_SSO_CALLBACK_URL = ''
###################################### #######################################
# Email Settings # # Email Settings #
###################################### #######################################
# Alliance Auth validates emails before # Alliance Auth validates emails before
# new users can log in. # new users can log in.
# It's recommended to use a free service # It's recommended to use a free service
# like SparkPost or Mailgun to send email. # like SparkPost or Mailgun to send email.
# https://www.sparkpost.com/docs/integrations/django/ # https://www.sparkpost.com/docs/integrations/django/
################# # Set the default from email to something
# like 'noreply@example.com'
#######################################
EMAIL_HOST = '' EMAIL_HOST = ''
EMAIL_PORT = 587 EMAIL_PORT = 587
EMAIL_HOST_USER = '' EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = '' EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = True EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = ''
###################################### #######################################
# Add any custom settings below here # # Add any custom settings below here. #
###################################### #######################################

View File

@@ -9,7 +9,9 @@ class NameFormatConfigForm(forms.ModelForm):
super(NameFormatConfigForm, self).__init__(*args, **kwargs) super(NameFormatConfigForm, self).__init__(*args, **kwargs)
SERVICE_CHOICES = [(s.name, s.name) for h in hooks.get_hooks('services_hook') for s in [h()]] SERVICE_CHOICES = [(s.name, s.name) for h in hooks.get_hooks('services_hook') for s in [h()]]
if self.instance.id: if self.instance.id:
SERVICE_CHOICES.append((self.instance.field, self.instance.field)) current_choice = (self.instance.service_name, self.instance.service_name)
if current_choice not in SERVICE_CHOICES:
SERVICE_CHOICES.append(current_choice)
self.fields['service_name'] = forms.ChoiceField(choices=SERVICE_CHOICES) self.fields['service_name'] = forms.ChoiceField(choices=SERVICE_CHOICES)

View File

@@ -6,4 +6,4 @@ class ServicesConfig(AppConfig):
label = 'services' label = 'services'
def ready(self): def ready(self):
pass from . import signals

View File

@@ -244,10 +244,10 @@ class Teamspeak3Manager:
return False return False
def generate_new_permissionkey(self, uid, username, corpticker): def generate_new_permissionkey(self, uid, username):
logger.debug("Re-issuing permission key for user id %s" % uid) logger.debug("Re-issuing permission key for user id %s" % uid)
self.delete_user(uid) self.delete_user(uid)
return self.add_user(username, corpticker) return self.add_user(username)
def update_groups(self, uid, ts_groups): def update_groups(self, uid, ts_groups):
logger.debug("Updating uid %s TS3 groups %s" % (uid, ts_groups)) logger.debug("Updating uid %s TS3 groups %s" % (uid, ts_groups))

View File

@@ -85,8 +85,7 @@ def reset_teamspeak3_perm(request):
ts3man.delete_user(request.user.teamspeak3.uid) ts3man.delete_user(request.user.teamspeak3.uid)
logger.debug("Generating new permission key for user %s with main character %s" % (request.user, character)) logger.debug("Generating new permission key for user %s with main character %s" % (request.user, character))
result = ts3man.generate_new_permissionkey(request.user.teamspeak3.uid, character.character_name, result = ts3man.generate_new_permissionkey(request.user.teamspeak3.uid, character.character_name)
character.corporation_ticker)
# if blank we failed # if blank we failed
if result[0] != "": if result[0] != "":

View File

@@ -1,5 +1,6 @@
import requests import requests
import logging import logging
import amqp.exceptions
import semantic_version as semver import semantic_version as semver
from django import template from django import template
from django.conf import settings from django.conf import settings
@@ -54,6 +55,9 @@ def get_celery_queue_length():
with app.connection_or_acquire() as conn: with app.connection_or_acquire() as conn:
return conn.default_channel.queue_declare( return conn.default_channel.queue_declare(
queue=getattr(settings, 'CELERY_DEFAULT_QUEUE', 'celery'), passive=True).message_count queue=getattr(settings, 'CELERY_DEFAULT_QUEUE', 'celery'), passive=True).message_count
except amqp.exceptions.ChannelError:
# Queue doesn't exist, probably empty
return 0
except Exception: except Exception:
logger.exception("Failed to get celery queue length") logger.exception("Failed to get celery queue length")
return -1 return -1
@@ -82,7 +86,7 @@ def get_version_info():
} }
try: try:
tags = cache.get_or_set('github_release_tags', get_github_tags, TAG_CACHE_TIME) tags = cache.get_or_set('github_release_tags', get_github_tags, TAG_CACHE_TIME)
current_ver = semver.Version(__version__, partial=True) current_ver = semver.Version.coerce(__version__)
# Set them all to the current version to start # Set them all to the current version to start
# If the server has only earlier or the same version # If the server has only earlier or the same version
@@ -102,7 +106,10 @@ def get_version_info():
if tag_name[0] == 'v': if tag_name[0] == 'v':
# Strip 'v' off front of verison if it exists # Strip 'v' off front of verison if it exists
tag_name = tag_name[1:] tag_name = tag_name[1:]
tag_ver = semver.Version(tag_name, partial=True) try:
tag_ver = semver.Version.coerce(tag_name)
except ValueError:
tag_ver = semver.Version('0.0.0', partial=True)
if tag_ver > current_ver: if tag_ver > current_ver:
if latest_major is None or tag_ver > latest_major: if latest_major is None or tag_ver > latest_major:
latest_major = tag_ver latest_major = tag_ver

View File

@@ -1,33 +1,9 @@
# Groups # Groups
Group Management is one of the core tasks of Alliance Auth. Many of Alliance Auth's services allow for synchronising of group membership, allowing you to grant permissions or roles in services to access certain aspects of them. Group Management is one of the core tasks of Alliance Auth. Many of Alliance Auth's services allow for synchronising of group membership, allowing you to grant permissions or roles in services to access certain aspects of them.
## Automatic Groups
When a member registers in Alliance Auth and selects a main character, Auth will assign them some groups automatically based on some factors.
```eval_rst
.. important::
The ``Corp_`` and ``Alliance_`` group name prefixes are reserved for Alliance Auth internal group management. If you prefix a group with these you will find Alliance Auth automatically removes users from the group.
```
```eval_rst
+------------------------------+-----------------------------------------------------------------------------------+
| Group | Condition |
+------------------------------+-----------------------------------------------------------------------------------+
| ``Corp_<corp_name>`` | Users Main Character belongs to the Corporation |
+------------------------------+-----------------------------------------------------------------------------------+
| ``Alliance_<alliance_name>`` | Users Main Character belongs to the Alliance |
+------------------------------+-----------------------------------------------------------------------------------+
| ``Member`` | User is a member of one of the tenant Corps or Alliances |
+------------------------------+-----------------------------------------------------------------------------------+
| ``Blue`` | User is a member of a blue Corp or Alliance, be it via standings or static config |
+------------------------------+-----------------------------------------------------------------------------------+
```
When the user no longer has the condition required to be a member of that group they are automatically removed by Auth.
## User Organised Groups ## User Organised Groups
Along with the automated groups, administrators can create custom groups for users to join. Examples might be groups like `Leadership`, `CEO` or `Scouts`. Administrators can create custom groups for users to join. Examples might be groups like `Leadership`, `CEO` or `Scouts`.
When you create a Django `Group`, Auth automatically creates a corresponding `AuthGroup` model. The admin page looks like this: When you create a Django `Group`, Auth automatically creates a corresponding `AuthGroup` model. The admin page looks like this:

View File

@@ -2,7 +2,7 @@
```eval_rst ```eval_rst
.. tip:: .. tip::
Installation is easiest as the root user. Log in as root or a user with sudo powers. If you are uncomfortable with linux permissions follow the steps below as the root user. Some commands do not behave the same when run with sudo.
``` ```
## Dependencies ## Dependencies
@@ -91,6 +91,11 @@ Create a Python virtual environment and put it somewhere convenient (e.g. `/home
python3 -m venv /home/allianceserver/venv/auth/ python3 -m venv /home/allianceserver/venv/auth/
```eval_rst
.. warning::
The python3 command may not be available on all installations. Try a specific version such as python3.6 if this is the case.
```
```eval_rst ```eval_rst
.. tip:: .. tip::
A virtual environment provides support for creating a lightweight "copy" of Python with their own site directories. Each virtual environment has its own Python binary (allowing creation of environments with various Python versions) and can have its own independent set of installed Python packages in its site directories. You can read more about virtual environments on the Python_ docs. A virtual environment provides support for creating a lightweight "copy" of Python with their own site directories. Each virtual environment has its own Python binary (allowing creation of environments with various Python versions) and can have its own independent set of installed Python packages in its site directories. You can read more about virtual environments on the Python_ docs.
@@ -106,18 +111,11 @@ Activate the virtualenv using `source /home/allianceserver/venv/auth/bin/activat
### Alliance Auth Project ### Alliance Auth Project
You can install the library using `pip install allianceauth`. This will install Alliance Auth and all its python dependencies. You can install the library using `pip install allianceauth`. This will install Alliance Auth and all its python dependencies. You should also install gunicorn with `pip install gunicorn` before proceeding.
Now you need to create the application that will run the Alliance Auth install. Ensure you are in the allianceserver home directory by issuing `cd /home/allianceserver`. Now you need to create the application that will run the Alliance Auth install. Ensure you are in the allianceserver home directory by issuing `cd /home/allianceserver`.
The `allianceauth start myauth` command will bootstrap a Django project which will run Alliance Auth. You can rename it from `myauth` to anything you'd like: this name is shown by default as the site name but that can be changed later. The `allianceauth start myauth` command bootstraps a Django project which will run Alliance Auth. You can rename it from `myauth` to anything you'd like: this name is shown by default as the site name but that can be changed later.
```eval_rst
.. tip::
If you plan to use gunicorn as your WSGI server (recommended), ensure it is installed before starting your auth project to have an entry automatically created in the project's supervisor config file. ::
pip install gunicorn
```
The settings file needs configuring. Edit the template at `myauth/myauth/settings/local.py`. Be sure to configure the EVE SSO and Email settings. The settings file needs configuring. Edit the template at `myauth/myauth/settings/local.py`. Be sure to configure the EVE SSO and Email settings.
@@ -143,9 +141,9 @@ And finally ensure the allianceserver user has read/write permissions to this di
### Gunicorn ### Gunicorn
To run the auth website a [WSGI Server](https://www.fullstackpython.com/wsgi-servers.html) is required. [Gunicorn](http://gunicorn.org/) is highly recommended for its ease of configuring. Installation is simple: `pip install gunicorn`. It can be manually called with `gunicorn myauth.wsgi` or automatically run using supervisor. To run the auth website a [WSGI Server](https://www.fullstackpython.com/wsgi-servers.html) is required. [Gunicorn](http://gunicorn.org/) is highly recommended for its ease of configuring. It can be manually run with `gunicorn myauth.wsgi` or automatically run using supervisor.
Additional information is available in the [gunicorn](gunicorn.md) doc. The default configuration is good enough for most installations. Additional information is available in the [gunicorn](gunicorn.md) doc.
### Supervisor ### Supervisor
@@ -163,8 +161,15 @@ CentOS:
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:
ln /home/allianceserver/myauth/supervisor.conf /etc/supervisor/conf.d/myauth.conf ln /home/allianceserver/myauth/supervisor.conf /etc/supervisor/conf.d/myauth.conf
supervisorctl reload
CentOS:
ln /home/allianceserver/myauth/supervisor.conf /etc/supervisord.d/myauth.ini
And 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.

View File

@@ -1,108 +1,69 @@
# Apache Setup # Apache Setup
### Overview
AllianceAuth gets served using a Web Server Gateway Interface (WSGI) script. This script passes web requests to AllianceAuth which generates the content to be displayed and returns it. This means very little has to be configured in Apache to host AllianceAuth. ## Overview
In the interest of ~~laziness~~ time-efficiency, scroll down for example configs. Use these, changing the ServerName to your domain name. Alliance Auth gets served using a Web Server Gateway Interface (WSGI) script. This script passes web requests to Alliance Auth which generates the content to be displayed and returns it. This means very little has to be configured in Apache to host Alliance Auth.
If you're using a small VPS to host services with very limited memory resources, consider using NGINX with [Gunicorn](gunicorn.md). Even if you would like to use Apache, Gunicorn may give you lower memory usage over mod_wsgi. If you're using a small VPS to host services with very limited memory, consider using [NGINX](nginx.md).
### Required Parameters for AllianceAuth Core ## Installation
The AllianceAuth core requires the following parameters to be set: Ubuntu:
WSGIDaemonProcess apt-get install apache2
WSGIProcessGroup
WSGIScriptAlias
The following aliases are required: CentOS:
Alias /static/ to point at the static folder yum install httpd
Alias /templates/ to point at the templates folder systemctl enable httpd
systemctl start httpd
## Description of Parameters ## Configuration
- `WSGIDaemonProcess` is the name of the process/application. It also needs to be passed the python-path parameter directing python to search the AllianceAuth directory for modules to load. Apache serves sites through defined virtual hosts. These are located in `/etc/apache2/sites-available/` on Ubuntu and `/etc/httpd/conf.d/httpd.conf` on CentOS.
- `WSGIProcessGroup` is the group to run the process under. Typically the same as the name of the process/application.
- `WSGIScriptAlias` points to the WSGI script.
## Additional Parameters for Full Setup A virtual host for auth need only proxy requests to your WSGI server (gunicorn if you followed the install guide) and serve static files. Examples can be found below. Create your config in its own file eg `myauth.conf`.
To pass additional services the following aliases and directories are required: ### Ubuntu
- `Alias /forums` to point at the forums folder To proxy and modify headers a few mods need to be enabled.
- `Alias /killboard` to point at the killboard
Each of these require directory permissions allowing all connections. a2enmod proxy
a2enmod proxy_http
a2enmod headers
For Apache 2.4 or greater: Create a new config file for auth eg `/etc/apache2/sites-available/myauth.conf` and fill out the virtual host configuration. To enable your config use `a2ensite myauth.conf` and then reload apache with `service apache2 reload`.
<Directory "/path/to/alias/folder"> ### CentOS
Require all granted
</Directory>
For Apache 2.3 or older: Place your virtual host configuration in the appropriate section within `/etc/httpd/conf.d/httpd.conf` and restart the httpd service with `systemctl restart httpd`.
<Directory "/path/to/alias/folder"> ## Sample Config File
Order Deny,Allow
Allow from all
</Directory>
## SSL
You can supply your own SSL certificates if you so desire. The alternative is running behind cloudflare for free SSL.
## Sample Config Files
### Minimally functional config
``` ```
<VirtualHost *:80> <VirtualHost *:80>
ServerName example.com ServerName auth.example.com
ServerAdmin webmaster@localhost
ProxyPassMatch ^/static !
DocumentRoot /var/www ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
WSGIDaemonProcess allianceauth python-path=/home/allianceserver/allianceauth ProxyPreserveHost On
WSGIProcessGroup allianceauth
WSGIScriptAlias / /home/allianceserver/allianceauth/alliance_auth/wsgi.py Alias "/static" "/var/www/myauth/static"
<Directory "/var/www/myauth/static">
Alias /static/ /home/allianceserver/allianceauth/static/ Require all granted
<Directory /home/allianceserver/allianceauth/>
Require all granted
</Directory> </Directory>
<Directory /var/www/>
Require all granted
</Directory>
</VirtualHost> </VirtualHost>
``` ```
### Own SSL Cert If you use SSL, add the following lines inside the `VirtualHost` block:
- Apache 2.4 or newer:
- [000-default.conf](http://pastebin.com/3LLzyNmV)
- [default-ssl.conf](http://pastebin.com/HUPPEp0R)
- Apache 2.3 or older:
- [000-default](http://pastebin.com/HfyKpQNu)
- [default-ssl](http://pastebin.com/2WCS5jnb)
### No SSL Cloudflare, or LetsEncrypt ```
- Apache 2.4 or newer: RequestHeader set X-FORWARDED-PROTOCOL https
- [000-default.conf](http://pastebin.com/j1Ps3ZK6) RequestHeader set X-FORWARDED-SSL On
- Apache 2.3 or older: ```
- [000-default](http://pastebin.com/BHQzf2pj)
To have LetsEncrypt automatically install SSL certs, comment out the three lines starting with `WSGI`, install certificates, then uncomment them in `000-default-ls-ssl.conf` ## SSL
## Enabling and Disabling Sites It's 2018 - there's no reason to run a site without SSL. The EFF provides free, renewable SSL certificates with an automated installer. Visit their [website](https://certbot.eff.org/) for information.
To instruct apache to serve traffic from a virtual host, enable it:
sudo a2ensite NAME
where NAME is the name of the configuration file (eg 000-default.conf)
To disable traffic from a site, disable the virtual host:
sudo a2dissite NAME
where NAME is the name of the configuration file (eg 000-default.conf)

View File

@@ -47,7 +47,7 @@ server {
location = /favicon.ico { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; }
location /static/ { location /static/ {
alias /home/allianceserver/allianceauth/static/; alias /var/www/myauth/static;
autoindex off; autoindex off;
} }

View File

@@ -10,7 +10,7 @@ app = Celery('devauth')
# Using a string here means the worker don't have to serialize # Using a string here means the worker don't have to serialize
# the configuration object to child processes. # the configuration object to child processes.
app.config_from_object('django.conf:settings') app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

View File

@@ -14,7 +14,7 @@ NOSE_ARGS = [
] ]
# Celery configuration # Celery configuration
CELERY_ALWAYS_EAGER = True # Forces celery to run locally for testing CELERY_TASK_ALWAYS_EAGER = True # Forces celery to run locally for testing
INSTALLED_APPS += [ INSTALLED_APPS += [
'allianceauth.eveonline.autogroups', 'allianceauth.eveonline.autogroups',