Adarnof's Little Things (#547)

* Port to Django 1.10
Initial migrations for current states of all models. Requires faking to retain data.
Removed all references to render_to_response, replacing with render shortcut.
Same for HttpResponseRedirect to render shortcut.
Corrected notification signal import to wait for app registry to finish loading.

* Correct typos from render conversion

* Modify models to suppress Django field warnings

* Script for automatic database conversion
 - fakes initial migrations to preserve data
Include LOGIN_URL setting

* Correct context processor import typo

* Removed pathfinder support.
Current pathfinder versions require SSO, not APIs added to database.
Conditionally load additional database definitions only if services are enabled.
Prevents errors when running auth without creating all possible databases.

* Condense context processors

* Include Django 1.10 installation in migrate script
Remove syncdb/evolve, replace with migrate for update script

* Replaced member/blue perms with user state system
Removed sigtracker
Initial migrations for default perms and groups
Removed perm bootstrapping on first run

* Clean up services list

* Remove fleet fittings page

* Provide action feedback via django messaging
Display unread notification count
Correct left navbar alignment

* Stop storing service passwords.
Provide them one time upon activation or reset.
Closes #177

* Add group sync buttons to admin site
Allow searcing of AuthServicesInfo models
Display user main character

* Correct button CSS to remove underlines on hover

* Added bulk actions to notifications
Altered notification default ordering

* Centralize API key validation.
Remove unused error count on API key model.
Restructure API key refresh task to queue all keys per user and await completion.
Closes #350

* Example configuration files for supervisor.
Copy to /etc/supervisor/conf.d and restart to take effect.
Closes #521
Closes #266

* Pre-save receiver for member/blue state switching
Removed is_blue field
Added link to admin site

* Remove all hardcoded URLs from views and templates
Correct missing render arguments
Closes #540

* Correct celeryd process directory

* Migration to automatically set user states.
Runs instead of waiting for next API refresh cycle. Should make the transition much easier.

* Verify service accounts accessible to member state

* Restructure project to remove unnecessary apps.
(celerytask, util, portal, registraion apps)
Added workarounds for python 3 compatibility.

* Correct python2 compatibility

* Check services against state being changed to

* Python3 compatibility fixes

* Relocate x2bool py3 fix

* SSO integration for logging in to existing accounts.

* Add missing url names for fleetup reverse

* Sanitize groupnames before syncing.

* Correct trailing slash preventing url resolution

* Alter group name sanitization to allow periods and hyphens

* Correct state check on pre_save model for corp/alliance group assignment

* Remove sigtracker table from old dbs to allow user deletion

* Include missing celery configuration

* Teamspeak error handling

* Prevent celery worker deadlock on async group result wait

* Correct active navbar links for translated urls.
Correct corp status url resolution for some links.
Remove DiscordAuthToken model.
This commit is contained in:
Adarnof 2016-10-16 18:01:14 -04:00 committed by GitHub
parent 56136d050a
commit 1b4f5e4e88
220 changed files with 5716 additions and 5331 deletions

7
.gitignore vendored
View File

@ -60,3 +60,10 @@ nginx_config.txt
# custom staticfiles # custom staticfiles
static/* static/*
#celerybeat
*.pid
celerybeat-schedule
#pycharm
.idea/*

View File

@ -4,15 +4,16 @@
<facet type="django" name="Django"> <facet type="django" name="Django">
<configuration> <configuration>
<option name="rootFolder" value="$MODULE_DIR$" /> <option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="settings.py" /> <option name="settingsModule" value="alliance_auth/settings.py.example" />
<option name="manageScript" value="manage.py" /> <option name="manageScript" value="manage.py" />
<option name="environment" value="&lt;map/&gt;" /> <option name="environment" value="&lt;map/&gt;" />
<option name="commandsToSkip" value="" />
</configuration> </configuration>
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 2.7.6 (/usr/bin/python2.7)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 2.7.11 virtualenv at ~/1.6" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="TemplatesService"> <component name="TemplatesService">

12
.idea/dataSources.xml generated
View File

@ -1,30 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DataSourceManagerImpl" format="xml" hash="1026499400"> <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="Django default" uuid="3eb61453-647a-4832-8320-f3561f039abc"> <data-source source="LOCAL" name="Django default" uuid="3eb61453-647a-4832-8320-f3561f039abc">
<driver-ref>mysql</driver-ref> <driver-ref>mysql</driver-ref>
<jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver> <jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_auth</jdbc-url> <jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_auth</jdbc-url>
<user-name>allianceauth</user-name>
<user-password>dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfcbdfdfdfdedfc2</user-password>
<libraries />
</data-source> </data-source>
<data-source source="LOCAL" name="Django phpbb3" uuid="2de247c2-1951-4e74-8276-6a1c89c396fa"> <data-source source="LOCAL" name="Django phpbb3" uuid="2de247c2-1951-4e74-8276-6a1c89c396fa">
<driver-ref>mysql</driver-ref> <driver-ref>mysql</driver-ref>
<jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver> <jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_forum</jdbc-url> <jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_forum</jdbc-url>
<user-name>allianceauth</user-name>
<user-password>dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfcbdfdfdfdedfc2</user-password>
<libraries />
</data-source> </data-source>
<data-source source="LOCAL" name="Django mumble" uuid="9963e5ca-7f2f-4dd3-9175-bc7102dfd48c"> <data-source source="LOCAL" name="Django mumble" uuid="9963e5ca-7f2f-4dd3-9175-bc7102dfd48c">
<driver-ref>mysql</driver-ref> <driver-ref>mysql</driver-ref>
<jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver> <jdbc-driver>com.mysql.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_mumble</jdbc-url> <jdbc-url>jdbc:mysql://127.0.0.1:3306/alliance_mumble</jdbc-url>
<user-name>alliancemumble</user-name>
<user-password>dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfc7dfdfdfc7dfc8dfc6dfcf</user-password>
<libraries />
</data-source> </data-source>
</component> </component>
</project> </project>

6
.idea/misc.xml generated
View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.8 (C:\Python27\python.exe)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.11 virtualenv at ~/1.6" project-jdk-type="Python SDK" />
<component name="PythonCompatibilityInspectionAdvertiser">
<option name="version" value="1" />
</component>
</project> </project>

View File

@ -18,7 +18,7 @@ Join us in-game in the channel allianceauth for help and feature requests.
Special Thanks: Special Thanks:
Thanking Nikdoof, without his old auth implementation this project wouldn't be as far as it is now. Thanks to Nikdoof, without his old auth implementation this project wouldn't be as far as it is now.
Note: Note:
@ -29,8 +29,7 @@ Note:
Requirements: Requirements:
# Django Stuff # # Django Stuff #
django 1.6.1 django 1.10.1
django-evolution
django-bootstrap-form django-bootstrap-form
django-celery django-celery
@ -58,11 +57,9 @@ Vagrant Instructions:
Special Permissions In Admin: Special Permissions In Admin:
auth | user | alliance_member ( Added auto by auth when a member is verified )
auth | user | group_management ( Access to add members to groups within the alliance ) auth | user | group_management ( Access to add members to groups within the alliance )
auth | user | jabber_broadcast ( Access to broadcast a message over jabber to own groups) auth | user | jabber_broadcast ( Access to broadcast a message over jabber to own groups)
auth | user | jabber_broadcast_all ( Can choose from all groups and the 'all' option when broadcasting) auth | user | jabber_broadcast_all ( Can choose from all groups and the 'all' option when broadcasting)
auth | user | blue_member ( Auto Added to people who register has a blue when adding api key)
auth | user | corp_apis ( View APIs, and jackKnife, of all members in user's corp. ) auth | user | corp_apis ( View APIs, and jackKnife, of all members in user's corp. )
auth | user | alliance_apis ( View APIs, and jackKnife, of all member in user's alliance member corps. ) auth | user | alliance_apis ( View APIs, and jackKnife, of all member in user's alliance member corps. )
auth | user | timer_management ( Access to create and remove timers) auth | user | timer_management ( Access to create and remove timers)

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,43 +1,46 @@
""" """
vim: set filetype=python:
Django settings for alliance_auth project. Django settings for alliance_auth project.
Generated by 'django-admin startproject' using Django 1.10.1.
For more information on this file, see For more information on this file, see
https://docs.djangoproject.com/en/1.6/topics/settings/ https://docs.djangoproject.com/en/1.10/topics/settings/
For the full list of settings and their values, see For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.6/ref/settings/ https://docs.djangoproject.com/en/1.10/ref/settings/
""" """
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
import djcelery import djcelery
from django.contrib import messages
djcelery.setup_loader() djcelery.setup_loader()
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Celery configuration
BROKER_URL = 'amqp://guest:guest@localhost:5672/'
CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler"
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
# Generate a new key here: http://www.miniwebtool.com/django-secret-key-generator/ SECRET_KEY = ''
SECRET_KEY = os.environ.get('AA_SECRET_KEY', '5xvh4e0x&@-$6(kj%4^80pdo1n5v-!mtx(e(1tw@kn-1le*ts@')
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = 'True' == os.environ.get('AA_DEBUG','True') DEBUG = 'True' == os.environ.get('AA_DEBUG','True')
TEMPLATE_DEBUG = True ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['127.0.0.1','yourdomain.com','www.yourdomain.com']
BROKER_URL = 'amqp://guest:guest@localhost:5672/'
CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler"
# Application definition # Application definition
INSTALLED_APPS = (
INSTALLED_APPS = [
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
@ -45,27 +48,25 @@ INSTALLED_APPS = (
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.humanize', 'django.contrib.humanize',
'django_evolution',
'djcelery', 'djcelery',
'celerytask',
'bootstrapform', 'bootstrapform',
'authentication', 'authentication',
'portal',
'registration',
'services', 'services',
'eveonline', 'eveonline',
'groupmanagement', 'groupmanagement',
'hrapplications', 'hrapplications',
'timerboard', 'timerboard',
'srp', 'srp',
'sigtracker',
'optimer', 'optimer',
'corputils', 'corputils',
'fleetactivitytracking', 'fleetactivitytracking',
'notifications', 'notifications',
) 'eve_sso',
'geelweb.django.navhelper',
]
MIDDLEWARE_CLASSES = ( MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
@ -73,7 +74,9 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
) ]
ROOT_URLCONF = 'alliance_auth.urls'
LOCALE_PATHS = ( LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale/'), os.path.join(BASE_DIR, 'locale/'),
@ -85,105 +88,75 @@ LANGUAGES = (
('de', ugettext('German')), ('de', ugettext('German')),
) )
ROOT_URLCONF = 'alliance_auth.urls' TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'customization/templates'),
os.path.join(BASE_DIR, 'stock/templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'services.context_processors.auth_settings',
'notifications.context_processors.user_notification_count',
'authentication.context_processors.states',
'authentication.context_processors.membership_state',
'authentication.context_processors.sso',
],
},
},
]
WSGI_APPLICATION = 'alliance_auth.wsgi.application' WSGI_APPLICATION = 'alliance_auth.wsgi.application'
# Database # Database
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_auth', 'NAME': 'aa_test',
'USER': os.environ.get('AA_DB_DEFAULT_USER', 'allianceserver'), 'USER': os.environ.get('AA_DB_DEFAULT_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_DEFAULT_PASSWORD', 'password'), 'PASSWORD': os.environ.get('AA_DB_DEFAULT_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_DEFAULT_HOST', '127.0.0.1'), 'HOST': os.environ.get('AA_DB_DEFAULT_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_DEFAULT_PORT', '3306'), 'PORT': os.environ.get('AA_DB_DEFAULT_PORT', '3306'),
}, },
'phpbb3': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_forum',
'USER': os.environ.get('AA_DB_PHPBB3_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_PHPBB3_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_PHPBB3_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_PHPBB3_PORT', '3306'),
},
'ips4': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_ips4',
'USER': os.environ.get('AA_DB_IPS4_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_IPS4_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_IPS4_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_IPS4_PORT', '3306'),
},
'smf': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_smf',
'USER': os.environ.get('AA_DB_SMF_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_SMF_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_SMF_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_SMF_PORT', '3306'),
},
'market': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_market',
'USER': os.environ.get('AA_DB_MARKET_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_MARKET_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_MARKET_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_MARKET_PORT', '3306'),
},
'pathfinder': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_pathfinder',
'USER': os.environ.get('AA_DB_PATHFINDER_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_PATHFINDER_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_PATHFINDER_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_PATHFINDER_PORT', '3306'),
} }
} # Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
TEMPLATE_CONTEXT_PROCESSORS = ( AUTH_PASSWORD_VALIDATORS = [
'django.contrib.auth.context_processors.auth', {
'django.core.context_processors.debug', 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
'django.core.context_processors.i18n', },
'django.core.context_processors.media', {
'django.core.context_processors.static', 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'django.core.context_processors.tz', },
'django.contrib.messages.context_processors.messages', {
'django.core.context_processors.request', 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
'util.context_processors.is_corp', },
'util.context_processors.corp_id', {
'util.context_processors.corp_name', 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
'util.context_processors.alliance_id', },
'util.context_processors.alliance_name', ]
'util.context_processors.jabber_url',
'util.context_processors.domain_url',
'util.context_processors.member_api_mask',
'util.context_processors.blue_api_mask',
'notifications.context_processors.user_notification_count',
)
TEMPLATE_DIRS = ( LOGIN_URL = 'auth_login_user'
os.path.join(BASE_DIR, 'customization/templates'),
os.path.join(BASE_DIR, 'stock/templates'),
)
STATICFILES_DIRS = ( SUPERUSER_STATE_BYPASS = 'True' == os.environ.get('AA_SUPERUSER_STATE_BYPASS', 'True')
os.path.join(BASE_DIR, "customization/static"),
os.path.join(BASE_DIR, "stock/static"),
)
LOGIN_URL = '/login_user/'
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/ # https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = os.environ.get('AA_LANGUAGE_CODE', 'en-us') LANGUAGE_CODE = os.environ.get('AA_LANGUAGE_CODE', 'en-us')
@ -195,11 +168,21 @@ USE_L10N = True
USE_TZ = True USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/home/allianceserver/allianceauth/static/'
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "customization/static"),
os.path.join(BASE_DIR, "stock/static"),
)
# Bootstrap messaging css workaround
MESSAGE_TAGS = {
messages.ERROR: 'danger'
}
##################################################### #####################################################
## ##
@ -216,7 +199,6 @@ STATIC_ROOT = '/home/allianceserver/allianceauth/static/'
########################### ###########################
IS_CORP = 'True' == os.environ.get('AA_IS_CORP', 'True') IS_CORP = 'True' == os.environ.get('AA_IS_CORP', 'True')
################# #################
# EMAIL SETTINGS # EMAIL SETTINGS
################# #################
@ -245,7 +227,19 @@ EMAIL_USE_TLS = 'True' == os.environ.get('AA_EMAIL_USE_TLS', 'True')
KILLBOARD_URL = os.environ.get('AA_KILLBOARD_URL', '') KILLBOARD_URL = os.environ.get('AA_KILLBOARD_URL', '')
EXTERNAL_MEDIA_URL = os.environ.get('AA_EXTERNAL_MEDIA_URL', '') EXTERNAL_MEDIA_URL = os.environ.get('AA_EXTERNAL_MEDIA_URL', '')
FORUM_URL = os.environ.get('AA_FORUM_URL', '') FORUM_URL = os.environ.get('AA_FORUM_URL', '')
SMF_URL = os.environ.get('AA_SMF_URL', '')
###################
# SSO Settings
###################
# Optional SSO.
# Get client ID and client secret from registering an app at
# https://developers.eveonline.com/
# Callback URL should be http://mydomain.com/sso/callback
# Leave callback blank to hide SSO button on login page
###################
EVE_SSO_CLIENT_ID = os.environ.get('AA_EVE_SSO_CLIENT_ID', '')
EVE_SSO_CLIENT_SECRET = os.environ.get('AA_EVE_SSO_CLIENT_SECRET', '')
EVE_SSO_CALLBACK_URL = os.environ.get('AA_EVE_SSO_CALLBACK_URL', '')
######################### #########################
# Default Group Settings # Default Group Settings
@ -287,7 +281,6 @@ ENABLE_AUTH_DISCOURSE = 'True' == os.environ.get('AA_ENABLE_AUTH_DISCOURSE', 'Fa
ENABLE_AUTH_IPS4 = 'True' == os.environ.get('AA_ENABLE_AUTH_IPS4', 'False') ENABLE_AUTH_IPS4 = 'True' == os.environ.get('AA_ENABLE_AUTH_IPS4', 'False')
ENABLE_AUTH_SMF = 'True' == os.environ.get('AA_ENABLE_AUTH_SMF', 'False') ENABLE_AUTH_SMF = 'True' == os.environ.get('AA_ENABLE_AUTH_SMF', 'False')
ENABLE_AUTH_MARKET = 'True' == os.environ.get('AA_ENABLE_AUTH_MARKET', 'False') ENABLE_AUTH_MARKET = 'True' == os.environ.get('AA_ENABLE_AUTH_MARKET', 'False')
ENABLE_AUTH_PATHFINDER = 'True' == os.environ.get('AA_ENABLE_AUTH_PATHFINDER', 'False')
ENABLE_AUTH_XENFORO = 'True' == os.environ.get('AA_ENABLE_AUTH_XENFORO', 'False') ENABLE_AUTH_XENFORO = 'True' == os.environ.get('AA_ENABLE_AUTH_XENFORO', 'False')
##################### #####################
@ -317,7 +310,6 @@ ENABLE_BLUE_DISCOURSE = 'True' == os.environ.get('AA_ENABLE_BLUE_DISCOURSE', 'Fa
ENABLE_BLUE_IPS4 = 'True' == os.environ.get('AA_ENABLE_BLUE_IPS4', 'False') ENABLE_BLUE_IPS4 = 'True' == os.environ.get('AA_ENABLE_BLUE_IPS4', 'False')
ENABLE_BLUE_SMF = 'True' == os.environ.get('AA_ENABLE_BLUE_SMF', 'False') ENABLE_BLUE_SMF = 'True' == os.environ.get('AA_ENABLE_BLUE_SMF', 'False')
ENABLE_BLUE_MARKET = 'True' == os.environ.get('AA_ENABLE_BLUE_MARKET', 'False') ENABLE_BLUE_MARKET = 'True' == os.environ.get('AA_ENABLE_BLUE_MARKET', 'False')
ENABLE_BLUE_PATHFINDER = 'True' == os.environ.get('AA_ENABLE_BLUE_PATHFINDER', 'False')
ENABLE_BLUE_XENFORO = 'True' == os.environ.get('AA_ENABLE_BLUE_XENFORO', 'False') ENABLE_BLUE_XENFORO = 'True' == os.environ.get('AA_ENABLE_BLUE_XENFORO', 'False')
######################### #########################
@ -360,15 +352,18 @@ BLUE_API_ACCOUNT = 'True' == os.environ.get('AA_BLUE_API_ACCOUNT', 'False')
REJECT_OLD_APIS = 'True' == os.environ.get('AA_REJECT_OLD_APIS', 'False') REJECT_OLD_APIS = 'True' == os.environ.get('AA_REJECT_OLD_APIS', 'False')
REJECT_OLD_APIS_MARGIN = os.environ.get('AA_REJECT_OLD_APIS_MARGIN', 50) REJECT_OLD_APIS_MARGIN = os.environ.get('AA_REJECT_OLD_APIS_MARGIN', 50)
##########################
# Pathfinder Configuration
##########################
PATHFINDER_URL = os.environ.get('AA_PATHFINDER_URL', 'http://pathfinder.yourdomain.com')
##################### #####################
# Alliance Market # Alliance Market
##################### #####################
MARKET_URL = os.environ.get('AA_MARKET_URL', 'http://yourdomain.com/market') MARKET_URL = os.environ.get('AA_MARKET_URL', 'http://yourdomain.com/market')
MARKET_DB = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_market',
'USER': os.environ.get('AA_DB_MARKET_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_MARKET_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_MARKET_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_MARKET_PORT', '3306'),
}
##################### #####################
# HR Configuration # HR Configuration
@ -427,6 +422,18 @@ BROADCAST_SERVICE_NAME = os.environ.get('AA_BROADCAST_SERVICE_NAME', "broadcast"
MUMBLE_URL = os.environ.get('AA_MUMBLE_URL', "yourdomain.com") MUMBLE_URL = os.environ.get('AA_MUMBLE_URL', "yourdomain.com")
MUMBLE_SERVER_ID = int(os.environ.get('AA_MUMBLE_SERVER_ID', '1')) MUMBLE_SERVER_ID = int(os.environ.get('AA_MUMBLE_SERVER_ID', '1'))
######################################
# PHPBB3 Configuration
######################################
PHPBB3_DB = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_forum',
'USER': os.environ.get('AA_DB_PHPBB3_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_PHPBB3_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_PHPBB3_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_PHPBB3_PORT', '3306'),
}
###################################### ######################################
# Teamspeak3 Configuration # Teamspeak3 Configuration
###################################### ######################################
@ -484,6 +491,28 @@ DISCOURSE_API_KEY = os.environ.get('AA_DISCOURSE_API_KEY', '')
##################################### #####################################
IPS4_URL = os.environ.get('AA_IPS4_URL', 'http://yourdomain.com/ips4') IPS4_URL = os.environ.get('AA_IPS4_URL', 'http://yourdomain.com/ips4')
IPS4_API_KEY = os.environ.get('AA_IPS4_API_KEY', '') IPS4_API_KEY = os.environ.get('AA_IPS4_API_KEY', '')
IPS4_DB = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_ips4',
'USER': os.environ.get('AA_DB_IPS4_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_IPS4_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_IPS4_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_IPS4_PORT', '3306'),
}
######################################
# SMF Configuration
######################################
SMF_URL = os.environ.get('AA_SMF_URL', '')
SMF_DB = {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'alliance_smf',
'USER': os.environ.get('AA_DB_SMF_USER', 'allianceserver'),
'PASSWORD': os.environ.get('AA_DB_SMF_PASSWORD', 'password'),
'HOST': os.environ.get('AA_DB_SMF_HOST', '127.0.0.1'),
'PORT': os.environ.get('AA_DB_SMF_PORT', '3306'),
}
###################################### ######################################
# Fleet-Up Configuration # Fleet-Up Configuration
@ -597,7 +626,7 @@ LOGGING = {
'level': 'DEBUG', 'level': 'DEBUG',
}, },
'fleetactivitytracking': { 'fleetactivitytracking': {
'handlers': ['log_file', 'console'], 'handlers': ['log_file', 'console', 'notifications'],
'level': 'ERROR', 'level': 'ERROR',
}, },
'util': { 'util': {
@ -610,3 +639,13 @@ LOGGING = {
}, },
} }
} }
# Conditionally add databases only if configured
if ENABLE_AUTH_FORUM or ENABLE_BLUE_FORUM:
DATABASES['phpbb3'] = PHPBB3_DB
if ENABLE_AUTH_SMF or ENABLE_BLUE_SMF:
DATABASES['smf'] = SMF_DB
if ENABLE_AUTH_MARKET or ENABLE_BLUE_MARKET:
DATABASES['market'] = MARKET_DB
if ENABLE_AUTH_IPS4 or ENABLE_BLUE_IPS4:
DATABASES['ips4'] = IPS4_DB

View File

@ -1,299 +1,303 @@
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.contrib import admin from django.contrib import admin
import django.contrib.auth.views
admin.autodiscover() import authentication.views
import eveonline.views
import services.views
import groupmanagement.views
import optimer.views
import timerboard.views
import corputils.views
import fleetactivitytracking.views
import fleetup.views
import srp.views
import notifications.views
import hrapplications.views
import eve_sso.urls
# Functional/Untranslated URL's # Functional/Untranslated URL's
urlpatterns = patterns('', urlpatterns = [
# Locale # Locale
url(r'^i18n/', include('django.conf.urls.i18n')), url(r'^i18n/', include('django.conf.urls.i18n')),
# Admin urls # Admin urls
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
# SSO
url (r'^sso/', include(eve_sso.urls, namespace='eve_sso')),
url (r'^sso/login$', authentication.views.sso_login, name='auth_sso_login'),
# Index # Index
url(_(r'^$'), 'portal.views.index_view', name='auth_index'), url(_(r'^$'), authentication.views.index_view, name='auth_index'),
# Authentication # Authentication
url(r'^logout_user/', 'authentication.views.logout_user', name='auth_logout_user'), url(r'^logout_user/', authentication.views.logout_user, name='auth_logout_user'),
# Eve Online # Eve Online
url(r'^main_character_change/(\w+)/$', 'eveonline.views.main_character_change', url(r'^main_character_change/(\w+)/$', eveonline.views.main_character_change,
name='auth_main_character_change'), name='auth_main_character_change'),
# Forum Service Control # Forum Service Control
url(r'^activate_forum/$', 'services.views.activate_forum', name='auth_activate_forum'), url(r'^activate_forum/$', services.views.activate_forum, name='auth_activate_forum'),
url(r'^deactivate_forum/$', 'services.views.deactivate_forum', name='auth_deactivate_forum'), url(r'^deactivate_forum/$', services.views.deactivate_forum, name='auth_deactivate_forum'),
url(r'^reset_forum_password/$', 'services.views.reset_forum_password', url(r'^reset_forum_password/$', services.views.reset_forum_password,
name='auth_reset_forum_password'), name='auth_reset_forum_password'),
url(r'^set_forum_password/$', 'services.views.set_forum_password', name='auth_set_forum_password'), url(r'^set_forum_password/$', services.views.set_forum_password, name='auth_set_forum_password'),
# Jabber Service Control # Jabber Service Control
url(r'^activate_jabber/$', 'services.views.activate_jabber', name='auth_activate_jabber'), url(r'^activate_jabber/$', services.views.activate_jabber, name='auth_activate_jabber'),
url(r'^deactivate_jabber/$', 'services.views.deactivate_jabber', name='auth_deactivate_jabber'), url(r'^deactivate_jabber/$', services.views.deactivate_jabber, name='auth_deactivate_jabber'),
url(r'^reset_jabber_password/$', 'services.views.reset_jabber_password', url(r'^reset_jabber_password/$', services.views.reset_jabber_password,
name='auth_reset_jabber_password'), name='auth_reset_jabber_password'),
# Mumble service control # Mumble service control
url(r'^activate_mumble/$', 'services.views.activate_mumble', name='auth_activate_mumble'), url(r'^activate_mumble/$', services.views.activate_mumble, name='auth_activate_mumble'),
url(r'^deactivate_mumble/$', 'services.views.deactivate_mumble', name='auth_deactivate_mumble'), url(r'^deactivate_mumble/$', services.views.deactivate_mumble, name='auth_deactivate_mumble'),
url(r'^reset_mumble_password/$', 'services.views.reset_mumble_password', url(r'^reset_mumble_password/$', services.views.reset_mumble_password,
name='auth_reset_mumble_password'), name='auth_reset_mumble_password'),
url(r'^set_mumble_password/$', 'services.views.set_mumble_password', name='auth_set_mumble_password'), url(r'^set_mumble_password/$', services.views.set_mumble_password, name='auth_set_mumble_password'),
# Ipboard service control # Ipboard service control
url(r'^activate_ipboard/$', 'services.views.activate_ipboard_forum', url(r'^activate_ipboard/$', services.views.activate_ipboard_forum,
name='auth_activate_ipboard'), name='auth_activate_ipboard'),
url(r'^deactivate_ipboard/$', 'services.views.deactivate_ipboard_forum', url(r'^deactivate_ipboard/$', services.views.deactivate_ipboard_forum,
name='auth_deactivate_ipboard'), name='auth_deactivate_ipboard'),
url(r'^reset_ipboard_password/$', 'services.views.reset_ipboard_password', url(r'^reset_ipboard_password/$', services.views.reset_ipboard_password,
name='auth_reset_ipboard_password'), name='auth_reset_ipboard_password'),
url(r'^set_ipboard_password/$', 'services.views.set_ipboard_password', name='auth_set_ipboard_password'), url(r'^set_ipboard_password/$', services.views.set_ipboard_password, name='auth_set_ipboard_password'),
# XenForo service control # XenForo service control
url(r'^activate_xenforo/$', 'services.views.activate_xenforo_forum', url(r'^activate_xenforo/$', services.views.activate_xenforo_forum,
name='auth_activate_xenforo'), name='auth_activate_xenforo'),
url(r'^deactivate_xenforo/$', 'services.views.deactivate_xenforo_forum', url(r'^deactivate_xenforo/$', services.views.deactivate_xenforo_forum,
name='auth_deactivate_xenforo'), name='auth_deactivate_xenforo'),
url(r'^reset_xenforo_password/$', 'services.views.reset_xenforo_password', url(r'^reset_xenforo_password/$', services.views.reset_xenforo_password,
name='auth_reset_xenforo_password'), name='auth_reset_xenforo_password'),
url(r'^set_xenforo_password/$', 'services.views.set_xenforo_password', name='auth_set_xenforo_password'), url(r'^set_xenforo_password/$', services.views.set_xenforo_password, name='auth_set_xenforo_password'),
# Teamspeak3 service control # Teamspeak3 service control
url(r'^activate_teamspeak3/$', 'services.views.activate_teamspeak3', url(r'^activate_teamspeak3/$', services.views.activate_teamspeak3,
name='auth_activate_teamspeak3'), name='auth_activate_teamspeak3'),
url(r'^deactivate_teamspeak3/$', 'services.views.deactivate_teamspeak3', url(r'^deactivate_teamspeak3/$', services.views.deactivate_teamspeak3,
name='auth_deactivate_teamspeak3'), name='auth_deactivate_teamspeak3'),
url(r'reset_teamspeak3_perm/$', 'services.views.reset_teamspeak3_perm', url(r'reset_teamspeak3_perm/$', services.views.reset_teamspeak3_perm,
name='auth_reset_teamspeak3_perm'), name='auth_reset_teamspeak3_perm'),
# Discord Service Control # Discord Service Control
url(r'^activate_discord/$', 'services.views.activate_discord', name='auth_activate_discord'), url(r'^activate_discord/$', services.views.activate_discord, name='auth_activate_discord'),
url(r'^deactivate_discord/$', 'services.views.deactivate_discord', name='auth_deactivate_discord'), url(r'^deactivate_discord/$', services.views.deactivate_discord, name='auth_deactivate_discord'),
url(r'^reset_discord/$', 'services.views.reset_discord', name='auth_reset_discord'), url(r'^reset_discord/$', services.views.reset_discord, name='auth_reset_discord'),
url(r'^discord_callback/$', 'services.views.discord_callback', name='auth_discord_callback'), url(r'^discord_callback/$', services.views.discord_callback, name='auth_discord_callback'),
url(r'^discord_add_bot/$', 'services.views.discord_add_bot', name='auth_discord_add_bot'), url(r'^discord_add_bot/$', services.views.discord_add_bot, name='auth_discord_add_bot'),
# Discourse Service Control # Discourse Service Control
url(r'^activate_discourse/$', 'services.views.activate_discourse', name='auth_activate_discourse'), url(r'^activate_discourse/$', services.views.activate_discourse, name='auth_activate_discourse'),
url(r'^deactivate_discourse/$', 'services.views.deactivate_discourse', name='auth_deactivate_discourse'), url(r'^deactivate_discourse/$', services.views.deactivate_discourse, name='auth_deactivate_discourse'),
# IPS4 Service Control # IPS4 Service Control
url(r'^activate_ips4/$', 'services.views.activate_ips4', url(r'^activate_ips4/$', services.views.activate_ips4,
name='auth_activate_ips4'), name='auth_activate_ips4'),
url(r'^deactivate_ips4/$', 'services.views.deactivate_ips4', url(r'^deactivate_ips4/$', services.views.deactivate_ips4,
name='auth_deactivate_ips4'), name='auth_deactivate_ips4'),
url(r'^reset_ips4_password/$', 'services.views.reset_ips4_password', url(r'^reset_ips4_password/$', services.views.reset_ips4_password,
name='auth_reset_ips4_password'), name='auth_reset_ips4_password'),
url(r'^set_ips4_password/$', 'services.views.set_ips4_password', name='auth_set_ips4_password'), url(r'^set_ips4_password/$', services.views.set_ips4_password, name='auth_set_ips4_password'),
# SMF Service Control # SMF Service Control
url(r'^activate_smf/$', 'services.views.activate_smf', name='auth_activate_smf'), url(r'^activate_smf/$', services.views.activate_smf, name='auth_activate_smf'),
url(r'^deactivate_smf/$', 'services.views.deactivate_smf', name='auth_deactivate_smf'), url(r'^deactivate_smf/$', services.views.deactivate_smf, name='auth_deactivate_smf'),
url(r'^reset_smf_password/$', 'services.views.reset_smf_password', url(r'^reset_smf_password/$', services.views.reset_smf_password,
name='auth_reset_smf_password'), name='auth_reset_smf_password'),
url(r'^set_smf_password/$', 'services.views.set_smf_password', name='auth_set_smf_password'), url(r'^set_smf_password/$', services.views.set_smf_password, name='auth_set_smf_password'),
# Alliance Market Control # Alliance Market Control
url(r'^activate_market/$', 'services.views.activate_market', name='auth_activate_market'), url(r'^activate_market/$', services.views.activate_market, name='auth_activate_market'),
url(r'^deactivate_market/$', 'services.views.deactivate_market', name='auth_deactivate_market'), url(r'^deactivate_market/$', services.views.deactivate_market, name='auth_deactivate_market'),
url(r'^reset_market_password/$', 'services.views.reset_market_password', url(r'^reset_market_password/$', services.views.reset_market_password,
name='auth_reset_market_password'), name='auth_reset_market_password'),
url(r'^set_market_password/$', 'services.views.set_market_password', name='auth_set_market_password'), url(r'^set_market_password/$', services.views.set_market_password, name='auth_set_market_password'),
# Pathfinder Control
url(r'^activate_pathfinder/$', 'services.views.activate_pathfinder', name='auth_activate_pathfinder'),
url(r'^deactivate_pathfinder/$', 'services.views.deactivate_pathfinder', name='auth_deactivate_pathfinder'),
url(r'^reset_pathfinder_password/$', 'services.views.reset_pathfinder_password',
name='auth_reset_pathfinder_password'),
url(r'^set_pathfinder_password/$', 'services.views.set_pathfinder_password', name='auth_set_pathfinder_password'),
# SRP URLS # SRP URLS
url(r'^srp_fleet_remove/(\w+)$', 'srp.views.srp_fleet_remove', name='auth_srp_fleet_remove'), url(r'^srp_fleet_remove/(\w+)$', srp.views.srp_fleet_remove, name='auth_srp_fleet_remove'),
url(r'^srp_fleet_disable/(\w+)$', 'srp.views.srp_fleet_disable', name='auth_srp_fleet_disable'), url(r'^srp_fleet_disable/(\w+)$', srp.views.srp_fleet_disable, name='auth_srp_fleet_disable'),
url(r'^srp_fleet_enable/(\w+)$', 'srp.views.srp_fleet_enable', name='auth_srp_fleet_enable'), url(r'^srp_fleet_enable/(\w+)$', srp.views.srp_fleet_enable, name='auth_srp_fleet_enable'),
url(r'^srp_fleet_mark_completed/(\w+)', 'srp.views.srp_fleet_mark_completed', url(r'^srp_fleet_mark_completed/(\w+)', srp.views.srp_fleet_mark_completed,
name='auth_srp_fleet_mark_completed'), name='auth_srp_fleet_mark_completed'),
url(r'^srp_fleet_mark_uncompleted/(\w+)', 'srp.views.srp_fleet_mark_uncompleted', url(r'^srp_fleet_mark_uncompleted/(\w+)', srp.views.srp_fleet_mark_uncompleted,
name='auth_srp_fleet_mark_uncompleted'), name='auth_srp_fleet_mark_uncompleted'),
url(r'^srp_request_remove/(\w+)', 'srp.views.srp_request_remove', url(r'^srp_request_remove/(\w+)', srp.views.srp_request_remove,
name="auth_srp_request_remove"), name="auth_srp_request_remove"),
url(r'srp_request_approve/(\w+)', 'srp.views.srp_request_approve', url(r'srp_request_approve/(\w+)', srp.views.srp_request_approve,
name='auth_srp_request_approve'), name='auth_srp_request_approve'),
url(r'srp_request_reject/(\w+)', 'srp.views.srp_request_reject', name='auth_srp_request_reject'), url(r'srp_request_reject/(\w+)', srp.views.srp_request_reject, name='auth_srp_request_reject'),
# Notifications # Notifications
url(r'^remove_notifications/(\w+)/$', 'notifications.views.remove_notification', name='auth_remove_notification'), url(r'^remove_notifications/(\w+)/$', notifications.views.remove_notification, name='auth_remove_notification'),
) url(r'^notifications/mark_all_read/$', notifications.views.mark_all_read, name='auth_mark_all_notifications_read'),
url(r'^notifications/delete_all_read/$', notifications.views.delete_all_read,
name='auth_delete_all_read_notifications'),
]
# User viewed/translated URLS # User viewed/translated URLS
urlpatterns += i18n_patterns('', urlpatterns += i18n_patterns(
# corputils # corputils
url(r'^corputils/$', 'corputils.views.corp_member_view', name='auth_corputils'), url(r'^corputils/$', corputils.views.corp_member_view, name='auth_corputils'),
url(r'^corputils/(?P<corpid>[0-9]+)/$', 'corputils.views.corp_member_view'), url(r'^corputils/(?P<corpid>[0-9]+)/$', corputils.views.corp_member_view, name='auth_corputils_corp_view'),
url(r'^corputils/(?P<corpid>[0-9]+)/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', 'corputils.views.corp_member_view', name='auth_corputils_month'), url(r'^corputils/(?P<corpid>[0-9]+)/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', corputils.views.corp_member_view,
url(r'^corputils/search/$', 'corputils.views.corputils_search', name="auth_corputils_search"), name='auth_corputils_month'),
url(r'^corputils/search/(?P<corpid>[0-9]+)/$', 'corputils.views.corputils_search'), url(r'^corputils/search/$', corputils.views.corputils_search, name="auth_corputils_search"),
url(r'^corputils/search/(?P<corpid>[0-9]+)/$', corputils.views.corputils_search, name='auth_corputils_search_corp'),
# FLEET FITTINGS
url(r'^fits/$', 'services.views.fleet_fits', name='auth_fleet_fits'),
# Fleetup # Fleetup
url(r'^fleetup/$', 'fleetup.views.fleetup_view', name='auth_fleetup_view'), url(r'^fleetup/$', fleetup.views.fleetup_view, name='auth_fleetup_view'),
url(r'^fleetup/fittings/$', 'fleetup.views.fleetup_fittings', name='auth_fleetup_fittings'), url(r'^fleetup/fittings/$', fleetup.views.fleetup_fittings, name='auth_fleetup_fittings'),
url(r'^fleetup/fittings/(?P<fittingnumber>[0-9]+)/$', 'fleetup.views.fleetup_fitting'), url(r'^fleetup/fittings/(?P<fittingnumber>[0-9]+)/$', fleetup.views.fleetup_fitting, name='auth_fleetup_fitting'),
url(r'^fleetup/doctrines/$', 'fleetup.views.fleetup_doctrines', name='auth_fleetup_doctrines'), url(r'^fleetup/doctrines/$', fleetup.views.fleetup_doctrines, name='auth_fleetup_doctrines'),
url(r'^fleetup/characters/$', 'fleetup.views.fleetup_characters', name='auth_fleetup_characters'), url(r'^fleetup/characters/$', fleetup.views.fleetup_characters, name='auth_fleetup_characters'),
url(r'^fleetup/doctrines/(?P<doctrinenumber>[0-9]+)/$', 'fleetup.views.fleetup_doctrine'), url(r'^fleetup/doctrines/(?P<doctrinenumber>[0-9]+)/$', fleetup.views.fleetup_doctrine, name='auth_fleetup_doctrine'),
# Authentication # Authentication
url(_(r'^login_user/'), 'authentication.views.login_user', name='auth_login_user'), url(_(r'^login_user/'), authentication.views.login_user, name='auth_login_user'),
url(_(r'^register_user/'), 'registration.views.register_user_view', name='auth_register_user'), url(_(r'^register_user/'), authentication.views.register_user_view, name='auth_register_user'),
url(_(r'^user/password/$'), 'django.contrib.auth.views.password_change', name='password_change'), url(_(r'^user/password/$'), django.contrib.auth.views.password_change, name='password_change'),
url(_(r'^user/password/done/$'), 'django.contrib.auth.views.password_change_done', url(_(r'^user/password/done/$'), django.contrib.auth.views.password_change_done,
name='password_change_done'), name='password_change_done'),
url(_(r'^user/password/reset/$'), 'django.contrib.auth.views.password_reset', url(_(r'^user/password/reset/$'), django.contrib.auth.views.password_reset,
name='password_reset'), name='password_reset'),
url(_(r'^user/password/password/reset/done/$'), 'django.contrib.auth.views.password_reset_done', url(_(r'^user/password/password/reset/done/$'), django.contrib.auth.views.password_reset_done,
name='password_reset_done'), name='password_reset_done'),
url(_(r'^user/password/reset/complete/$'), 'django.contrib.auth.views.password_reset_complete', url(_(r'^user/password/reset/complete/$'), django.contrib.auth.views.password_reset_complete,
name='password_reset_complete'), name='password_reset_complete'),
url(_(r'^user/password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$'), url(_(r'^user/password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$'),
'django.contrib.auth.views.password_reset_confirm', name='password_reset_confirm'), django.contrib.auth.views.password_reset_confirm, name='password_reset_confirm'),
# Portal Urls # Portal Urls
url(_(r'^dashboard/$'), 'portal.views.dashboard_view', name='auth_dashboard'), url(_(r'^dashboard/$'), authentication.views.dashboard_view, name='auth_dashboard'),
url(_(r'^help/$'), 'portal.views.help_view', name='auth_help'), url(_(r'^help/$'), authentication.views.help_view, name='auth_help'),
# Eveonline Urls # Eveonline Urls
url(_(r'^add_api_key/'), 'eveonline.views.add_api_key', name='auth_add_api_key'), url(_(r'^add_api_key/'), eveonline.views.add_api_key, name='auth_add_api_key'),
url(_(r'^api_key_management/'), 'eveonline.views.api_key_management_view', url(_(r'^api_key_management/'), eveonline.views.api_key_management_view,
name='auth_api_key_management'), name='auth_api_key_management'),
url(_(r'^refresh_api_pair/([0-9]+)/$'), 'eveonline.views.user_refresh_api', name='auth_user_refresh_api'), url(_(r'^refresh_api_pair/([0-9]+)/$'), eveonline.views.user_refresh_api, name='auth_user_refresh_api'),
url(_(r'^delete_api_pair/(\w+)/$'), 'eveonline.views.api_key_removal', name='auth_api_key_removal'), url(_(r'^delete_api_pair/(\w+)/$'), eveonline.views.api_key_removal, name='auth_api_key_removal'),
url(_(r'^characters/'), 'eveonline.views.characters_view', name='auth_characters'), url(_(r'^characters/'), eveonline.views.characters_view, name='auth_characters'),
# Group management # Group management
url(_(r'^groups/'), 'groupmanagement.views.groups_view', name='auth_groups'), url(_(r'^groups/'), groupmanagement.views.groups_view, name='auth_groups'),
url(_(r'^group/management/'), 'groupmanagement.views.group_management', url(_(r'^group/management/'), groupmanagement.views.group_management,
name='auth_group_management'), name='auth_group_management'),
url(_(r'^group/request_add/(\w+)'), 'groupmanagement.views.group_request_add', url(_(r'^group/request_add/(\w+)'), groupmanagement.views.group_request_add,
name='auth_group_request_add'), name='auth_group_request_add'),
url(_(r'^group/request/accept/(\w+)'), 'groupmanagement.views.group_accept_request', url(_(r'^group/request/accept/(\w+)'), groupmanagement.views.group_accept_request,
name='auth_group_accept_request'), name='auth_group_accept_request'),
url(_(r'^group/request/reject/(\w+)'), 'groupmanagement.views.group_reject_request', url(_(r'^group/request/reject/(\w+)'), groupmanagement.views.group_reject_request,
name='auth_group_reject_request'), name='auth_group_reject_request'),
url(_(r'^group/request_leave/(\w+)'), 'groupmanagement.views.group_request_leave', url(_(r'^group/request_leave/(\w+)'), groupmanagement.views.group_request_leave,
name='auth_group_request_leave'), name='auth_group_request_leave'),
url(_(r'group/leave_request/accept/(\w+)'), 'groupmanagement.views.group_leave_accept_request', url(_(r'group/leave_request/accept/(\w+)'), groupmanagement.views.group_leave_accept_request,
name='auth_group_leave_accept_request'), name='auth_group_leave_accept_request'),
url(_(r'^group/leave_request/reject/(\w+)'), 'groupmanagement.views.group_leave_reject_request', url(_(r'^group/leave_request/reject/(\w+)'), groupmanagement.views.group_leave_reject_request,
name='auth_group_leave_reject_request'), name='auth_group_leave_reject_request'),
# HR Application Management # HR Application Management
url(_(r'^hr_application_management/'), 'hrapplications.views.hr_application_management_view', url(_(r'^hr_application_management/'), hrapplications.views.hr_application_management_view,
name="auth_hrapplications_view"), name="auth_hrapplications_view"),
url(_(r'^hr_application_create/$'), 'hrapplications.views.hr_application_create_view', url(_(r'^hr_application_create/$'), hrapplications.views.hr_application_create_view,
name="auth_hrapplication_create_view"), name="auth_hrapplication_create_view"),
url(_(r'^hr_application_create/(\d+)'), 'hrapplications.views.hr_application_create_view', url(_(r'^hr_application_create/(\d+)'), hrapplications.views.hr_application_create_view,
name="auth_hrapplication_create_view"), name="auth_hrapplication_create_view"),
url(_(r'^hr_application_remove/(\w+)'), 'hrapplications.views.hr_application_remove', url(_(r'^hr_application_remove/(\w+)'), hrapplications.views.hr_application_remove,
name="auth_hrapplication_remove"), name="auth_hrapplication_remove"),
url(_(r'hr_application_view/(\w+)'), 'hrapplications.views.hr_application_view', url(_(r'hr_application_view/(\w+)'), hrapplications.views.hr_application_view,
name="auth_hrapplication_view"), name="auth_hrapplication_view"),
url(_(r'hr_application_personal_view/(\w+)'), 'hrapplications.views.hr_application_personal_view', url(_(r'hr_application_personal_view/(\w+)'), hrapplications.views.hr_application_personal_view,
name="auth_hrapplication_personal_view"), name="auth_hrapplication_personal_view"),
url(_(r'hr_application_personal_removal/(\w+)'), url(_(r'hr_application_personal_removal/(\w+)'),
'hrapplications.views.hr_application_personal_removal', hrapplications.views.hr_application_personal_removal,
name="auth_hrapplication_personal_removal"), name="auth_hrapplication_personal_removal"),
url(_(r'hr_application_approve/(\w+)'), 'hrapplications.views.hr_application_approve', url(_(r'hr_application_approve/(\w+)'), hrapplications.views.hr_application_approve,
name="auth_hrapplication_approve"), name="auth_hrapplication_approve"),
url(_(r'hr_application_reject/(\w+)'), 'hrapplications.views.hr_application_reject', url(_(r'hr_application_reject/(\w+)'), hrapplications.views.hr_application_reject,
name="auth_hrapplication_reject"), name="auth_hrapplication_reject"),
url(_(r'hr_application_search/'), 'hrapplications.views.hr_application_search', url(_(r'hr_application_search/'), hrapplications.views.hr_application_search,
name="auth_hrapplication_search"), name="auth_hrapplication_search"),
url(_(r'hr_mark_in_progress/(\w+)'), 'hrapplications.views.hr_application_mark_in_progress', url(_(r'hr_mark_in_progress/(\w+)'), hrapplications.views.hr_application_mark_in_progress,
name="auth_hrapplication_mark_in_progress"), name="auth_hrapplication_mark_in_progress"),
# Fleet Operations Timers # Fleet Operations Timers
url(_(r'^optimer/$'), 'optimer.views.optimer_view', name='auth_optimer_view'), url(_(r'^optimer/$'), optimer.views.optimer_view, name='auth_optimer_view'),
url(_(r'^add_optimer/$'), 'optimer.views.add_optimer_view', name='auth_add_optimer_view'), url(_(r'^add_optimer/$'), optimer.views.add_optimer_view, name='auth_add_optimer_view'),
url(_(r'^remove_optimer/(\w+)'), 'optimer.views.remove_optimer', name='auth_remove_optimer'), url(_(r'^remove_optimer/(\w+)'), optimer.views.remove_optimer, name='auth_remove_optimer'),
url(_(r'^edit_optimer/(\w+)$'), 'optimer.views.edit_optimer', name='auth_edit_optimer'), url(_(r'^edit_optimer/(\w+)$'), optimer.views.edit_optimer, name='auth_edit_optimer'),
# Service Urls # Service Urls
url(_(r'^services/$'), 'services.views.services_view', name='auth_services'), url(_(r'^services/$'), services.views.services_view, name='auth_services'),
url(_(r'^services/jabber_broadcast/$'), 'services.views.jabber_broadcast_view', url(_(r'^services/jabber_broadcast/$'), services.views.jabber_broadcast_view,
name='auth_jabber_broadcast_view'), name='auth_jabber_broadcast_view'),
# Teamspeak Urls # Teamspeak Urls
url(r'verify_teamspeak3/$', 'services.views.verify_teamspeak3', name='auth_verify_teamspeak3'), url(r'verify_teamspeak3/$', services.views.verify_teamspeak3, name='auth_verify_teamspeak3'),
# corputils # corputils
url(_(r'^corputils/$'), 'corputils.views.corp_member_view', name='auth_corputils'), url(_(r'^corputils/$'), corputils.views.corp_member_view, name='auth_corputils'),
url(_(r'^corputils/(?P<corpid>[0-9]+)/$'), 'corputils.views.corp_member_view'), url(_(r'^corputils/(?P<corpid>[0-9]+)/$'), corputils.views.corp_member_view, name='auth_corputils_corp_view'),
url(_(r'^corputils/search/$'), 'corputils.views.corputils_search', name="auth_corputils_search"), url(_(r'^corputils/search/$'), corputils.views.corputils_search, name="auth_corputils_search"),
url(_(r'^corputils/search/(?P<corpid>[0-9]+)/$'), 'corputils.views.corputils_search'), url(_(r'^corputils/search/(?P<corpid>[0-9]+)/$'), corputils.views.corputils_search, name='auth_corputils_search_corp'),
# Timer URLS # Timer URLS
url(_(r'^timers/$'), 'timerboard.views.timer_view', name='auth_timer_view'), url(_(r'^timers/$'), timerboard.views.timer_view, name='auth_timer_view'),
url(_(r'^add_timer/$'), 'timerboard.views.add_timer_view', name='auth_add_timer_view'), url(_(r'^add_timer/$'), timerboard.views.add_timer_view, name='auth_add_timer_view'),
url(_(r'^remove_timer/(\w+)'), 'timerboard.views.remove_timer', name='auth_remove_timer'), url(_(r'^remove_timer/(\w+)'), timerboard.views.remove_timer, name='auth_remove_timer'),
url(_(r'^edit_timer/(\w+)$'), 'timerboard.views.edit_timer', name='auth_edit_timer'), url(_(r'^edit_timer/(\w+)$'), timerboard.views.edit_timer, name='auth_edit_timer'),
# Sig Tracker
url(_(r'^sigtracker/$'), 'sigtracker.views.sigtracker_view', name='auth_signature_view'),
url(_(r'^add_signature/$'), 'sigtracker.views.add_signature_view', name='auth_add_signature_view'),
url(_(r'^remove_signature/(\w+)'), 'sigtracker.views.remove_signature', name='auth_remove_signature'),
url(_(r'^edit_signature/(\w+)$'), 'sigtracker.views.edit_signature', name='auth_edit_signature'),
# SRP URLS # SRP URLS
url(_(r'^srp/$'), 'srp.views.srp_management', name='auth_srp_management_view'), url(_(r'^srp/$'), srp.views.srp_management, name='auth_srp_management_view'),
url(_(r'^srp_all/$'), 'srp.views.srp_management_all', name='auth_srp_management_all_view'), url(_(r'^srp_all/$'), srp.views.srp_management_all, name='auth_srp_management_all_view'),
url(_(r'^srp_fleet_view/(\w+)$'), 'srp.views.srp_fleet_view', name='auth_srp_fleet_view'), url(_(r'^srp_fleet_view/(\w+)$'), srp.views.srp_fleet_view, name='auth_srp_fleet_view'),
url(_(r'^srp_fleet_add_view/$'), 'srp.views.srp_fleet_add_view', name='auth_srp_fleet_add_view'), url(_(r'^srp_fleet_add_view/$'), srp.views.srp_fleet_add_view, name='auth_srp_fleet_add_view'),
url(_(r'^srp_fleet_edit/(\w+)$'), 'srp.views.srp_fleet_edit_view', name='auth_srp_fleet_edit_view'), url(_(r'^srp_fleet_edit/(\w+)$'), srp.views.srp_fleet_edit_view, name='auth_srp_fleet_edit_view'),
url(_(r'^srp_request/(\w+)'), 'srp.views.srp_request_view', name='auth_srp_request_view'), url(_(r'^srp_request/(\w+)'), srp.views.srp_request_view, name='auth_srp_request_view'),
url(_(r'srp_request_amount_update/(\w+)'), 'srp.views.srp_request_update_amount_view', url(_(r'srp_request_amount_update/(\w+)'), srp.views.srp_request_update_amount_view,
name="auth_srp_request_update_amount_view"), name="auth_srp_request_update_amount_view"),
# Tools # Tools
url(_(r'^tool/fleet_formatter_tool/$'), 'services.views.fleet_formatter_view', url(_(r'^tool/fleet_formatter_tool/$'), services.views.fleet_formatter_view,
name='auth_fleet_format_tool_view'), name='auth_fleet_format_tool_view'),
# Notifications # Notifications
url(_(r'^notifications/$'), 'notifications.views.notification_list', name='auth_notification_list'), url(_(r'^notifications/$'), notifications.views.notification_list, name='auth_notification_list'),
url(_(r'^notifications/(\w+)/$'), 'notifications.views.notification_view', name='auth_notification_view'), url(_(r'^notifications/(\w+)/$'), notifications.views.notification_view, name='auth_notification_view'),
# Jabber # Jabber
url(_(r'^set_jabber_password/$'), 'services.views.set_jabber_password', name='auth_set_jabber_password'), url(_(r'^set_jabber_password/$'), services.views.set_jabber_password, name='auth_set_jabber_password'),
# FLEET FITTINGS
url(_(r'^fits/$'), 'services.views.fleet_fits', name='auth_fleet_fits'),
# FleetActivityTracking (FAT) # FleetActivityTracking (FAT)
url(r'^fat/$', 'fleetactivitytracking.views.fatlink_view', name='auth_fatlink_view'), url(r'^fat/$', fleetactivitytracking.views.fatlink_view, name='auth_fatlink_view'),
url(r'^fat/statistics/$', 'fleetactivitytracking.views.fatlink_statistics_view', name='auth_fatlink_view_statistics'), url(r'^fat/statistics/$', fleetactivitytracking.views.fatlink_statistics_view, name='auth_fatlink_view_statistics'),
url(r'^fat/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', 'fleetactivitytracking.views.fatlink_statistics_view', name='auth_fatlink_view_statistics_month'), url(r'^fat/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', fleetactivitytracking.views.fatlink_statistics_view,
url(r'^fat/user/statistics/$', 'fleetactivitytracking.views.fatlink_personal_statistics_view', name='auth_fatlink_view_personal_statistics'), name='auth_fatlink_view_statistics_month'),
url(r'^fat/user/statistics/(?P<year>[0-9]+)/$', 'fleetactivitytracking.views.fatlink_personal_statistics_view', name='auth_fatlink_view_personal_statistics_year'), url(r'^fat/user/statistics/$', fleetactivitytracking.views.fatlink_personal_statistics_view,
url(r'^fat/user/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', 'fleetactivitytracking.views.fatlink_monthly_personal_statistics_view', name='auth_fatlink_view_personal_statistics'),
url(r'^fat/user/statistics/(?P<year>[0-9]+)/$', fleetactivitytracking.views.fatlink_personal_statistics_view,
name='auth_fatlink_view_personal_statistics_year'),
url(r'^fat/user/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$',
fleetactivitytracking.views.fatlink_monthly_personal_statistics_view,
name='auth_fatlink_view_personal_statistics_month'), name='auth_fatlink_view_personal_statistics_month'),
url(r'^fat/user/(?P<char_id>[0-9]+)/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$', 'fleetactivitytracking.views.fatlink_monthly_personal_statistics_view', url(r'^fat/user/(?P<char_id>[0-9]+)/statistics/(?P<year>[0-9]+)/(?P<month>[0-9]+)/$',
fleetactivitytracking.views.fatlink_monthly_personal_statistics_view,
name='auth_fatlink_view_user_statistics_month'), name='auth_fatlink_view_user_statistics_month'),
url(r'^fat/create/$', 'fleetactivitytracking.views.create_fatlink_view', name='auth_create_fatlink_view'), url(r'^fat/create/$', fleetactivitytracking.views.create_fatlink_view, name='auth_create_fatlink_view'),
url(r'^fat/modify/$', 'fleetactivitytracking.views.modify_fatlink_view', name='auth_modify_fatlink_view'), url(r'^fat/modify/$', fleetactivitytracking.views.modify_fatlink_view, name='auth_modify_fatlink_view'),
url(r'^fat/modify/(?P<hash>[a-zA-Z0-9_-]+)/([a-z0-9_-]+)$', url(r'^fat/modify/(?P<hash>[a-zA-Z0-9_-]+)/([a-z0-9_-]+)$',
'fleetactivitytracking.views.modify_fatlink_view'), fleetactivitytracking.views.modify_fatlink_view),
url(r'^fat/link/$', 'fleetactivitytracking.views.fatlink_view', name='auth_click_fatlink_view'), url(r'^fat/link/$', fleetactivitytracking.views.fatlink_view, name='auth_click_fatlink_view'),
url(r'^fat/link/(?P<hash>[a-zA-Z0-9]+)/(?P<fatname>[a-z0-9_-]+)/$', url(r'^fat/link/(?P<hash>[a-zA-Z0-9]+)/(?P<fatname>[a-z0-9_-]+)/$',
'fleetactivitytracking.views.click_fatlink_view'), fleetactivitytracking.views.click_fatlink_view),
) )

View File

@ -8,12 +8,11 @@ https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/
""" """
import os import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings")
from django.core.wsgi import get_wsgi_application # virtualenv wrapper, uncomment below to activate
# virtualenv wrapper
# activate_env=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'env/bin/activate_this.py') # activate_env=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'env/bin/activate_this.py')
# execfile(activate_env, dict(__file__=activate_env)) # execfile(activate_env, dict(__file__=activate_env))

View File

@ -0,0 +1,2 @@
from __future__ import unicode_literals
default_app_config = 'authentication.apps.AuthenticationConfig'

View File

@ -1,7 +1,146 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import AuthServicesInfo from authentication.models import AuthServicesInfo
from eveonline.models import EveCharacter
from services.tasks import update_jabber_groups
from services.tasks import update_mumble_groups
from services.tasks import update_forum_groups
from services.tasks import update_ipboard_groups
from services.tasks import update_smf_groups
from services.tasks import update_teamspeak3_groups
from services.tasks import update_discord_groups
from services.tasks import update_discord_nickname
from services.tasks import update_discourse_groups
# Register your models here. @admin.register(AuthServicesInfo)
admin.site.register(AuthServicesInfo) class AuthServicesInfoManager(admin.ModelAdmin):
@staticmethod
def main_character(obj):
if obj.main_char_id:
try:
return EveCharacter.objects.get(character_id=obj.main_char_id)
except EveCharacter.DoesNotExist:
pass
return None
def sync_jabber(self, request, queryset):
count = 0
for a in queryset: # queryset filtering doesn't work here?
if a.jabber_username != "":
update_jabber_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s jabber accounts queued for group sync." % count)
sync_jabber.short_description = "Sync groups for selected jabber accounts"
def sync_mumble(self, request, queryset):
count = 0
for a in queryset:
if a.mumble_username != "":
update_mumble_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s mumble accounts queued for group sync." % count)
sync_mumble.short_description = "Sync groups for selected mumble accounts"
def sync_forum(self, request, queryset):
count = 0
for a in queryset:
if a.forum_username != "":
update_forum_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s forum accounts queued for group sync." % count)
sync_forum.short_description = "Sync groups for selected forum accounts"
def sync_ipboard(self, request, queryset):
count = 0
for a in queryset:
if a.ipboard_username != "":
update_ipboard_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s ipboard accounts queued for group sync." % count)
sync_ipboard.short_description = "Sync groups for selected ipboard accounts"
def sync_smf(self, request, queryset):
count = 0
for a in queryset:
if a.smf_username != "":
update_smf_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s smf accounts queued for group sync." % count)
sync_smf.short_description = "Sync groups for selected smf accounts"
def sync_teamspeak(self, request, queryset):
count = 0
for a in queryset:
if a.teamspeak3_uid != "":
update_teamspeak3_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s teamspeak accounts queued for group sync." % count)
sync_teamspeak.short_description = "Sync groups for selected teamspeak accounts"
def sync_discord(self, request, queryset):
count = 0
for a in queryset:
if a.discord_uid != "":
update_discord_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s discord accounts queued for group sync." % count)
sync_discord.short_description = "Sync groups for selected discord accounts"
def sync_discourse(self, request, queryset):
count = 0
for a in queryset:
if a.discourse_username != "":
update_discourse_groups.delay(a.user.pk)
count += 1
self.message_user(request, "%s discourse accounts queued for group sync." % count)
sync_discourse.short_description = "Sync groups for selected discourse accounts"
def sync_nicknames(self, request, queryset):
count = 0
for a in queryset:
if a.discord_uid != "":
update_discord_nickname(a.user.pk)
count += 1
self.message_user(request, "%s discord accounts queued for nickname sync." % count)
sync_nicknames.short_description = "Sync nicknames for selected discord accounts"
actions = [
'sync_jabber',
'sync_mumble',
'sync_forum',
'sync_ipboard',
'sync_smf',
'sync_teamspeak',
'sync_discord',
'sync_discourse',
'sync_nicknames',
]
search_fields = [
'user__username',
'ipboard_username',
'xenforo_username',
'forum_username',
'jabber_username',
'mumble_username',
'teamspeak3_uid',
'discord_uid',
'discourse_username',
'ips4_username',
'smf_username',
'market_username',
'main_char_id',
]
list_display = ('user', 'main_character')

10
authentication/apps.py Normal file
View File

@ -0,0 +1,10 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class AuthenticationConfig(AppConfig):
name = 'authentication'
def ready(self):
import authentication.signals

View File

@ -0,0 +1,25 @@
from __future__ import unicode_literals
from authentication.models import AuthServicesInfo
from authentication.states import NONE_STATE, BLUE_STATE, MEMBER_STATE
from django.conf import settings
def membership_state(request):
if request.user.is_authenticated:
auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
return {'STATE': auth.state}
return {'STATE': NONE_STATE}
def states(request):
return {
'BLUE_STATE': BLUE_STATE,
'MEMBER_STATE': MEMBER_STATE,
'NONE_STATE': NONE_STATE,
'MEMBER_BLUE_STATE': [MEMBER_STATE, BLUE_STATE],
}
def sso(request):
return {
'EVE_SSO_CALLBACK_URL': settings.EVE_SSO_CALLBACK_URL,
}

View File

@ -0,0 +1,33 @@
from __future__ import unicode_literals
from django.contrib.auth.decorators import user_passes_test
from authentication.models import AuthServicesInfo
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
from django.conf import settings
def _state_required(states, *args, **kwargs):
def test_func(user):
if user.is_superuser and settings.SUPERUSER_STATE_BYPASS:
return True
if user.is_authenticated:
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
return auth.state in states
return False
return user_passes_test(test_func, *args, **kwargs)
def members(*args, **kwargs):
return _state_required([MEMBER_STATE], *args, **kwargs)
def blues(*args, **kwargs):
return _state_required([BLUE_STATE], *args, **kwargs)
def members_and_blues(*args, **kwargs):
return _state_required([MEMBER_STATE, BLUE_STATE], *args, **kwargs)
def none_state(*args, **kwargs):
return _state_required([NONE_STATE], *args, **kwargs)

View File

@ -1,7 +1,42 @@
from __future__ import unicode_literals
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
import re
class LoginForm(forms.Form): class LoginForm(forms.Form):
username = forms.CharField(label=_('Username'), max_length=32, required=True) username = forms.CharField(label=_('Username'), max_length=32, required=True)
password = forms.CharField(label=_('Password'), widget=forms.PasswordInput()) password = forms.CharField(label=_('Password'), widget=forms.PasswordInput())
class RegistrationForm(forms.Form):
username = forms.CharField(label=_('Username'), max_length=30, required=True)
password = forms.CharField(label=_('Password'), widget=forms.PasswordInput(), required=True)
password_again = forms.CharField(label=_('Password Again'), widget=forms.PasswordInput(), required=True)
email = forms.CharField(label=_('Email'), max_length=254, required=True)
email_again = forms.CharField(label=_('Email Again'), max_length=254, required=True)
def clean(self):
if ' ' in self.cleaned_data['username']:
raise forms.ValidationError('Username cannot contain a space')
# We attempt to get the user object if we succeed we know email as been used
try:
User.objects.get(email=self.cleaned_data['email'])
raise forms.ValidationError('Email as already been used')
except User.DoesNotExist:
pass
if not re.match("^\w+$", self.cleaned_data['username']):
raise forms.ValidationError('Username contains illegal characters')
if 'password' in self.cleaned_data and 'password_again' in self.cleaned_data:
if self.cleaned_data['password'] != self.cleaned_data['password_again']:
raise forms.ValidationError('Passwords do not match')
if 'email' in self.cleaned_data and 'email_again' in self.cleaned_data:
if self.cleaned_data['email'] != self.cleaned_data['email_again']:
raise forms.ValidationError('Emails do not match')
return self.cleaned_data

View File

@ -1,40 +1,22 @@
from __future__ import unicode_literals
from django.contrib.auth.models import User from django.contrib.auth.models import User
from models import AuthServicesInfo from authentication.models import AuthServicesInfo
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AuthServicesInfoManager: class AuthServicesInfoManager:
def __init__(self): def __init__(self):
pass pass
@staticmethod @staticmethod
def __get_or_create(user): def update_main_char_id(char_id, user):
if AuthServicesInfo.objects.filter(user=user).exists():
logger.debug("Returning existing authservicesinfo model for user %s" % user)
return AuthServicesInfo.objects.get(user=user)
else:
# We have to create
logger.info("Creating new authservicesinfo model for user %s" % user)
authserviceinfo = AuthServicesInfo()
authserviceinfo.user = user
authserviceinfo.save()
return authserviceinfo
@staticmethod
def get_auth_service_info(user):
if User.objects.filter(username=user.username).exists():
return AuthServicesInfoManager.__get_or_create(user)
logger.error("Failed to get authservicesinfo object for user %s: user does not exist." % user)
return None
@staticmethod
def update_main_char_Id(char_id, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s main character to id %s" % (user, char_id)) logger.debug("Updating user %s main character to id %s" % (user, char_id))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.main_char_id = char_id authserviceinfo.main_char_id = char_id
authserviceinfo.save(update_fields=['main_char_id']) authserviceinfo.save(update_fields=['main_char_id'])
logger.info("Updated user %s main character to id %s" % (user, char_id)) logger.info("Updated user %s main character to id %s" % (user, char_id))
@ -42,62 +24,56 @@ class AuthServicesInfoManager:
logger.error("Failed to update user %s main character id to %s: user does not exist." % (user, char_id)) logger.error("Failed to update user %s main character id to %s: user does not exist." % (user, char_id))
@staticmethod @staticmethod
def update_user_forum_info(username, password, user): def update_user_forum_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s forum info: username %s" % (user, username)) logger.debug("Updating user %s forum info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.forum_username = username authserviceinfo.forum_username = username
authserviceinfo.forum_password = password authserviceinfo.save(update_fields=['forum_username'])
authserviceinfo.save(update_fields=['forum_username', 'forum_password'])
logger.info("Updated user %s forum info in authservicesinfo model." % user) logger.info("Updated user %s forum info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s forum info: user does not exist." % user) logger.error("Failed to update user %s forum info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_jabber_info(username, password, user): def update_user_jabber_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s jabber info: username %s" % (user, username)) logger.debug("Updating user %s jabber info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.jabber_username = username authserviceinfo.jabber_username = username
authserviceinfo.jabber_password = password authserviceinfo.save(update_fields=['jabber_username'])
authserviceinfo.save(update_fields=['jabber_username', 'jabber_password'])
logger.info("Updated user %s jabber info in authservicesinfo model." % user) logger.info("Updated user %s jabber info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s jabber info: user does not exist." % user) logger.error("Failed to update user %s jabber info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_mumble_info(username, password, user): def update_user_mumble_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s mumble info: username %s" % (user, username)) logger.debug("Updating user %s mumble info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.mumble_username = username authserviceinfo.mumble_username = username
authserviceinfo.mumble_password = password authserviceinfo.save(update_fields=['mumble_username'])
authserviceinfo.save(update_fields=['mumble_username', 'mumble_password'])
logger.info("Updated user %s mumble info in authservicesinfo model." % user) logger.info("Updated user %s mumble info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s mumble info: user does not exist." % user) logger.error("Failed to update user %s mumble info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_ipboard_info(username, password, user): def update_user_ipboard_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s ipboard info: uername %s" % (user, username)) logger.debug("Updating user %s ipboard info: uername %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.ipboard_username = username authserviceinfo.ipboard_username = username
authserviceinfo.ipboard_password = password authserviceinfo.save(update_fields=['ipboard_username'])
authserviceinfo.save(update_fields=['ipboard_username', 'ipboard_password'])
logger.info("Updated user %s ipboard info in authservicesinfo model." % user) logger.info("Updated user %s ipboard info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s ipboard info: user does not exist." % user) logger.error("Failed to update user %s ipboard info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_xenforo_info(username, password, user): def update_user_xenforo_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s xenforo info: uername %s" % (user, username)) logger.debug("Updating user %s xenforo info: uername %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.xenforo_username = username authserviceinfo.xenforo_username = username
authserviceinfo.xenforo_password = password authserviceinfo.save(update_fields=['xenforo_username'])
authserviceinfo.save(update_fields=['xenforo_username', 'xenforo_password'])
logger.info("Updated user %s xenforo info in authservicesinfo model." % user) logger.info("Updated user %s xenforo info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s xenforo info: user does not exist." % user) logger.error("Failed to update user %s xenforo info: user does not exist." % user)
@ -106,7 +82,7 @@ class AuthServicesInfoManager:
def update_user_teamspeak3_info(uid, perm_key, user): def update_user_teamspeak3_info(uid, perm_key, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s teamspeak3 info: uid %s" % (user, uid)) logger.debug("Updating user %s teamspeak3 info: uid %s" % (user, uid))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.teamspeak3_uid = uid authserviceinfo.teamspeak3_uid = uid
authserviceinfo.teamspeak3_perm_key = perm_key authserviceinfo.teamspeak3_perm_key = perm_key
authserviceinfo.save(update_fields=['teamspeak3_uid', 'teamspeak3_perm_key']) authserviceinfo.save(update_fields=['teamspeak3_uid', 'teamspeak3_perm_key'])
@ -118,7 +94,7 @@ class AuthServicesInfoManager:
def update_is_blue(is_blue, user): def update_is_blue(is_blue, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s blue status: %s" % (user, is_blue)) logger.debug("Updating user %s blue status: %s" % (user, is_blue))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.is_blue = is_blue authserviceinfo.is_blue = is_blue
authserviceinfo.save(update_fields=['is_blue']) authserviceinfo.save(update_fields=['is_blue'])
logger.info("Updated user %s blue status to %s in authservicesinfo model." % (user, is_blue)) logger.info("Updated user %s blue status to %s in authservicesinfo model." % (user, is_blue))
@ -127,7 +103,7 @@ class AuthServicesInfoManager:
def update_user_discord_info(user_id, user): def update_user_discord_info(user_id, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s discord info: user_id %s" % (user, user_id)) logger.debug("Updating user %s discord info: user_id %s" % (user, user_id))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.discord_uid = user_id authserviceinfo.discord_uid = user_id
authserviceinfo.save(update_fields=['discord_uid']) authserviceinfo.save(update_fields=['discord_uid'])
logger.info("Updated user %s discord info in authservicesinfo model." % user) logger.info("Updated user %s discord info in authservicesinfo model." % user)
@ -135,62 +111,46 @@ class AuthServicesInfoManager:
logger.error("Failed to update user %s discord info: user does not exist." % user) logger.error("Failed to update user %s discord info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_discourse_info(username, password, user): def update_user_discourse_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s discourse info: username %s" % (user, username)) logger.debug("Updating user %s discourse info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.discourse_username = username authserviceinfo.discourse_username = username
authserviceinfo.discourse_password = password authserviceinfo.save(update_fields=['discourse_username'])
authserviceinfo.save(update_fields=['discourse_username', 'discourse_password'])
logger.info("Updated user %s discourse info in authservicesinfo model." % user) logger.info("Updated user %s discourse info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s discourse info: user does not exist." % user) logger.error("Failed to update user %s discourse info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_ips4_info(username, password, id, user): def update_user_ips4_info(username, id, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s IPS4 info: username %s" % (user, username)) logger.debug("Updating user %s IPS4 info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.ips4_username = username authserviceinfo.ips4_username = username
authserviceinfo.ips4_password = password
authserviceinfo.ips4_id = id authserviceinfo.ips4_id = id
authserviceinfo.save(update_fields=['ips4_username', 'ips4_password', 'ips4_id']) authserviceinfo.save(update_fields=['ips4_username', 'ips4_id'])
logger.info("Updated user %s IPS4 info in authservicesinfo model." % user) logger.info("Updated user %s IPS4 info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s IPS4 info: user does not exist." % user) logger.error("Failed to update user %s IPS4 info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_smf_info(username, password, user): def update_user_smf_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s forum info: username %s" % (user, username)) logger.debug("Updating user %s forum info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.smf_username = username authserviceinfo.smf_username = username
authserviceinfo.smf_password = password authserviceinfo.save(update_fields=['smf_username'])
authserviceinfo.save(update_fields=['smf_username', 'smf_password'])
logger.info("Updated user %s smf info in authservicesinfo model." % user) logger.info("Updated user %s smf info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s smf info: user does not exist." % user) logger.error("Failed to update user %s smf info: user does not exist." % user)
@staticmethod @staticmethod
def update_user_market_info(username, password, user): def update_user_market_info(username, user):
if User.objects.filter(username=user.username).exists(): if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s market info: username %s" % (user, username)) logger.debug("Updating user %s market info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user) authserviceinfo = AuthServicesInfo.objects.get_or_create(user=user)[0]
authserviceinfo.market_username = username authserviceinfo.market_username = username
authserviceinfo.market_password = password authserviceinfo.save(update_fields=['market_username'])
authserviceinfo.save(update_fields=['market_username', 'market_password'])
logger.info("Updated user %s market info in authservicesinfo model." % user) logger.info("Updated user %s market info in authservicesinfo model." % user)
else: else:
logger.error("Failed to update user %s market info: user does not exist." % user) logger.error("Failed to update user %s market info: user does not exist." % user)
@staticmethod
def update_user_pathfinder_info(username, password, user):
if User.objects.filter(username=user.username).exists():
logger.debug("Updating user %s market info: username %s" % (user, username))
authserviceinfo = AuthServicesInfoManager.__get_or_create(user)
authserviceinfo.pathfinder_username = username
authserviceinfo.pathfinder_password = password
authserviceinfo.save(update_fields=['pathfinder_username', 'pathfinder_password'])
logger.info("Updated user %s pathfinder info in authservicesinfo model." % user)
else:
logger.error("Failed to update user %s pathfinder info: user does not exist." % user)

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:38
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='AuthServicesInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ipboard_username', models.CharField(blank=True, default=b'', max_length=254)),
('ipboard_password', models.CharField(blank=True, default=b'', max_length=254)),
('xenforo_username', models.CharField(blank=True, default=b'', max_length=254)),
('xenforo_password', models.CharField(blank=True, default=b'', max_length=254)),
('forum_username', models.CharField(blank=True, default=b'', max_length=254)),
('forum_password', models.CharField(blank=True, default=b'', max_length=254)),
('jabber_username', models.CharField(blank=True, default=b'', max_length=254)),
('jabber_password', models.CharField(blank=True, default=b'', max_length=254)),
('mumble_username', models.CharField(blank=True, default=b'', max_length=254)),
('mumble_password', models.CharField(blank=True, default=b'', max_length=254)),
('teamspeak3_uid', models.CharField(blank=True, default=b'', max_length=254)),
('teamspeak3_perm_key', models.CharField(blank=True, default=b'', max_length=254)),
('discord_uid', models.CharField(blank=True, default=b'', max_length=254)),
('discourse_username', models.CharField(blank=True, default=b'', max_length=254)),
('discourse_password', models.CharField(blank=True, default=b'', max_length=254)),
('ips4_username', models.CharField(blank=True, default=b'', max_length=254)),
('ips4_password', models.CharField(blank=True, default=b'', max_length=254)),
('ips4_id', models.CharField(blank=True, default=b'', max_length=254)),
('smf_username', models.CharField(blank=True, default=b'', max_length=254)),
('smf_password', models.CharField(blank=True, default=b'', max_length=254)),
('market_username', models.CharField(blank=True, default=b'', max_length=254)),
('market_password', models.CharField(blank=True, default=b'', max_length=254)),
('pathfinder_username', models.CharField(blank=True, default=b'', max_length=254)),
('pathfinder_password', models.CharField(blank=True, default=b'', max_length=254)),
('main_char_id', models.CharField(blank=True, default=b'', max_length=64)),
('is_blue', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-07 19:14
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('authentication', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='authservicesinfo',
name='pathfinder_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='pathfinder_username',
),
]

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-09 20:29
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0002_auto_20160907_1914'),
]
operations = [
migrations.AddField(
model_name='authservicesinfo',
name='state',
field=models.CharField(blank=True, choices=[(None, b'None'), (b'Blue', b'Blue'), (b'Member', b'Member')], default=None, max_length=10, null=True),
),
]

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-09 23:19
from __future__ import unicode_literals
from django.db import migrations
def create_permissions(apps, schema_editor):
User = apps.get_model('auth', 'User')
ContentType = apps.get_model('contenttypes', 'ContentType')
Permission = apps.get_model('auth', 'Permission')
ct = ContentType.objects.get_for_model(User)
Permission.objects.get_or_create(codename="member", content_type=ct, name="member")
Permission.objects.get_or_create(codename="group_management", content_type=ct, name="group_management")
Permission.objects.get_or_create(codename="jabber_broadcast", content_type=ct, name="jabber_broadcast")
Permission.objects.get_or_create(codename="jabber_broadcast_all", content_type=ct, name="jabber_broadcast_all")
Permission.objects.get_or_create(codename="fleetactivitytracking", content_type=ct, name="fleetactivitytracking")
Permission.objects.get_or_create(codename="fleetactivitytracking_statistics", content_type=ct, name="fleetactivitytracking_statistics")
Permission.objects.get_or_create(codename="human_resources", content_type=ct, name="human_resources")
Permission.objects.get_or_create(codename="blue_member", content_type=ct, name="blue_member")
Permission.objects.get_or_create(codename="alliance_apis", content_type=ct, name="alliance_apis")
Permission.objects.get_or_create(codename="corp_apis", content_type=ct, name="corp_apis")
Permission.objects.get_or_create(codename="timer_management", content_type=ct, name="timer_management")
Permission.objects.get_or_create(codename="timer_view", content_type=ct, name="timer_view")
Permission.objects.get_or_create(codename="srp_management", content_type=ct, name="srp_management")
Permission.objects.get_or_create(codename="signature_management", content_type=ct, name="signature_management")
Permission.objects.get_or_create(codename="signature_view", content_type=ct, name="signature_view")
Permission.objects.get_or_create(codename="optimer_management", content_type=ct, name="optimer_management")
Permission.objects.get_or_create(codename="optimer_view", content_type=ct, name="optimer_view")
Permission.objects.get_or_create(codename="logging_notifications", content_type=ct, name="logging_notifications")
def reverse(apps, schema_editor):
#too lazy
pass
class Migration(migrations.Migration):
dependencies = [
('authentication', '0003_authservicesinfo_state'),
]
operations = [
migrations.RunPython(create_permissions, reverse)
]

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-09 23:11
from __future__ import unicode_literals
from django.db import migrations
def delete_permissions(apps, schema_editor):
User = apps.get_model('auth', 'User')
ContentType = apps.get_model('contenttypes', 'ContentType')
Permission = apps.get_model('auth', 'Permission')
ct = ContentType.objects.get_for_model(User)
Permission.objects.filter(content_type=ct).filter(codename__in=['member', 'blue_member', 'signature_management', 'signature_view']).delete()
def create_permissions(apps, schema_editor):
User = apps.get_model('auth', 'User')
ContentType = apps.get_model('contenttypes', 'ContentType')
Permission = apps.get_model('auth', 'Permission')
ct = ContentType.objects.get_for_model(User)
Permission.objects.get_or_create(codename="member", content_type=ct, name="member")
Permission.objects.get_or_create(codename="blue_member", content_type=ct, name="blue_member")
class Migration(migrations.Migration):
dependencies = [
('authentication', '0004_create_permissions'),
]
operations = [
migrations.RunPython(delete_permissions, create_permissions),
]

View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-10 05:42
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('authentication', '0005_delete_perms'),
]
operations = [
migrations.RemoveField(
model_name='authservicesinfo',
name='discourse_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='forum_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='ipboard_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='ips4_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='jabber_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='market_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='mumble_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='smf_password',
),
migrations.RemoveField(
model_name='authservicesinfo',
name='xenforo_password',
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-10 21:50
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('authentication', '0006_auto_20160910_0542'),
]
operations = [
migrations.RemoveField(
model_name='authservicesinfo',
name='is_blue',
),
]

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-12 13:04
from __future__ import unicode_literals
from django.db import migrations
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
from django.conf import settings
def determine_membership_by_character(char, apps):
if settings.IS_CORP:
if int(char.corporation_id) == int(settings.CORP_ID):
return MEMBER_STATE
else:
if int(char.alliance_id) == int(settings.ALLIANCE_ID):
return MEMBER_STATE
EveCorporationInfo = apps.get_model('eveonline', 'EveCorporationInfo')
if EveCorporationInfo.objects.filter(corporation_id=char.corporation_id).exists() is False:
return NONE_STATE
else:
corp = EveCorporationInfo.objects.get(corporation_id=char.corporation_id)
if corp.is_blue:
return BLUE_STATE
else:
return NONE_STATE
def determine_membership_by_user(user, apps):
AuthServicesInfo = apps.get_model('authentication', 'AuthServicesInfo')
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.main_char_id:
EveCharacter = apps.get_model('eveonline', 'EveCharacter')
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
return determine_membership_by_character(char, apps)
else:
return NONE_STATE
else:
return NONE_STATE
def set_state(user, apps):
if user.is_active:
state = determine_membership_by_user(user, apps)
else:
state = NONE_STATE
AuthServicesInfo = apps.get_model('authentication', 'AuthServicesInfo')
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
if auth.state != state:
auth.state = state
auth.save()
def set_initial_state(apps, schema_editor):
User = apps.get_model('auth', 'User')
for u in User.objects.all():
set_state(u, apps)
class Migration(migrations.Migration):
dependencies = [
('authentication', '0007_remove_authservicesinfo_is_blue'),
('eveonline', '0001_initial'),
('auth', '0001_initial'),
]
operations = [
migrations.RunPython(set_initial_state, migrations.RunPython.noop)
]

View File

@ -1,35 +1,34 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
@python_2_unicode_compatible
class AuthServicesInfo(models.Model): class AuthServicesInfo(models.Model):
STATE_CHOICES = (
(NONE_STATE, 'None'),
(BLUE_STATE, 'Blue'),
(MEMBER_STATE, 'Member'),
)
ipboard_username = models.CharField(max_length=254, blank=True, default="") ipboard_username = models.CharField(max_length=254, blank=True, default="")
ipboard_password = models.CharField(max_length=254, blank=True, default="")
xenforo_username = models.CharField(max_length=254, blank=True, default="") xenforo_username = models.CharField(max_length=254, blank=True, default="")
xenforo_password = models.CharField(max_length=254, blank=True, default="")
forum_username = models.CharField(max_length=254, blank=True, default="") forum_username = models.CharField(max_length=254, blank=True, default="")
forum_password = models.CharField(max_length=254, blank=True, default="")
jabber_username = models.CharField(max_length=254, blank=True, default="") jabber_username = models.CharField(max_length=254, blank=True, default="")
jabber_password = models.CharField(max_length=254, blank=True, default="")
mumble_username = models.CharField(max_length=254, blank=True, default="") mumble_username = models.CharField(max_length=254, blank=True, default="")
mumble_password = models.CharField(max_length=254, blank=True, default="")
teamspeak3_uid = models.CharField(max_length=254, blank=True, default="") teamspeak3_uid = models.CharField(max_length=254, blank=True, default="")
teamspeak3_perm_key = models.CharField(max_length=254, blank=True, default="") teamspeak3_perm_key = models.CharField(max_length=254, blank=True, default="")
discord_uid = models.CharField(max_length=254, blank=True, default="") discord_uid = models.CharField(max_length=254, blank=True, default="")
discourse_username = models.CharField(max_length=254, blank=True, default="") discourse_username = models.CharField(max_length=254, blank=True, default="")
discourse_password = models.CharField(max_length=254, blank=True, default="")
ips4_username = models.CharField(max_length=254, blank=True, default="") ips4_username = models.CharField(max_length=254, blank=True, default="")
ips4_password = models.CharField(max_length=254, blank=True, default="")
ips4_id = models.CharField(max_length=254, blank=True, default="") ips4_id = models.CharField(max_length=254, blank=True, default="")
smf_username = models.CharField(max_length=254, blank=True, default="") smf_username = models.CharField(max_length=254, blank=True, default="")
smf_password = models.CharField(max_length=254, blank=True, default="")
market_username = models.CharField(max_length=254, blank=True, default="") market_username = models.CharField(max_length=254, blank=True, default="")
market_password = models.CharField(max_length=254, blank=True, default="")
pathfinder_username = models.CharField(max_length=254, blank=True, default="")
pathfinder_password = models.CharField(max_length=254, blank=True, default="")
main_char_id = models.CharField(max_length=64, blank=True, default="") main_char_id = models.CharField(max_length=64, blank=True, default="")
is_blue = models.BooleanField(default=False)
user = models.ForeignKey(User) user = models.ForeignKey(User)
state = models.CharField(blank=True, null=True, choices=STATE_CHOICES, default=NONE_STATE, max_length=10)
def __str__(self): def __str__(self):
return self.user.username + ' - AuthInfo' return self.user.username + ' - AuthInfo'

25
authentication/signals.py Normal file
View File

@ -0,0 +1,25 @@
from __future__ import unicode_literals
from django.db.models.signals import pre_save
from django.dispatch import receiver
from authentication.models import AuthServicesInfo
from authentication.states import MEMBER_STATE, BLUE_STATE
from authentication.tasks import make_member, make_blue, disable_member
from services.tasks import validate_services
import logging
logger = logging.getLogger(__name__)
@receiver(pre_save, sender=AuthServicesInfo)
def pre_save_auth_state(sender, instance, *args, **kwargs):
if instance.pk:
old_instance = AuthServicesInfo.objects.get(pk=instance.pk)
if old_instance.state != instance.state:
logger.debug('Detected state change for %s' % instance.user)
if instance.state == MEMBER_STATE:
make_member(instance)
elif instance.state == BLUE_STATE:
make_blue(instance)
else:
disable_member(instance.user)
validate_services(instance.user, instance.state)

4
authentication/states.py Normal file
View File

@ -0,0 +1,4 @@
from __future__ import unicode_literals
MEMBER_STATE = 'Member'
BLUE_STATE = 'Blue'
NONE_STATE = None

168
authentication/tasks.py Normal file
View File

@ -0,0 +1,168 @@
from __future__ import unicode_literals
from services.tasks import validate_services
from django.contrib.auth.models import Group
from authentication.models import AuthServicesInfo
from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE
from eveonline.models import EveCharacter, EveCorporationInfo
from notifications import notify
from django.conf import settings
import logging
logger = logging.getLogger(__name__)
def generate_corp_group_name(corpname):
return 'Corp_' + corpname.replace(' ', '_')
def generate_alliance_group_name(alliancename):
return 'Alliance_' + alliancename.replace(' ', '_')
def disable_member(user):
logger.debug("Disabling member %s" % user)
if user.user_permissions.all().exists():
logger.info("Clearning user %s permission to deactivate user." % user)
user.user_permissions.clear()
if user.groups.all().exists():
logger.info("Clearing user %s groups to deactivate user." % user)
user.groups.clear()
validate_services(user, None)
def make_member(auth):
logger.debug("Ensuring user %s has member permissions and groups." % auth.user)
# ensure member is not blue right now
blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP)
if blue_group in auth.user.groups.all():
logger.info("Removing user %s blue group" % auth.user)
auth.user.groups.remove(blue_group)
# make member
member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP)
if member_group not in auth.user.groups.all():
logger.info("Adding user %s to member group" % auth.user)
auth.user.groups.add(member_group)
assign_corp_group(auth)
assign_alliance_group(auth)
def make_blue(auth):
logger.debug("Ensuring user %s has blue permissions and groups." % auth.user)
# ensure user is not a member
member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP)
if member_group in auth.user.groups.all():
logger.info("Removing user %s member group" % auth.user)
auth.user.groups.remove(member_group)
# make blue
blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP)
if blue_group not in auth.user.groups.all():
logger.info("Adding user %s to blue group" % auth.user)
auth.user.groups.add(blue_group)
assign_corp_group(auth)
assign_alliance_group(auth)
def determine_membership_by_character(char):
if settings.IS_CORP:
if int(char.corporation_id) == int(settings.CORP_ID):
logger.debug("Character %s in owning corp id %s" % (char, char.corporation_id))
return MEMBER_STATE
else:
if int(char.alliance_id) == int(settings.ALLIANCE_ID):
logger.debug("Character %s in owning alliance id %s" % (char, char.alliance_id))
return MEMBER_STATE
if EveCorporationInfo.objects.filter(corporation_id=char.corporation_id).exists() is False:
logger.debug("No corp model for character %s corp id %s. Unable to check standings. Non-member." % (
char, char.corporation_id))
return NONE_STATE
else:
corp = EveCorporationInfo.objects.get(corporation_id=char.corporation_id)
if corp.is_blue:
logger.debug("Character %s member of blue corp %s" % (char, corp))
return BLUE_STATE
else:
logger.debug("Character %s member of non-blue corp %s. Non-member." % (char, corp))
return NONE_STATE
def determine_membership_by_user(user):
logger.debug("Determining membership of user %s" % user)
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
return determine_membership_by_character(char)
else:
logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (
user, auth.main_char_id))
return NONE_STATE
else:
logger.debug("User %s has no main character set. Non-member." % user)
return NONE_STATE
def set_state(user):
if user.is_active:
state = determine_membership_by_user(user)
else:
state = NONE_STATE
logger.debug("Assigning user %s to state %s" % (user, state))
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
if auth.state != state:
auth.state = state
auth.save()
notify(user, "Membership State Change", message="You membership state has been changed to %s" % state)
def assign_corp_group(auth):
corp_group = None
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
corpname = generate_corp_group_name(char.corporation_name)
if auth.state == BLUE_STATE and settings.BLUE_CORP_GROUPS:
logger.debug("Validating blue user %s has corp group assigned." % auth.user)
corp_group, c = Group.objects.get_or_create(name=corpname)
elif auth.state == MEMBER_STATE and settings.MEMBER_CORP_GROUPS:
logger.debug("Validating member %s has corp group assigned." % auth.user)
corp_group, c = Group.objects.get_or_create(name=corpname)
else:
logger.debug("Ensuring %s has no corp groups assigned." % auth.user)
if corp_group:
if corp_group not in auth.user.groups.all():
logger.info("Adding user %s to corp group %s" % (auth.user, corp_group))
auth.user.groups.add(corp_group)
for g in auth.user.groups.all():
if str.startswith(str(g.name), "Corp_"):
if g != corp_group:
logger.info("Removing user %s from old corpgroup %s" % (auth.user, g))
auth.user.groups.remove(g)
def assign_alliance_group(auth):
alliance_group = None
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
if char.alliance_name:
alliancename = generate_alliance_group_name(char.alliance_name)
if auth.state == BLUE_STATE and settings.BLUE_ALLIANCE_GROUPS:
logger.debug("Validating blue user %s has alliance group assigned." % auth.user)
alliance_group, c = Group.objects.get_or_create(name=alliancename)
elif auth.state == MEMBER_STATE and settings.MEMBER_ALLIANCE_GROUPS:
logger.debug("Validating member %s has alliance group assigned." % auth.user)
alliance_group, c = Group.objects.get_or_create(name=alliancename)
else:
logger.debug("Ensuring %s has no alliance groups assigned." % auth.user)
else:
logger.debug("User %s main character %s not in an alliance. Ensuring no alliance group assigned." % (
auth.user, char))
if alliance_group:
if alliance_group not in auth.user.groups.all():
logger.info("Adding user %s to alliance group %s" % (auth.user, alliance_group))
auth.user.groups.add(alliance_group)
for g in auth.user.groups.all():
if str.startswith(str(g.name), "Alliance_"):
if g != alliance_group:
logger.info("Removing user %s from old alliance group %s" % (auth.user, g))
auth.user.groups.remove(g)

View File

@ -1,17 +1,21 @@
from __future__ import unicode_literals
from django.contrib.auth import login from django.contrib.auth import login
from django.contrib.auth import logout from django.contrib.auth import logout
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.http import HttpResponseRedirect from django.shortcuts import render, redirect
from django.shortcuts import render_to_response from django.contrib.auth.decorators import login_required
from django.template import RequestContext from eveonline.managers import EveManager
from django.utils import translation from eveonline.models import EveCharacter
from authentication.models import AuthServicesInfo
from forms import LoginForm from authentication.forms import LoginForm, RegistrationForm
from django.contrib.auth.models import User
from django.contrib import messages
from eve_sso.decorators import token_required
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def login_user(request): def login_user(request):
logger.debug("login_user called by user %s" % request.user) logger.debug("login_user called by user %s" % request.user)
if request.method == 'POST': if request.method == 'POST':
@ -24,24 +28,89 @@ def login_user(request):
if user.is_active: if user.is_active:
logger.info("Successful login attempt from user %s" % user) logger.info("Successful login attempt from user %s" % user)
login(request, user) login(request, user)
return HttpResponseRedirect("/dashboard/") return redirect("auth_dashboard")
else: else:
logger.info("Login attempt failed for user %s: user marked inactive." % user) logger.info("Login attempt failed for user %s: user marked inactive." % user)
messages.warning(request, 'Your account has been disabled.')
else: else:
logger.info("Failed login attempt: provided username %s" % form.cleaned_data['username']) logger.info("Failed login attempt: provided username %s" % form.cleaned_data['username'])
messages.error(request, 'Username/password invalid.')
return render_to_response('public/login.html', {'form': form, 'error': True}, return render(request, 'public/login.html', context={'form': form})
context_instance=RequestContext(request))
else: else:
logger.debug("Providing new login form.") logger.debug("Providing new login form.")
form = LoginForm() form = LoginForm()
return render_to_response('public/login.html', {'form': form}, context_instance=RequestContext(request)) return render(request, 'public/login.html', context={'form': form})
def logout_user(request): def logout_user(request):
logger.debug("logout_user called by user %s" % request.user) logger.debug("logout_user called by user %s" % request.user)
logoutUser = request.user temp_user = request.user
logout(request) logout(request)
logger.info("Successful logout for user %s" % logoutUser) logger.info("Successful logout for user %s" % temp_user)
return HttpResponseRedirect("/") return redirect("auth_index")
def register_user_view(request):
logger.debug("register_user_view called by user %s" % request.user)
if request.method == 'POST':
form = RegistrationForm(request.POST)
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
if not User.objects.filter(username=form.cleaned_data['username']).exists():
user = User.objects.create_user(form.cleaned_data['username'],
form.cleaned_data['email'], form.cleaned_data['password'])
user.save()
logger.info("Created new user %s" % user)
messages.warning(request, 'Add an API key to set up your account.')
return redirect("auth_dashboard")
else:
logger.error("Unable to register new user: username %s already exists." % form.cleaned_data['username'])
return render(request, 'public/register.html', context={'form': form, 'error': True})
else:
logger.debug("Registration form invalid. Returning for user %s to make corrections." % request.user)
else:
logger.debug("Returning blank registration form.")
form = RegistrationForm()
return render(request, 'public/register.html', context={'form': form})
def index_view(request):
logger.debug("index_view called by user %s" % request.user)
return render(request, 'public/index.html')
@login_required
def dashboard_view(request):
logger.debug("dashboard_view called by user %s" % request.user)
render_items = {'characters': EveManager.get_characters_by_owner_id(request.user.id),
'authinfo': AuthServicesInfo.objects.get_or_create(user=request.user)[0]}
return render(request, 'registered/dashboard.html', context=render_items)
@login_required
def help_view(request):
logger.debug("help_view called by user %s" % request.user)
return render(request, 'registered/help.html')
@token_required(new=True)
def sso_login(request, tokens=[]):
token = tokens[0]
try:
char = EveCharacter.objects.get(character_id=token.character_id)
if char.user:
if char.user.is_active:
login(request, char.user)
return redirect(dashboard_view)
else:
messages.error(request, 'Your account has been disabled.')
else:
messages.warning(request, 'Authenticated character has no owning account. Please log in with username and password.')
except EveCharacter.DoesNotExist:
messages.error(request, 'No account exists with the authenticated character. Please create an account first.')
return redirect(login_user)

View File

@ -1 +0,0 @@
import signals

View File

@ -1,7 +0,0 @@
from django.contrib import admin
from models import SyncGroupCache
# Register your models here.
admin.site.register(SyncGroupCache)

View File

@ -1,12 +0,0 @@
from django.db import models
from django.contrib.auth.models import User
class SyncGroupCache(models.Model):
groupname = models.CharField(max_length=254)
servicename = models.CharField(max_length=254, default="")
user = models.ForeignKey(User)
def __str__(self):
return self.user.username + ' - ' + self.groupname + ' - ' + self.servicename + ' - SyncGroupCache'

View File

@ -1,785 +0,0 @@
from django.conf import settings
from celery.task import periodic_task
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
from notifications import notify
from celery import task
from celery.task.schedules import crontab
from services.managers.openfire_manager import OpenfireManager
from services.managers.mumble_manager import MumbleManager
from services.managers.phpbb3_manager import Phpbb3Manager
from services.managers.ipboard_manager import IPBoardManager
from services.managers.xenforo_manager import XenForoManager
from services.managers.teamspeak3_manager import Teamspeak3Manager
from services.managers.discord_manager import DiscordOAuthManager
from services.managers.discourse_manager import DiscourseManager
from services.managers.smf_manager import smfManager
from services.models import AuthTS
from services.models import TSgroup
from authentication.models import AuthServicesInfo
from eveonline.managers import EveManager
from services.managers.eve_api_manager import EveApiManager
from util.common_task import deactivate_services
from util import add_member_permission
from util import remove_member_permission
from util import check_if_user_has_permission
from util.common_task import add_user_to_group
from util.common_task import remove_user_from_group
from util.common_task import generate_corp_group_name
from util.common_task import generate_alliance_group_name
from eveonline.models import EveCharacter
from eveonline.models import EveCorporationInfo
from eveonline.models import EveAllianceInfo
from authentication.managers import AuthServicesInfoManager
from services.models import DiscordAuthToken
import evelink
import time
import logging
logger = logging.getLogger(__name__)
def disable_member(user):
change = False
logger.debug("Disabling member %s" % user)
if user.user_permissions.all().exists():
logger.info("Clearning user %s permission to deactivate user." % user)
user.user_permissions.clear()
change = True
if user.groups.all().exists():
logger.info("Clearing user %s groups to deactivate user." % user)
user.groups.clear()
change = True
deactivate_services(user)
return change
def is_teamspeak3_active():
return settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3
@task
def update_jabber_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating jabber groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s jabber groups to %s" % (user, groups))
try:
OpenfireManager.update_user_groups(authserviceinfo.jabber_username, authserviceinfo.jabber_password, groups)
except:
logger.exception("Jabber group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s jabber groups." % user)
@task
def update_all_jabber_groups():
logger.debug("Updating ALL jabber groups")
for user in AuthServicesInfo.objects.exclude(jabber_username__exact=''):
update_jabber_groups.delay(user.user_id)
@task
def update_mumble_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating mumble groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s mumble groups to %s" % (user, groups))
try:
MumbleManager.update_groups(authserviceinfo.mumble_username, groups)
except:
logger.exception("Mumble group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s mumble groups." % user)
@task
def update_all_mumble_groups():
logger.debug("Updating ALL mumble groups")
for user in AuthServicesInfo.objects.exclude(mumble_username__exact=''):
update_mumble_groups.delay(user.user_id)
@task
def update_forum_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating forum groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s forum groups to %s" % (user, groups))
try:
Phpbb3Manager.update_groups(authserviceinfo.forum_username, groups)
except:
logger.exception("Phpbb group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s forum groups." % user)
@task
def update_all_forum_groups():
logger.debug("Updating ALL forum groups")
for user in AuthServicesInfo.objects.exclude(forum_username__exact=''):
update_forum_groups.delay(user.user_id)
@task
def update_smf_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating smf groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s smf groups to %s" % (user, groups))
try:
smfManager.update_groups(authserviceinfo.smf_username, groups)
except:
logger.exception("smf group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s smf groups." % user)
@task
def update_all_smf_groups():
logger.debug("Updating ALL smf groups")
for user in AuthServicesInfo.objects.exclude(smf_username__exact=''):
update_smf_groups.delay(user.user_id)
@task
def update_ipboard_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating user %s ipboard groups." % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
groups.append('empty')
logger.debug("Updating user %s ipboard groups to %s" % (user, groups))
try:
IPBoardManager.update_groups(authserviceinfo.ipboard_username, groups)
except:
logger.exception("IPBoard group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s ipboard groups." % user)
@task
def update_all_ipboard_groups():
logger.debug("Updating ALL ipboard groups")
for user in AuthServicesInfo.objects.exclude(ipboard_username__exact=''):
update_ipboard_groups.delay(user.user_id)
@task
def update_teamspeak3_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating user %s teamspeak3 groups" % user)
usergroups = user.groups.all()
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = {}
for usergroup in usergroups:
filtered_groups = AuthTS.objects.filter(auth_group=usergroup)
if filtered_groups:
for filtered_group in filtered_groups:
for ts_group in filtered_group.ts_group.all():
groups[ts_group.ts_group_name] = ts_group.ts_group_id
logger.debug("Updating user %s teamspeak3 groups to %s" % (user, groups))
Teamspeak3Manager.update_groups(authserviceinfo.teamspeak3_uid, groups)
logger.debug("Updated user %s teamspeak3 groups." % user)
@task
def update_all_teamspeak3_groups():
logger.debug("Updating ALL teamspeak3 groups")
for user in AuthServicesInfo.objects.exclude(teamspeak3_uid__exact=''):
update_teamspeak3_groups.delay(user.user_id)
@task
def update_discord_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discord groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
logger.debug("No syncgroups found for user. Adding empty group.")
groups.append('empty')
logger.debug("Updating user %s discord groups to %s" % (user, groups))
try:
DiscordOAuthManager.update_groups(authserviceinfo.discord_uid, groups)
except:
logger.exception("Discord group sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s discord groups." % user)
@task
def update_all_discord_groups():
logger.debug("Updating ALL discord groups")
for user in AuthServicesInfo.objects.exclude(discord_uid__exact=''):
update_discord_groups.delay(user.user_id)
@task
def update_discord_nickname(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discord nickname for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
character = EveManager.get_character_by_id(authserviceinfo.main_char_id)
logger.debug("Updating user %s discord nickname to %s" % (user, character.character_name))
try:
DiscordOAuthManager.update_nickname(authserviceinfo.discord_uid, character.character_name)
except:
logger.exception("Discord nickname sync failed for %s, retrying in 10 mins" % user)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s discord nickname." % user)
@task
def update_all_discord_nicknames():
logger.debug("Updating ALL discord nicknames")
for user in AuthServicesInfo.objects.exclude(discord_uid__exact=''):
update_discord_nickname(user.user_id)
@task
def update_discourse_groups(pk):
user = User.objects.get(pk=pk)
logger.debug("Updating discourse groups for user %s" % user)
authserviceinfo = AuthServicesInfo.objects.get(user=user)
groups = []
for group in user.groups.all():
groups.append(str(group.name))
if len(groups) == 0:
logger.debug("No syncgroups found for user. Adding empty group.")
groups.append('empty')
logger.debug("Updating user %s discourse groups to %s" % (user, groups))
try:
DiscourseManager.update_groups(authserviceinfo.discourse_username, groups)
except:
logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user, exc_info=True)
raise self.retry(countdown = 60 * 10)
logger.debug("Updated user %s discourse groups." % user)
@task
def update_all_discourse_groups():
logger.debug("Updating ALL discourse groups")
for user in AuthServicesInfo.objects.exclude(discourse_username__exact=''):
update_discourse_groups.delay(user.user_id)
def assign_corp_group(auth):
corp_group = None
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
corpname = generate_corp_group_name(char.corporation_name)
state = determine_membership_by_character(char)
if state == "BLUE" and settings.BLUE_CORP_GROUPS:
logger.debug("Validating blue user %s has corp group assigned." % auth.user)
corp_group, c = Group.objects.get_or_create(name=corpname)
elif state == "MEMBER" and settings.MEMBER_CORP_GROUPS:
logger.debug("Validating member %s has corp group assigned." % auth.user)
corp_group, c = Group.objects.get_or_create(name=corpname)
else:
logger.debug("Ensuring non-member %s has no corp groups assigned." % auth.user)
if corp_group:
if not corp_group in auth.user.groups.all():
logger.info("Adding user %s to corp group %s" % (auth.user, corp_group))
auth.user.groups.add(corp_group)
for g in auth.user.groups.all():
if str.startswith(str(g.name), "Corp_"):
if g != corp_group:
logger.info("Removing user %s from old corpgroup %s" % (auth.user, g))
auth.user.groups.remove(g)
def assign_alliance_group(auth):
alliance_group = None
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
if char.alliance_name:
alliancename = generate_alliance_group_name(char.alliance_name)
state = determine_membership_by_character(char)
if state == "BLUE" and settings.BLUE_ALLIANCE_GROUPS:
logger.debug("Validating blue user %s has alliance group assigned." % auth.user)
alliance_group, c = Group.objects.get_or_create(name=alliancename)
elif state == "MEMBER" and settings.MEMBER_ALLIANCE_GROUPS:
logger.debug("Validating member %s has alliance group assigned." % auth.user)
alliance_group, c = Group.objects.get_or_create(name=alliancename)
else:
logger.debug("Ensuring non-member %s has no alliance groups assigned." % auth.user)
else:
logger.debug("User %s main character %s not in an alliance. Ensuring no allinace group assigned." % (auth.user, char))
if alliance_group:
if not alliance_group in auth.user.groups.all():
logger.info("Adding user %s to alliance group %s" % (auth.user, alliance_group))
auth.user.groups.add(alliance_group)
for g in auth.user.groups.all():
if str.startswith(str(g.name), "Alliance_"):
if g != alliance_group:
logger.info("Removing user %s from old alliancegroup %s" % (auth.user, g))
auth.user.groups.remove(g)
def make_member(user):
change = False
logger.debug("Ensuring user %s has member permissions and groups." % user)
# ensure member is not blue right now
if check_if_user_has_permission(user, 'blue_member'):
logger.info("Removing user %s blue permission to transition to member" % user)
remove_member_permission(user, 'blue_member')
change = True
blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP)
if blue_group in user.groups.all():
logger.info("Removing user %s blue group" % user)
user.groups.remove(blue_group)
change = True
# make member
if check_if_user_has_permission(user, 'member') is False:
logger.info("Adding user %s member permission" % user)
add_member_permission(user, 'member')
change = True
member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP)
if not member_group in user.groups.all():
logger.info("Adding user %s to member group" % user)
user.groups.add(member_group)
change = True
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.is_blue:
logger.info("Marking user %s as non-blue" % user)
auth.is_blue = False
auth.save()
change = True
assign_corp_group(auth)
assign_alliance_group(auth)
return change
def make_blue(user):
change = False
logger.debug("Ensuring user %s has blue permissions and groups." % user)
# ensure user is not a member
if check_if_user_has_permission(user, 'member'):
logger.info("Removing user %s member permission to transition to blue" % user)
remove_member_permission(user, 'blue_member')
change = True
member_group, c = Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP)
if member_group in user.groups.all():
logger.info("Removing user %s member group" % user)
user.groups.remove(member_group)
change = True
# make blue
if check_if_user_has_permission(user, 'blue_member') is False:
logger.info("Adding user %s blue permission" % user)
add_member_permission(user, 'blue_member')
change = True
blue_group, c = Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP)
if not blue_group in user.groups.all():
logger.info("Adding user %s to blue group" % user)
user.groups.add(blue_group)
change = True
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.is_blue is False:
logger.info("Marking user %s as blue" % user)
auth.is_blue = True
auth.save()
change = True
assign_corp_group(auth)
assign_alliance_group(auth)
return change
def determine_membership_by_character(char):
if settings.IS_CORP:
if int(char.corporation_id) == int(settings.CORP_ID):
logger.debug("Character %s in owning corp id %s" % (char, char.corporation_id))
return "MEMBER"
else:
if int(char.alliance_id) == int(settings.ALLIANCE_ID):
logger.debug("Character %s in owning alliance id %s" % (char, char.alliance_id))
return "MEMBER"
if EveCorporationInfo.objects.filter(corporation_id=char.corporation_id).exists() is False:
logger.debug("No corp model for character %s corp id %s. Unable to check standings. Non-member." % (char, char.corporation_id))
return False
else:
corp = EveCorporationInfo.objects.get(corporation_id=char.corporation_id)
if corp.is_blue:
logger.debug("Character %s member of blue corp %s" % (char, corp))
return "BLUE"
else:
logger.debug("Character %s member of non-blue corp %s. Non-member." % (char, corp))
return False
def determine_membership_by_user(user):
logger.debug("Determining membership of user %s" % user)
auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists():
char = EveCharacter.objects.get(character_id=auth.main_char_id)
return determine_membership_by_character(char)
else:
logger.debug("Character model matching user %s main character id %s does not exist. Non-member." % (user, auth.main_char_id))
return False
else:
logger.debug("User %s has no main character set. Non-member." % user)
return False
def set_state(user):
if user.is_superuser:
return
change = False
if user.is_active:
state = determine_membership_by_user(user)
else:
state = False
logger.debug("Assigning user %s to state %s" % (user, state))
if state == "MEMBER":
change = make_member(user)
elif state == "BLUE":
change = make_blue(user)
else:
change = disable_member(user)
if change:
notify(user, "Membership State Change", message="You membership state has been changed to %s" % state)
def refresh_api(api_key_pair):
logger.debug("Running update on api key %s" % api_key_pair.api_id)
user = api_key_pair.user
if EveApiManager.api_key_is_valid(api_key_pair.api_id, api_key_pair.api_key):
#check to ensure API key meets min spec
logger.info("Determined api key %s is still active." % api_key_pair.api_id)
still_valid = True
state = determine_membership_by_user(user)
if state == "BLUE":
if settings.BLUE_API_ACCOUNT:
if not EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key):
logger.info("Determined api key %s for blue user %s is no longer type account as requred." % (api_key_pair.api_id, user))
still_valid = False
notify(user, "API Failed Validation", message="Your API key ID %s is not account-wide as required." % api_key_pair.api_id, level="danger")
if not EveApiManager.check_blue_api_is_full(api_key_pair.api_id, api_key_pair.api_key):
logger.info("Determined api key %s for blue user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user))
still_valid = False
notify(user, "API Failed Validation", message="Your API key ID %s does not meet access mask requirements." % api_key_pair.api_id, level="danger")
elif state == "MEMBER":
if settings.MEMBER_API_ACCOUNT:
if not EveApiManager.check_api_is_type_account(api_key_pair.api_id, api_key_pair.api_key):
logger.info("Determined api key %s for user %s is no longer type account as required." % (api_key_pair.api_id, user))
still_valid = False
notify(user, "API Failed Validation", message="Your API key ID %s is not account-wide as required." % api_key_pair.api_id, level="danger")
if not EveApiManager.check_api_is_full(api_key_pair.api_id, api_key_pair.api_key):
logger.info("Determined api key %s for user %s no longer meets minimum access mask as required." % (api_key_pair.api_id, user))
still_valid = False
notify(user, "API Failed Validation", message="Your API key ID %s does not meet access mask requirements." % api_key_pair.api_id, level="danger")
if not still_valid:
logger.debug("API key %s has failed validation; it and its characters will be deleted." % api_key_pair.api_id)
EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id)
EveManager.delete_api_key_pair(api_key_pair.api_id, user.id)
notify(user, "API Key Deleted", message="Your API key ID %s has failed validation. It and its associated characters have been deleted." % api_key_pair.api_id, level="danger")
else:
logger.info("Determined api key %s still meets requirements." % api_key_pair.api_id)
# Update characters
characters = EveApiManager.get_characters_from_api(api_key_pair.api_id, api_key_pair.api_key)
EveManager.update_characters_from_list(characters)
new_character = False
for char in characters.result:
# Ensure we have a model for all characters on key
if not EveManager.check_if_character_exist(characters.result[char]['name']):
new_character = True
logger.debug("API key %s has a new character on the account: %s" % (api_key_pair.api_id, characters.result[char]['name']))
if new_character:
logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api_key_pair.api_id))
EveManager.create_characters_from_list(characters, user, api_key_pair.api_id)
current_chars = EveCharacter.objects.filter(api_id=api_key_pair.api_id)
for c in current_chars:
if not int(c.character_id) in characters.result:
logger.info("Character %s no longer found on API ID %s" % (c, api_key_pair.api_id))
c.delete()
else:
logger.debug("API key %s is no longer valid; it and its characters will be deleted." % api_key_pair.api_id)
EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id)
EveManager.delete_api_key_pair(api_key_pair.api_id, user.id)
notify(user, "API Key Deleted", message="Your API key ID %s is invalid. It and its associated characters have been deleted." % api_key_pair.api_id, level="danger")
# Run every 3 hours
@periodic_task(run_every=crontab(minute=0, hour="*/3"))
def run_api_refresh():
users = User.objects.all()
logger.debug("Running api refresh on %s users." % len(users))
for user in users:
# Check if the api server is online
logger.debug("Running api refresh for user %s" % user)
if EveApiManager.check_if_api_server_online():
api_key_pairs = EveManager.get_api_key_pairs(user.id)
logger.debug("User %s has api key pairs %s" % (user, api_key_pairs))
if api_key_pairs:
authserviceinfo, c = AuthServicesInfo.objects.get_or_create(user=user)
logger.debug("User %s has api keys. Proceeding to refresh." % user)
for api_key_pair in api_key_pairs:
try:
refresh_api(api_key_pair)
except evelink.api.APIError as e:
if int(e.code) >= 500:
logger.error("EVE API servers encountered error %s updating %s" % (e.code, api_key_pair))
elif int(e.code) == 221:
logger.warn("API server hiccup %s while updating %s" % (e.code, api_key_pair))
else:
logger.info("API key %s failed update with error code %s" % (api_key_pair.api_id, e.code))
EveManager.delete_characters_by_api_id(api_key_pair.api_id, user.id)
EveManager.delete_api_key_pair(api_key_pair.api_id, user.id)
notify(user, "API Key Deleted", message="Your API key ID %s failed validation with code %s. It and its associated characters have been deleted." % (api_key_pair.api_id, e.code), level="danger")
# Check our main character
if EveCharacter.objects.filter(character_id=authserviceinfo.main_char_id).exists() is False:
logger.info("User %s main character id %s missing model. Clearning main character." % (user, authserviceinfo.main_char_id))
authserviceinfo.main_char_id = ''
authserviceinfo.save()
notify(user, "Main Character Reset", message="Your specified main character no longer has a model.\nThis could be the result of an invalid API\nYour main character ID has been reset.", level="warn")
set_state(user)
def populate_alliance(id, blue=False):
logger.debug("Populating alliance model with id %s blue %s" % (id, blue))
alliance_info = EveApiManager.get_alliance_information(id)
if not alliance_info:
raise ValueError("Supplied alliance id %s is invalid" % id)
if EveAllianceInfo.objects.filter(alliance_id=id).exists():
alliance = EveAllianceInfo.objects.get(alliance_id=id)
else:
EveManager.create_alliance_info(alliance_info['id'], alliance_info['name'], alliance_info['ticker'],
alliance_info['executor_id'], alliance_info['member_count'], blue)
alliance = EveAllianceInfo.objects.get(alliance_id=id)
for member_corp in alliance_info['member_corps']:
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
if corp.alliance != alliance:
corp.alliance = alliance
corp.save()
else:
logger.info("Creating new alliance member corp id %s" % member_corp)
corpinfo = EveApiManager.get_corporation_information(member_corp)
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], blue, alliance)
@task
def update_alliance(id):
alliance = EveAllianceInfo.objects.get(alliance_id=id)
corps = EveCorporationInfo.objects.filter(alliance=alliance)
logger.debug("Updating alliance %s with %s member corps" % (alliance, len(corps)))
allianceinfo = EveApiManager.get_alliance_information(alliance.alliance_id)
if allianceinfo:
EveManager.update_alliance_info(allianceinfo['id'], allianceinfo['executor_id'],
allianceinfo['member_count'], alliance.is_blue)
for corp in corps:
if corp.corporation_id in allianceinfo['member_corps'] is False:
logger.info("Corp %s no longer in alliance %s" % (corp, alliance))
corp.alliance = None
corp.save()
populate_alliance(alliance.alliance_id, blue=alliance.is_blue)
elif EveApiManager.check_if_alliance_exists(alliance.alliance_id) is False:
logger.info("Alliance %s has closed. Deleting model" % alliance)
alliance.delete()
@task
def update_corp(id):
corp = EveCorporationInfo.objects.get(corporation_id=id)
logger.debug("Updating corp %s" % corp)
corpinfo = EveApiManager.get_corporation_information(corp.corporation_id)
if corpinfo:
alliance = None
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
EveManager.update_corporation_info(corpinfo['id'], corpinfo['members']['current'], alliance, corp.is_blue)
elif EveApiManager.check_if_corp_exists(corp.corporation_id) is False:
logger.info("Corp %s has closed. Deleting model" % corp)
corp.delete()
# Run Every 2 hours
@periodic_task(run_every=crontab(minute=0, hour="*/2"))
def run_corp_update():
if EveApiManager.check_if_api_server_online() is False:
logger.warn("Aborted updating corp and alliance models: API server unreachable")
return
standing_level = 'alliance'
try:
# get corp info for owning corp if required
ownercorpinfo = {}
if settings.IS_CORP:
standing_level = 'corp'
logger.debug("Getting information for owning corp with id %s" % settings.CORP_ID)
ownercorpinfo = EveApiManager.get_corporation_information(settings.CORP_ID)
if not ownercorpinfo:
logger.error("Failed to retrieve corp info for owning corp id %s - bad corp id?" % settings.CORP_ID)
return
# check if we need to update an alliance model
alliance_id = ''
if ownercorpinfo and ownercorpinfo['alliance']['id']:
alliance_id = ownercorpinfo['alliance']['id']
elif settings.IS_CORP is False:
alliance_id = settings.ALLIANCE_ID
# get and create alliance info for owning alliance if required
alliance = None
if alliance_id:
logger.debug("Getting information for owning alliance with id %s" % alliance_id)
ownerallianceinfo = EveApiManager.get_alliance_information(alliance_id)
if not ownerallianceinfo:
logger.error("Failed to retrieve corp info for owning alliance id %s - bad alliance id?" % alliance_id)
return
if EveAllianceInfo.objects.filter(alliance_id=ownerallianceinfo['id']).exists():
logger.debug("Updating existing owner alliance model with id %s" % alliance_id)
EveManager.update_alliance_info(ownerallianceinfo['id'], ownerallianceinfo['executor_id'], ownerallianceinfo['member_count'], False)
else:
populate_alliance(alliance_id)
alliance = EveAllianceInfo.objects.get(alliance_id=alliance_id)
# create corp info for owning corp if required
if ownercorpinfo:
if EveCorporationInfo.objects.filter(corporation_id=ownercorpinfo['id']).exists():
logger.debug("Updating existing owner corp model with id %s" % ownercorpinfo['id'])
EveManager.update_corporation_info(ownercorpinfo['id'], ownercorpinfo['members']['current'], alliance, False)
else:
logger.info("Creating model for owning corp with id %s" % ownercorpinfo['id'])
EveManager.create_corporation_info(ownercorpinfo['id'], ownercorpinfo['name'], ownercorpinfo['ticker'],
ownercorpinfo['members']['current'], False, alliance)
# validate and create corp models for member corps of owning alliance
if alliance:
current_corps = EveCorporationInfo.objects.filter(alliance=alliance)
for corp in current_corps:
if corp.corporation_id in ownerallianceinfo['member_corps'] is False:
logger.info("Corp %s is no longer in owning alliance %s - updating model." % (corp, alliance))
corp.alliance = None
corp.save()
for member_corp in ownerallianceinfo['member_corps']:
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
if corp.alliance == alliance is not True:
logger.info("Associating corp %s with owning alliance %s" % (corp, alliance))
corp.alliance = alliance
corp.save()
else:
corpinfo = EveApiManager.get_corporation_information(member_corp)
logger.info("Creating model for owning alliance member corp with id %s" % corpinfo['id'])
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], False, alliance)
# update existing corp models
for corp in EveCorporationInfo.objects.all():
update_corp.delay(corp.corporation_id)
# update existing alliance models
for alliance in EveAllianceInfo.objects.all():
update_alliance.delay(alliance.alliance_id)
# create standings
standings = EveApiManager.get_corp_standings()
if standings:
standings = standings[standing_level]
for standing in standings:
if int(standings[standing]['standing']) >= settings.BLUE_STANDING:
logger.debug("Standing %s meets threshold" % standing)
if EveApiManager.check_if_id_is_alliance(standing):
logger.debug("Standing %s is an alliance" % standing)
if EveAllianceInfo.objects.filter(alliance_id=standing).exists():
alliance = EveAllianceInfo.objects.get(alliance_id=standing)
if alliance.is_blue is not True:
logger.info("Updating alliance %s as blue" % alliance)
alliance.is_blue = True
alliance.save()
else:
populate_alliance(standing, blue=True)
elif EveApiManager.check_if_id_is_corp(standing):
logger.debug("Standing %s is a corp" % standing)
if EveCorporationInfo.objects.filter(corporation_id=standing).exists():
corp = EveCorporationInfo.objects.get(corporation_id=standing)
if corp.is_blue is not True:
logger.info("Updating corp %s as blue" % corp)
corp.is_blue = True
corp.save()
else:
logger.info("Creating model for blue corp with id %s" % standing)
corpinfo = EveApiManager.get_corporation_information(standing)
corp_alliance = None
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
logger.debug("New corp model for standing %s has existing alliance model" % standing)
corp_alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], True, corp_alliance)
# update alliance standings
for alliance in EveAllianceInfo.objects.filter(is_blue=True):
if int(alliance.alliance_id) in standings:
if float(standings[int(alliance.alliance_id)]['standing']) < float(settings.BLUE_STANDING):
logger.info("Alliance %s no longer meets minimum blue standing threshold" % alliance)
alliance.is_blue = False
alliance.save()
else:
logger.info("Alliance %s no longer in standings" % alliance)
alliance.is_blue = False
alliance.save()
# update corp standings
for corp in EveCorporationInfo.objects.filter(is_blue=True):
if int(corp.corporation_id) in standings:
if float(standings[int(corp.corporation_id)]['standing']) < float(settings.BLUE_STANDING):
logger.info("Corp %s no longer meets minimum blue standing threshold" % corp)
corp.is_blue = False
corp.save()
else:
if corp.alliance:
if not corp.alliance.is_blue:
logger.info("Corp %s and its alliance %s are no longer blue" % (corp, corp.alliance))
corp.is_blue = False
corp.save()
else:
logger.info("Corp %s is no longer blue" % corp)
corp.is_blue = False
corp.save()
# delete unnecessary alliance models
for alliance in EveAllianceInfo.objects.filter(is_blue=False):
logger.debug("Checking to delete alliance %s" % alliance)
if not settings.IS_CORP:
if not alliance.alliance_id == settings.ALLIANCE_ID:
logger.info("Deleting unnecessary alliance model %s" % alliance)
alliance.delete()
else:
if not alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists():
logger.info("Deleting unnecessary alliance model %s" % alliance)
alliance.delete()
# delete unnecessary corp models
for corp in EveCorporationInfo.objects.filter(is_blue=False):
logger.debug("Checking to delete corp %s" % corp)
if not settings.IS_CORP:
if corp.alliance:
logger.debug("Corp %s has alliance %s" % (corp, corp.alliance))
if not corp.alliance.alliance_id == settings.ALLIANCE_ID:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
if corp.corporation_id != settings.CORP_ID:
logger.debug("Corp %s is not owning corp" % corp)
if corp.alliance:
logger.debug("Corp %s has alliance %s" % (corp, corp.alliance))
if not corp.alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists():
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.debug("Corp %s is owning corp" % corp)
except evelink.api.APIError as e:
logger.error("Model update failed with error code %s" % e.code)
@periodic_task(run_every=crontab(minute="*/30"))
def run_ts3_group_update():
if is_teamspeak3_active():
logger.debug("TS3 installed. Syncing local group objects.")
Teamspeak3Manager._sync_ts_group_db()

View File

@ -1 +0,0 @@
# Create your tests here.

View File

@ -1 +0,0 @@
# Create your views here.

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

7
corputils/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class CorpUtilsConfig(AppConfig):
name = 'corputils'

View File

@ -1,9 +1,8 @@
from __future__ import unicode_literals
from django import forms from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from eveonline.models import EveCorporationInfo
from eveonline.models import EveAllianceInfo
class CorputilsSearchForm(forms.Form): class CorputilsSearchForm(forms.Form):
search_string = forms.CharField(max_length=254, required=True, label="", widget=forms.TextInput(attrs={'placeholder': _('Search characters...')})) search_string = forms.CharField(max_length=254, required=True, label="",
widget=forms.TextInput(attrs={'placeholder': _('Search characters...')}))

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,12 +1,11 @@
from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.shortcuts import HttpResponseRedirect from django.shortcuts import render, redirect
from collections import namedtuple from collections import namedtuple
from authentication.managers import AuthServicesInfoManager from authentication.models import AuthServicesInfo
from services.managers.eve_api_manager import EveApiManager from services.managers.eve_api_manager import EveApiManager
from services.managers.evewho_manager import EveWhoManager from services.managers.evewho_manager import EveWhoManager
from eveonline.models import EveCorporationInfo from eveonline.models import EveCorporationInfo
@ -14,14 +13,15 @@ from eveonline.models import EveAllianceInfo
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
from eveonline.models import EveApiKeyPair from eveonline.models import EveApiKeyPair
from fleetactivitytracking.models import Fat from fleetactivitytracking.models import Fat
from util import check_if_user_has_permission from corputils.forms import CorputilsSearchForm
from forms import CorputilsSearchForm
from evelink.api import APIError from evelink.api import APIError
import logging import logging
import datetime import datetime
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Player(object): class Player(object):
def __init__(self, main, user, maincorp, maincorpid, altlist, apilist, n_fats): def __init__(self, main, user, maincorp, maincorpid, altlist, apilist, n_fats):
self.main = main self.main = main
@ -32,12 +32,14 @@ class Player(object):
self.apilist = apilist self.apilist = apilist
self.n_fats = n_fats self.n_fats = n_fats
def first_day_of_next_month(year, month): def first_day_of_next_month(year, month):
if month == 12: if month == 12:
return datetime.datetime(year + 1, 1, 1) return datetime.datetime(year + 1, 1, 1)
else: else:
return datetime.datetime(year, month + 1, 1) return datetime.datetime(year, month + 1, 1)
def first_day_of_previous_month(year, month): def first_day_of_previous_month(year, month):
if month == 1: if month == 1:
return datetime.datetime(year - 1, 12, 1) return datetime.datetime(year - 1, 12, 1)
@ -55,16 +57,17 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
logger.debug("corp_member_view called by user %s" % request.user) logger.debug("corp_member_view called by user %s" % request.user)
try: try:
user_main = EveCharacter.objects.get(character_id=AuthServicesInfoManager.get_auth_service_info(user=request.user).main_char_id) user_main = EveCharacter.objects.get(
character_id=AuthServicesInfo.objects.get_or_create(user=request.user)[0].main_char_id)
user_corp_id = int(user_main.corporation_id) user_corp_id = int(user_main.corporation_id)
except (ValueError, EveCharacter.DoesNotExist): except (ValueError, EveCharacter.DoesNotExist):
user_corp_id = settings.CORP_ID user_corp_id = settings.CORP_ID
if not settings.IS_CORP: if not settings.IS_CORP:
alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID) alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID)
alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance) alliancecorps = EveCorporationInfo.objects.filter(alliance=alliance)
membercorplist = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in alliancecorps] membercorplist = [(int(membercorp.corporation_id), str(membercorp.corporation_name)) for membercorp in
alliancecorps]
membercorplist.sort(key=lambda tup: tup[1]) membercorplist.sort(key=lambda tup: tup[1])
membercorp_id_list = [int(membercorp.corporation_id) for membercorp in alliancecorps] membercorp_id_list = [int(membercorp.corporation_id) for membercorp in alliancecorps]
@ -77,7 +80,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
user_corp_id = None user_corp_id = None
if not corpid: if not corpid:
if(settings.IS_CORP): if settings.IS_CORP:
corpid = settings.CORP_ID corpid = settings.CORP_ID
elif user_corp_id: elif user_corp_id:
corpid = user_corp_id corpid = user_corp_id
@ -86,7 +89,8 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
corp = EveCorporationInfo.objects.get(corporation_id=corpid) corp = EveCorporationInfo.objects.get(corporation_id=corpid)
if check_if_user_has_permission(request.user, 'alliance_apis') or (check_if_user_has_permission(request.user, 'corp_apis') and (user_corp_id == corpid)): if request.user.has_perm('auth.alliance_apis') or (
request.user.has_perm('auth.corp_apis') and (user_corp_id == corpid)):
logger.debug("Retreiving and sending API-information") logger.debug("Retreiving and sending API-information")
if settings.IS_CORP: if settings.IS_CORP:
@ -107,7 +111,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
char = EveCharacter.objects.get(character_id=char_id) char = EveCharacter.objects.get(character_id=char_id)
char_owner = char.user char_owner = char.user
try: try:
mainid = int(AuthServicesInfoManager.get_auth_service_info(user=char_owner).main_char_id) mainid = int(AuthServicesInfo.objects.get_or_create(user=char_owner)[0].main_char_id)
mainchar = EveCharacter.objects.get(character_id=mainid) mainchar = EveCharacter.objects.get(character_id=mainid)
mainname = mainchar.character_name mainname = mainchar.character_name
maincorp = mainchar.corporation_name maincorp = mainchar.corporation_name
@ -120,7 +124,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
maincorp = "Not set." maincorp = "Not set."
maincorpid = None maincorpid = None
api_pair = None api_pair = None
num_registered_characters = num_registered_characters + 1 num_registered_characters += 1
characters_with_api.setdefault(mainname, Player(main=mainchar, characters_with_api.setdefault(mainname, Player(main=mainchar,
user=char_owner, user=char_owner,
maincorp=maincorp, maincorp=maincorp,
@ -132,7 +136,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
if api_pair: if api_pair:
characters_with_api[mainname].apilist.append(api_pair) characters_with_api[mainname].apilist.append(api_pair)
except (EveCharacter.DoesNotExist): except EveCharacter.DoesNotExist:
characters_without_api.update({member_data["name"]: member_data["id"]}) characters_without_api.update({member_data["name"]: member_data["id"]})
for char in EveCharacter.objects.filter(corporation_id=corpid): for char in EveCharacter.objects.filter(corporation_id=corpid):
@ -140,7 +144,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
logger.info("Character '%s' does not exist in EveWho dump." % char.character_name) logger.info("Character '%s' does not exist in EveWho dump." % char.character_name)
char_owner = char.user char_owner = char.user
try: try:
mainid = int(AuthServicesInfoManager.get_auth_service_info(user=char_owner).main_char_id) mainid = int(AuthServicesInfo.objects.get_or_create(user=char_owner)[0].main_char_id)
mainchar = EveCharacter.objects.get(character_id=mainid) mainchar = EveCharacter.objects.get(character_id=mainid)
mainname = mainchar.character_name mainname = mainchar.character_name
maincorp = mainchar.corporation_name maincorp = mainchar.corporation_name
@ -153,7 +157,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
maincorp = "Not set." maincorp = "Not set."
maincorpid = None maincorpid = None
api_pair = None api_pair = None
num_registered_characters = num_registered_characters + 1 num_registered_characters += 1
characters_with_api.setdefault(mainname, Player(main=mainchar, characters_with_api.setdefault(mainname, Player(main=mainchar,
user=char_owner, user=char_owner,
maincorp=maincorp, maincorp=maincorp,
@ -168,13 +172,13 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
n_unacounted = corp.member_count - (num_registered_characters + len(characters_without_api)) n_unacounted = corp.member_count - (num_registered_characters + len(characters_without_api))
for mainname, player in characters_with_api.items(): for mainname, player in characters_with_api.items():
fats_this_month = Fat.objects.filter(user=player.user).filter(fatlink__fatdatetime__gte = start_of_month).filter(fatlink__fatdatetime__lt = start_of_next_month) fats_this_month = Fat.objects.filter(user=player.user).filter(
fatlink__fatdatetime__gte=start_of_month).filter(fatlink__fatdatetime__lt=start_of_next_month)
characters_with_api[mainname].n_fats = len(fats_this_month) characters_with_api[mainname].n_fats = len(fats_this_month)
if start_of_next_month > datetime.datetime.now(): if start_of_next_month > datetime.datetime.now():
start_of_next_month = None start_of_next_month = None
if not settings.IS_CORP: if not settings.IS_CORP:
context = {"membercorplist": membercorplist, context = {"membercorplist": membercorplist,
"corp": corp, "corp": corp,
@ -196,8 +200,8 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo
context["previous_month"] = start_of_previous_month context["previous_month"] = start_of_previous_month
context["this_month"] = start_of_month context["this_month"] = start_of_month
return render_to_response('registered/corputils.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/corputils.html', context=context)
return HttpResponseRedirect("/dashboard/") return redirect("auth_dashboard")
@login_required @login_required
@ -208,13 +212,15 @@ def corputils_search(request, corpid=settings.CORP_ID):
authorized = False authorized = False
try: try:
user_main = EveCharacter.objects.get(character_id=AuthServicesInfoManager.get_auth_service_info(user=request.user).main_char_id) user_main = EveCharacter.objects.get(
if check_if_user_has_permission(request.user, 'alliance_apis') or (check_if_user_has_permission(request.user, 'corp_apis') and (user_main.corporation_id == corpid)): character_id=AuthServicesInfo.objects.get_or_create(user=request.user)[0].main_char_id)
if request.user.has_perm('auth.alliance_apis') or (
request.user.has_perm('auth.corp_apis') and (user_main.corporation_id == corpid)):
logger.debug("Retreiving and sending API-information") logger.debug("Retreiving and sending API-information")
authorized = True authorized = True
except (ValueError, EveCharacter.DoesNotExist): except (ValueError, EveCharacter.DoesNotExist):
if check_if_user_has_permission(request.user, 'alliance_apis'): if request.user.has_perm('auth.alliance_apis'):
logger.debug("Retreiving and sending API-information") logger.debug("Retrieving and sending API-information")
authorized = True authorized = True
if authorized: if authorized:
@ -229,14 +235,16 @@ def corputils_search(request, corpid=settings.CORP_ID):
if settings.IS_CORP: if settings.IS_CORP:
try: try:
member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID, settings.CORP_API_VCODE) member_list = EveApiManager.get_corp_membertracking(settings.CORP_API_ID,
settings.CORP_API_VCODE)
except APIError: except APIError:
logger.debug("Corp API does not have membertracking scope, using EveWho data instead.") logger.debug("Corp API does not have membertracking scope, using EveWho data instead.")
member_list = EveWhoManager.get_corporation_members(corpid) member_list = EveWhoManager.get_corporation_members(corpid)
else: else:
member_list = EveWhoManager.get_corporation_members(corpid) member_list = EveWhoManager.get_corporation_members(corpid)
SearchResult = namedtuple('SearchResult', ['name', 'id', 'main', 'api_registered', 'character', 'apiinfo']) SearchResult = namedtuple('SearchResult',
['name', 'id', 'main', 'api_registered', 'character', 'apiinfo'])
searchresults = [] searchresults = []
for memberid, member_data in member_list.items(): for memberid, member_data in member_list.items():
@ -244,7 +252,7 @@ def corputils_search(request, corpid=settings.CORP_ID):
try: try:
char = EveCharacter.objects.get(character_name=member_data["name"]) char = EveCharacter.objects.get(character_name=member_data["name"])
user = char.user user = char.user
mainid = int(AuthServicesInfoManager.get_auth_service_info(user=user).main_char_id) mainid = int(AuthServicesInfo.objects.get_or_create(user=user)[0].main_char_id)
main = EveCharacter.objects.get(character_id=mainid) main = EveCharacter.objects.get(character_id=mainid)
api_registered = True api_registered = True
apiinfo = EveApiKeyPair.objects.get(api_id=char.api_id) apiinfo = EveApiKeyPair.objects.get(api_id=char.api_id)
@ -254,25 +262,24 @@ def corputils_search(request, corpid=settings.CORP_ID):
main = "" main = ""
apiinfo = None apiinfo = None
searchresults.append(SearchResult(name=member_data["name"], id=memberid, main=main, api_registered=api_registered, searchresults.append(SearchResult(name=member_data["name"], id=memberid, main=main,
api_registered=api_registered,
character=char, apiinfo=apiinfo)) character=char, apiinfo=apiinfo))
logger.info("Found %s members for user %s matching search string %s" % (
len(searchresults), request.user, searchstring))
logger.info("Found %s members for user %s matching search string %s" % (len(searchresults), request.user, searchstring)) context = {'corp': corp, 'results': searchresults, 'search_form': CorputilsSearchForm(),
"year": datetime.datetime.now().year, "month": datetime.datetime.now().month}
context = {'corp': corp, 'results': searchresults, 'search_form': CorputilsSearchForm(), "year":datetime.datetime.now().year, "month":datetime.datetime.now().month} return render(request, 'registered/corputilssearchview.html',
context=context)
return render_to_response('registered/corputilssearchview.html',
context, context_instance=RequestContext(request))
else: else:
logger.debug("Form invalid - returning for user %s to retry." % request.user) logger.debug("Form invalid - returning for user %s to retry." % request.user)
context = {'corp': corp, 'members': None, 'search_form': CorputilsSearchForm()} context = {'corp': corp, 'members': None, 'search_form': CorputilsSearchForm()}
return render_to_response('registered/corputilssearchview.html', return render(request, 'registered/corputilssearchview.html', context=context)
context, context_instance=RequestContext(request))
else: else:
logger.debug("Returning empty search form for user %s" % request.user) logger.debug("Returning empty search form for user %s" % request.user)
return HttpResponseRedirect("/corputils/") return redirect("auth_corputils")
return HttpResponseRedirect("/dashboard/") return redirect("auth_dashboard")

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,24 +1,28 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import EveCharacter from eveonline.models import EveCharacter
from models import EveApiKeyPair from eveonline.models import EveApiKeyPair
from models import EveAllianceInfo from eveonline.models import EveAllianceInfo
from models import EveCorporationInfo from eveonline.models import EveCorporationInfo
from authentication.managers import AuthServicesInfoManager from authentication.models import AuthServicesInfo
admin.site.register(EveAllianceInfo) admin.site.register(EveAllianceInfo)
admin.site.register(EveCorporationInfo) admin.site.register(EveCorporationInfo)
class EveApiKeyPairAdmin(admin.ModelAdmin): class EveApiKeyPairAdmin(admin.ModelAdmin):
search_fields = ['api_id', 'user__username'] search_fields = ['api_id', 'user__username']
list_display = ['api_id', 'user'] list_display = ['api_id', 'user']
class EveCharacterAdmin(admin.ModelAdmin): class EveCharacterAdmin(admin.ModelAdmin):
search_fields = ['character_name', 'corporation_name', 'alliance_name', 'user__username', 'api_id'] search_fields = ['character_name', 'corporation_name', 'alliance_name', 'user__username', 'api_id']
list_display = ('character_name', 'corporation_name', 'alliance_name', 'user', 'main_character') list_display = ('character_name', 'corporation_name', 'alliance_name', 'user', 'main_character')
def main_character(self, obj): @staticmethod
auth = AuthServicesInfoManager.get_auth_service_info(obj.user) def main_character(obj):
auth = AuthServicesInfo.objects.get_or_create(user=obj.user)[0]
if auth and auth.main_char_id: if auth and auth.main_char_id:
try: try:
return EveCharacter.objects.get(character_id=auth.main_char_id) return EveCharacter.objects.get(character_id=auth.main_char_id)
@ -26,5 +30,6 @@ class EveCharacterAdmin(admin.ModelAdmin):
pass pass
return None return None
admin.site.register(EveCharacter, EveCharacterAdmin) admin.site.register(EveCharacter, EveCharacterAdmin)
admin.site.register(EveApiKeyPair, EveApiKeyPairAdmin) admin.site.register(EveApiKeyPair, EveApiKeyPairAdmin)

7
eveonline/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class EveonlineConfig(AppConfig):
name = 'eveonline'

View File

@ -1,23 +1,24 @@
from __future__ import unicode_literals
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from services.managers.eve_api_manager import EveApiManager from services.managers.eve_api_manager import EveApiManager
from eveonline.managers import EveManager from eveonline.managers import EveManager
from eveonline.models import EveCharacter
import evelink import evelink
from celerytask.tasks import determine_membership_by_character
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class UpdateKeyForm(forms.Form):
user_state = None
class UpdateKeyForm(forms.Form):
api_id = forms.CharField(max_length=254, required=True, label="Key ID") api_id = forms.CharField(max_length=254, required=True, label="Key ID")
api_key = forms.CharField(max_length=254, required=True, label="Verification Code") api_key = forms.CharField(max_length=254, required=True, label="Verification Code")
def __init__(self, user, *args, **kwargs):
super(UpdateKeyForm, self).__init__(*args, **kwargs)
self.user = user
def clean_api_id(self): def clean_api_id(self):
try: try:
api_id = int(self.cleaned_data['api_id']) api_id = int(self.cleaned_data['api_id'])
@ -28,35 +29,18 @@ class UpdateKeyForm(forms.Form):
def clean(self): def clean(self):
super(UpdateKeyForm, self).clean() super(UpdateKeyForm, self).clean()
if 'api_id' in self.cleaned_data and 'api_key' in self.cleaned_data:
try:
if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']): if EveManager.check_if_api_key_pair_exist(self.cleaned_data['api_id']):
logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id']) logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id'])
raise forms.ValidationError(u'API key already exist') raise forms.ValidationError('API key already exist')
if EveApiManager.api_key_is_valid(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: if settings.REJECT_OLD_APIS and not EveManager.check_if_api_key_pair_is_new(
raise forms.ValidationError(u'API key is invalid') self.cleaned_data['api_id'],
if (settings.REJECT_OLD_APIS and settings.REJECT_OLD_APIS_MARGIN):
EveManager.check_if_api_key_pair_is_new(self.cleaned_data['api_id'], settings.REJECT_OLD_APIS_MARGIN) is False): raise forms.ValidationError('API key is too old. Please create a new key')
raise forms.ValidationError(u'API key is too old. Please create a new key') try:
chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result EveApiManager.validate_api(self.cleaned_data['api_id'], self.cleaned_data['api_key'], self.user)
states = []
states.append(self.user_state)
for char in chars:
evechar = EveCharacter()
evechar.character_name = chars[char]['name']
evechar.corporation_id = chars[char]['corp']['id']
evechar.alliance_id = chars[char]['alliance']['id']
state = determine_membership_by_character(evechar)
logger.debug("API ID %s character %s has state %s" % (self.cleaned_data['api_id'], evechar, state))
states.append(state)
if 'MEMBER' in states:
if EveApiManager.validate_member_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False:
raise forms.ValidationError(u'API must meet member requirements')
if 'BLUE' in states:
if EveApiManager.validate_blue_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False:
raise forms.ValidationError(u'API must meet blue requirements')
return self.cleaned_data return self.cleaned_data
except EveApiManager.ApiValidationError as e:
raise forms.ValidationError(str(e))
except evelink.api.APIError as e: except evelink.api.APIError as e:
logger.debug("Got error code %s while validating API %s" % (e.code, self.cleaned_data['api_id'])) logger.debug("Got error code %s while validating API %s" % (e.code, self.cleaned_data['api_id']))
if int(e.code) in [221, 222]: if int(e.code) in [221, 222]:

View File

@ -1,13 +1,15 @@
from models import EveCharacter from __future__ import unicode_literals
from models import EveApiKeyPair from eveonline.models import EveCharacter
from models import EveAllianceInfo from eveonline.models import EveApiKeyPair
from models import EveCorporationInfo from eveonline.models import EveAllianceInfo
from eveonline.models import EveCorporationInfo
from services.managers.eve_api_manager import EveApiManager from services.managers.eve_api_manager import EveApiManager
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class EveManager: class EveManager:
def __init__(self): def __init__(self):
pass pass
@ -64,8 +66,8 @@ class EveManager:
eve_char.save() eve_char.save()
logger.info("Updated character model %s" % eve_char) logger.info("Updated character model %s" % eve_char)
else: else:
logger.warn("Attempting to update non-existing character model with name %s" % chars.result[char]['name']) logger.warn(
"Attempting to update non-existing character model with name %s" % chars.result[char]['name'])
@staticmethod @staticmethod
def create_api_keypair(api_id, api_key, user_id): def create_api_keypair(api_id, api_key, user_id):
@ -179,7 +181,9 @@ class EveManager:
logger.info("Deleted user %s api key id %s" % (user_id, api_id)) logger.info("Deleted user %s api key id %s" % (user_id, api_id))
apikeypair.delete() apikeypair.delete()
else: else:
logger.error("Unable to delete api: user mismatch: key id %s owned by user id %s, not deleting user id %s" % (api_id, apikeypair.user.id, user_id)) logger.error(
"Unable to delete api: user mismatch: key id %s owned by user id %s, not deleting user id %s" % (
api_id, apikeypair.user.id, user_id))
else: else:
logger.warn("Unable to locate api id %s - cannot delete." % api_id) logger.warn("Unable to locate api id %s - cannot delete." % api_id)
@ -195,7 +199,10 @@ class EveManager:
logger.info("Deleting user %s character %s from api %s" % (user_id, char, api_id)) logger.info("Deleting user %s character %s from api %s" % (user_id, char, api_id))
char.delete() char.delete()
else: else:
logger.error("Unable to delete character %s by api %s: user mismatch: character owned by user id%s, not deleting user id %s" % (char, api_id, char.user.id, user_id)) logger.error(
"Unable to delete character %s by api %s: user mismatch: character owned by user id %s, "
"not deleting user id %s" % (
char, api_id, char.user.id, user_id))
@staticmethod @staticmethod
def check_if_character_exist(char_name): def check_if_character_exist(char_name):

View File

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:39
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='EveAllianceInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('alliance_id', models.CharField(max_length=254)),
('alliance_name', models.CharField(max_length=254)),
('alliance_ticker', models.CharField(max_length=254)),
('executor_corp_id', models.CharField(max_length=254)),
('is_blue', models.BooleanField(default=False)),
('member_count', models.IntegerField()),
],
),
migrations.CreateModel(
name='EveApiKeyPair',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('api_id', models.CharField(max_length=254)),
('api_key', models.CharField(max_length=254)),
('error_count', models.PositiveIntegerField(default=0)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='EveCharacter',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('character_id', models.CharField(max_length=254)),
('character_name', models.CharField(max_length=254)),
('corporation_id', models.CharField(max_length=254)),
('corporation_name', models.CharField(max_length=254)),
('corporation_ticker', models.CharField(max_length=254)),
('alliance_id', models.CharField(max_length=254)),
('alliance_name', models.CharField(max_length=254)),
('api_id', models.CharField(max_length=254)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='EveCorporationInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('corporation_id', models.CharField(max_length=254)),
('corporation_name', models.CharField(max_length=254)),
('corporation_ticker', models.CharField(max_length=254)),
('member_count', models.IntegerField()),
('is_blue', models.BooleanField(default=False)),
('alliance', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveAllianceInfo')),
],
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-10 20:20
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('eveonline', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='eveapikeypair',
name='error_count',
),
]

View File

@ -1,7 +1,10 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
@python_2_unicode_compatible
class EveCharacter(models.Model): class EveCharacter(models.Model):
character_id = models.CharField(max_length=254) character_id = models.CharField(max_length=254)
character_name = models.CharField(max_length=254) character_name = models.CharField(max_length=254)
@ -17,16 +20,17 @@ class EveCharacter(models.Model):
return self.character_name return self.character_name
@python_2_unicode_compatible
class EveApiKeyPair(models.Model): class EveApiKeyPair(models.Model):
api_id = models.CharField(max_length=254) api_id = models.CharField(max_length=254)
api_key = models.CharField(max_length=254) api_key = models.CharField(max_length=254)
user = models.ForeignKey(User) user = models.ForeignKey(User)
error_count = models.PositiveIntegerField(default=0)
def __str__(self): def __str__(self):
return self.user.username + " - ApiKeyPair" return self.user.username + " - ApiKeyPair"
@python_2_unicode_compatible
class EveAllianceInfo(models.Model): class EveAllianceInfo(models.Model):
alliance_id = models.CharField(max_length=254) alliance_id = models.CharField(max_length=254)
alliance_name = models.CharField(max_length=254) alliance_name = models.CharField(max_length=254)
@ -39,6 +43,7 @@ class EveAllianceInfo(models.Model):
return self.alliance_name return self.alliance_name
@python_2_unicode_compatible
class EveCorporationInfo(models.Model): class EveCorporationInfo(models.Model):
corporation_id = models.CharField(max_length=254) corporation_id = models.CharField(max_length=254)
corporation_name = models.CharField(max_length=254) corporation_name = models.CharField(max_length=254)

346
eveonline/tasks.py Normal file
View File

@ -0,0 +1,346 @@
from __future__ import unicode_literals
from django.conf import settings
from celery.task import periodic_task
from django.contrib.auth.models import User
from notifications import notify
from celery import task
from celery.task.schedules import crontab
from authentication.models import AuthServicesInfo
from eveonline.managers import EveManager
from eveonline.models import EveApiKeyPair
from services.managers.eve_api_manager import EveApiManager
from eveonline.models import EveCharacter
from eveonline.models import EveCorporationInfo
from eveonline.models import EveAllianceInfo
from authentication.tasks import set_state
import logging
import evelink
logger = logging.getLogger(__name__)
@task
def refresh_api(api):
logger.debug('Running update on api key %s' % api.api_id)
still_valid = True
try:
EveApiManager.validate_api(api.api_id, api.api_key, api.user)
# Update characters
characters = EveApiManager.get_characters_from_api(api.api_id, api.api_key)
EveManager.update_characters_from_list(characters)
new_character = False
for char in characters.result:
# Ensure we have a model for all characters on key
if not EveManager.check_if_character_exist(characters.result[char]['name']):
logger.debug(
"API key %s has a new character on the account: %s" % (api.api_id, characters.result[char]['name']))
new_character = True
if new_character:
logger.debug("Creating new character %s from api key %s" % (characters.result[char]['name'], api.api_id))
EveManager.create_characters_from_list(characters, api.user, api.api_id)
current_chars = EveCharacter.objects.filter(api_id=api.api_id)
for c in current_chars:
if not int(c.character_id) in characters.result:
logger.info("Character %s no longer found on API ID %s" % (c, api.api_id))
c.delete()
except evelink.api.APIError as e:
logger.warning('Received unexpected APIError (%s) while updating API %s' % (e.code, api.api_id))
except EveApiManager.ApiInvalidError:
logger.debug("API key %s is no longer valid; it and its characters will be deleted." % api.api_id)
notify(api.user, "API Failed Validation", message="Your API key ID %s is no longer valid." % api.api_id,
level="danger")
still_valid = False
except EveApiManager.ApiAccountValidationError:
logger.info(
"Determined api key %s for user %s no longer meets account access requirements." % (api.api_id, api.user))
notify(api.user, "API Failed Validation",
message="Your API key ID %s is no longer account-wide as required." % api.api_id, level="danger")
still_valid = False
except EveApiManager.ApiMaskValidationError as e:
logger.info("Determined api key %s for user %s no longer meets minimum access mask as required." % (
api.api_id, api.user))
notify(api.user, "API Failed Validation",
message="Your API key ID %s no longer meets access mask requirements. Required: %s Got: %s" % (
api.api_id, e.required_mask, e.api_mask), level="danger")
still_valid = False
finally:
if not still_valid:
EveManager.delete_characters_by_api_id(api.api_id, api.user.id)
EveManager.delete_api_key_pair(api.api_id, api.user.id)
notify(api.user, "API Key Deleted",
message="Your API key ID %s is invalid. It and its associated characters have been deleted." % api.api_id,
level="danger")
@task
def refresh_user_apis(user):
logger.debug('Refreshing all APIs belonging to user %s' % user)
apis = EveApiKeyPair.objects.filter(user=user)
for x in apis:
refresh_api(x)
# Check our main character
auth = AuthServicesInfo.objects.get_or_create(user=user)[0]
if auth.main_char_id:
if EveCharacter.objects.filter(character_id=auth.main_char_id).exists() is False:
logger.info(
"User %s main character id %s missing model. Clearning main character." % (user, auth.main_char_id))
auth.main_char_id = ''
auth.save()
notify(user, "Main Character Reset",
message="Your specified main character no longer has a model.\nThis could be the result of "
"an invalid API.\nYour main character ID has been reset.",
level="warn")
set_state(user)
@periodic_task(run_every=crontab(minute=0, hour="*/3"))
def run_api_refresh():
for u in User.objects.all():
refresh_user_apis.delay(u)
def populate_alliance(id, blue=False):
logger.debug("Populating alliance model with id %s blue %s" % (id, blue))
alliance_info = EveApiManager.get_alliance_information(id)
if not alliance_info:
raise ValueError("Supplied alliance id %s is invalid" % id)
if not EveAllianceInfo.objects.filter(alliance_id=id).exists():
EveManager.create_alliance_info(alliance_info['id'], alliance_info['name'], alliance_info['ticker'],
alliance_info['executor_id'], alliance_info['member_count'], blue)
alliance = EveAllianceInfo.objects.get(alliance_id=id)
for member_corp in alliance_info['member_corps']:
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
if corp.alliance != alliance:
corp.alliance = alliance
corp.save()
else:
logger.info("Creating new alliance member corp id %s" % member_corp)
corpinfo = EveApiManager.get_corporation_information(member_corp)
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], blue, alliance)
@task
def update_alliance(id):
alliance = EveAllianceInfo.objects.get(alliance_id=id)
corps = EveCorporationInfo.objects.filter(alliance=alliance)
logger.debug("Updating alliance %s with %s member corps" % (alliance, len(corps)))
allianceinfo = EveApiManager.get_alliance_information(alliance.alliance_id)
if allianceinfo:
EveManager.update_alliance_info(allianceinfo['id'], allianceinfo['executor_id'],
allianceinfo['member_count'], alliance.is_blue)
for corp in corps:
if corp.corporation_id in allianceinfo['member_corps'] is False:
logger.info("Corp %s no longer in alliance %s" % (corp, alliance))
corp.alliance = None
corp.save()
populate_alliance(alliance.alliance_id, blue=alliance.is_blue)
elif EveApiManager.check_if_alliance_exists(alliance.alliance_id) is False:
logger.info("Alliance %s has closed. Deleting model" % alliance)
alliance.delete()
@task
def update_corp(id):
corp = EveCorporationInfo.objects.get(corporation_id=id)
logger.debug("Updating corp %s" % corp)
corpinfo = EveApiManager.get_corporation_information(corp.corporation_id)
if corpinfo:
alliance = None
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
EveManager.update_corporation_info(corpinfo['id'], corpinfo['members']['current'], alliance, corp.is_blue)
elif EveApiManager.check_if_corp_exists(corp.corporation_id) is False:
logger.info("Corp %s has closed. Deleting model" % corp)
corp.delete()
# Run Every 2 hours
@periodic_task(run_every=crontab(minute=0, hour="*/2"))
def run_corp_update():
if EveApiManager.check_if_api_server_online() is False:
logger.warn("Aborted updating corp and alliance models: API server unreachable")
return
standing_level = 'alliance'
try:
# get corp info for owning corp if required
ownercorpinfo = {}
if settings.IS_CORP:
standing_level = 'corp'
logger.debug("Getting information for owning corp with id %s" % settings.CORP_ID)
ownercorpinfo = EveApiManager.get_corporation_information(settings.CORP_ID)
if not ownercorpinfo:
logger.error("Failed to retrieve corp info for owning corp id %s - bad corp id?" % settings.CORP_ID)
return
# check if we need to update an alliance model
alliance_id = ''
if ownercorpinfo and ownercorpinfo['alliance']['id']:
alliance_id = ownercorpinfo['alliance']['id']
elif settings.IS_CORP is False:
alliance_id = settings.ALLIANCE_ID
# get and create alliance info for owning alliance if required
alliance = None
if alliance_id:
logger.debug("Getting information for owning alliance with id %s" % alliance_id)
ownerallianceinfo = EveApiManager.get_alliance_information(alliance_id)
if not ownerallianceinfo:
logger.error("Failed to retrieve corp info for owning alliance id %s - bad alliance id?" % alliance_id)
return
if EveAllianceInfo.objects.filter(alliance_id=ownerallianceinfo['id']).exists():
logger.debug("Updating existing owner alliance model with id %s" % alliance_id)
EveManager.update_alliance_info(ownerallianceinfo['id'], ownerallianceinfo['executor_id'],
ownerallianceinfo['member_count'], False)
else:
populate_alliance(alliance_id)
alliance = EveAllianceInfo.objects.get(alliance_id=alliance_id)
# create corp info for owning corp if required
if ownercorpinfo:
if EveCorporationInfo.objects.filter(corporation_id=ownercorpinfo['id']).exists():
logger.debug("Updating existing owner corp model with id %s" % ownercorpinfo['id'])
EveManager.update_corporation_info(ownercorpinfo['id'], ownercorpinfo['members']['current'], alliance,
False)
else:
logger.info("Creating model for owning corp with id %s" % ownercorpinfo['id'])
EveManager.create_corporation_info(ownercorpinfo['id'], ownercorpinfo['name'], ownercorpinfo['ticker'],
ownercorpinfo['members']['current'], False, alliance)
# validate and create corp models for member corps of owning alliance
if alliance:
current_corps = EveCorporationInfo.objects.filter(alliance=alliance)
for corp in current_corps:
if corp.corporation_id in ownerallianceinfo['member_corps'] is False:
logger.info("Corp %s is no longer in owning alliance %s - updating model." % (corp, alliance))
corp.alliance = None
corp.save()
for member_corp in ownerallianceinfo['member_corps']:
if EveCorporationInfo.objects.filter(corporation_id=member_corp).exists():
corp = EveCorporationInfo.objects.get(corporation_id=member_corp)
if corp.alliance == alliance is not True:
logger.info("Associating corp %s with owning alliance %s" % (corp, alliance))
corp.alliance = alliance
corp.save()
else:
corpinfo = EveApiManager.get_corporation_information(member_corp)
logger.info("Creating model for owning alliance member corp with id %s" % corpinfo['id'])
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], False, alliance)
# update existing corp models
for corp in EveCorporationInfo.objects.all():
update_corp.delay(corp.corporation_id)
# update existing alliance models
for alliance in EveAllianceInfo.objects.all():
update_alliance.delay(alliance.alliance_id)
# create standings
standings = EveApiManager.get_corp_standings()
if standings:
standings = standings[standing_level]
for standing in standings:
if int(standings[standing]['standing']) >= settings.BLUE_STANDING:
logger.debug("Standing %s meets threshold" % standing)
if EveApiManager.check_if_id_is_alliance(standing):
logger.debug("Standing %s is an alliance" % standing)
if EveAllianceInfo.objects.filter(alliance_id=standing).exists():
alliance = EveAllianceInfo.objects.get(alliance_id=standing)
if alliance.is_blue is not True:
logger.info("Updating alliance %s as blue" % alliance)
alliance.is_blue = True
alliance.save()
else:
populate_alliance(standing, blue=True)
elif EveApiManager.check_if_id_is_corp(standing):
logger.debug("Standing %s is a corp" % standing)
if EveCorporationInfo.objects.filter(corporation_id=standing).exists():
corp = EveCorporationInfo.objects.get(corporation_id=standing)
if corp.is_blue is not True:
logger.info("Updating corp %s as blue" % corp)
corp.is_blue = True
corp.save()
else:
logger.info("Creating model for blue corp with id %s" % standing)
corpinfo = EveApiManager.get_corporation_information(standing)
corp_alliance = None
if EveAllianceInfo.objects.filter(alliance_id=corpinfo['alliance']['id']).exists():
logger.debug("New corp model for standing %s has existing alliance model" % standing)
corp_alliance = EveAllianceInfo.objects.get(alliance_id=corpinfo['alliance']['id'])
EveManager.create_corporation_info(corpinfo['id'], corpinfo['name'], corpinfo['ticker'],
corpinfo['members']['current'], True, corp_alliance)
# update alliance standings
for alliance in EveAllianceInfo.objects.filter(is_blue=True):
if int(alliance.alliance_id) in standings:
if float(standings[int(alliance.alliance_id)]['standing']) < float(settings.BLUE_STANDING):
logger.info("Alliance %s no longer meets minimum blue standing threshold" % alliance)
alliance.is_blue = False
alliance.save()
else:
logger.info("Alliance %s no longer in standings" % alliance)
alliance.is_blue = False
alliance.save()
# update corp standings
for corp in EveCorporationInfo.objects.filter(is_blue=True):
if int(corp.corporation_id) in standings:
if float(standings[int(corp.corporation_id)]['standing']) < float(settings.BLUE_STANDING):
logger.info("Corp %s no longer meets minimum blue standing threshold" % corp)
corp.is_blue = False
corp.save()
else:
if corp.alliance:
if not corp.alliance.is_blue:
logger.info("Corp %s and its alliance %s are no longer blue" % (corp, corp.alliance))
corp.is_blue = False
corp.save()
else:
logger.info("Corp %s is no longer blue" % corp)
corp.is_blue = False
corp.save()
# delete unnecessary alliance models
for alliance in EveAllianceInfo.objects.filter(is_blue=False):
logger.debug("Checking to delete alliance %s" % alliance)
if not settings.IS_CORP:
if not alliance.alliance_id == settings.ALLIANCE_ID:
logger.info("Deleting unnecessary alliance model %s" % alliance)
alliance.delete()
else:
if not alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists():
logger.info("Deleting unnecessary alliance model %s" % alliance)
alliance.delete()
# delete unnecessary corp models
for corp in EveCorporationInfo.objects.filter(is_blue=False):
logger.debug("Checking to delete corp %s" % corp)
if not settings.IS_CORP:
if corp.alliance:
logger.debug("Corp %s has alliance %s" % (corp, corp.alliance))
if not corp.alliance.alliance_id == settings.ALLIANCE_ID:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
if corp.corporation_id != settings.CORP_ID:
logger.debug("Corp %s is not owning corp" % corp)
if corp.alliance:
logger.debug("Corp %s has alliance %s" % (corp, corp.alliance))
if not corp.alliance.evecorporationinfo_set.filter(corporation_id=settings.CORP_ID).exists():
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.info("Deleting unnecessary corp model %s" % corp)
corp.delete()
else:
logger.debug("Corp %s is owning corp" % corp)
except evelink.api.APIError as e:
logger.error("Model update failed with error code %s" % e.code)

View File

@ -1,59 +1,27 @@
from django.conf import settings from __future__ import unicode_literals
from django.http import HttpResponseRedirect from django.shortcuts import render, redirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required from django.contrib import messages
from util import add_member_permission from eveonline.forms import UpdateKeyForm
from util import remove_member_permission from eveonline.managers import EveManager
from util import check_if_user_has_permission
from forms import UpdateKeyForm
from managers import EveManager
from authentication.managers import AuthServicesInfoManager from authentication.managers import AuthServicesInfoManager
from services.managers.eve_api_manager import EveApiManager from services.managers.eve_api_manager import EveApiManager
from util.common_task import add_user_to_group
from util.common_task import remove_user_from_group
from util.common_task import deactivate_services
from util.common_task import generate_corp_group_name
from eveonline.models import EveCorporationInfo
from eveonline.models import EveCharacter
from eveonline.models import EveApiKeyPair from eveonline.models import EveApiKeyPair
from authentication.models import AuthServicesInfo from authentication.models import AuthServicesInfo
from celerytask.tasks import determine_membership_by_user from authentication.tasks import set_state
from celerytask.tasks import set_state from eveonline.tasks import refresh_api
from celerytask.tasks import refresh_api
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def disable_member(user, char_id):
logger.debug("Disabling user %s with character id %s" % (user, char_id))
remove_member_permission(user, 'member')
remove_user_from_group(user, settings.DEFAULT_AUTH_GROUP)
remove_user_from_group(user,
generate_corp_group_name(
EveManager.get_character_by_id(char_id).corporation_name))
deactivate_services(user)
logger.info("Disabled member %s" % user)
def disable_blue_member(user):
logger.debug("Disabling blue user %s" % user)
remove_member_permission(user, 'blue_member')
remove_user_from_group(user, settings.DEFAULT_BLUE_GROUP)
deactivate_services(user)
logger.info("Disabled blue user %s" % user)
@login_required @login_required
def add_api_key(request): def add_api_key(request):
logger.debug("add_api_key called by user %s" % request.user) logger.debug("add_api_key called by user %s" % request.user)
user_state = determine_membership_by_user(request.user)
if request.method == 'POST': if request.method == 'POST':
form = UpdateKeyForm(request.POST) form = UpdateKeyForm(request.user, request.POST)
form.user_state=user_state
logger.debug("Request type POST with form valid: %s" % form.is_valid()) logger.debug("Request type POST with form valid: %s" % form.is_valid())
if form.is_valid(): if form.is_valid():
EveManager.create_api_keypair(form.cleaned_data['api_id'], EveManager.create_api_keypair(form.cleaned_data['api_id'],
@ -65,16 +33,18 @@ def add_api_key(request):
form.cleaned_data['api_key']) form.cleaned_data['api_key'])
EveManager.create_characters_from_list(characters, request.user, form.cleaned_data['api_id']) EveManager.create_characters_from_list(characters, request.user, form.cleaned_data['api_id'])
logger.info("Successfully processed api add form for user %s" % request.user) logger.info("Successfully processed api add form for user %s" % request.user)
return HttpResponseRedirect("/api_key_management/") messages.success(request, 'Added API key %s to your account.' % form.cleaned_data['api_id'])
auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
if not auth.main_char_id:
messages.warning(request, 'Please select a main character.')
return redirect("/api_key_management/")
else: else:
logger.debug("Form invalid: returning to form.") logger.debug("Form invalid: returning to form.")
else: else:
logger.debug("Providing empty update key form for user %s" % request.user) logger.debug("Providing empty update key form for user %s" % request.user)
form = UpdateKeyForm() form = UpdateKeyForm(request.user)
form.user_state = user_state
context = {'form': form, 'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} context = {'form': form, 'apikeypairs': EveManager.get_api_key_pairs(request.user.id)}
return render_to_response('registered/addapikey.html', context, return render(request, 'registered/addapikey.html', context=context)
context_instance=RequestContext(request))
@login_required @login_required
@ -82,51 +52,48 @@ def api_key_management_view(request):
logger.debug("api_key_management_view called by user %s" % request.user) logger.debug("api_key_management_view called by user %s" % request.user)
context = {'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} context = {'apikeypairs': EveManager.get_api_key_pairs(request.user.id)}
return render_to_response('registered/apikeymanagment.html', context, return render(request, 'registered/apikeymanagment.html', context=context)
context_instance=RequestContext(request))
@login_required @login_required
def api_key_removal(request, api_id): def api_key_removal(request, api_id):
logger.debug("api_key_removal called by user %s for api id %s" % (request.user, api_id)) logger.debug("api_key_removal called by user %s for api id %s" % (request.user, api_id))
authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
# Check if our users main id is in the to be deleted characters # Check if our users main id is in the to be deleted characters
characters = EveManager.get_characters_by_owner_id(request.user.id) characters = EveManager.get_characters_by_owner_id(request.user.id)
if characters is not None: if characters is not None:
for character in characters: for character in characters:
if character.character_id == authinfo.main_char_id: if character.character_id == authinfo.main_char_id:
if character.api_id == api_id: if character.api_id == api_id:
# TODO: Remove services also messages.warning(request,
if authinfo.is_blue: 'You have deleted your main character. Please select a new main character.')
logger.debug("Blue user %s deleting api for main character. Disabling." % request.user) set_state(request.user)
disable_blue_member(request.user)
else:
logger.debug("User %s deleting api for main character. Disabling." % request.user)
disable_member(request.user, authinfo.main_char_id)
EveManager.delete_api_key_pair(api_id, request.user.id) EveManager.delete_api_key_pair(api_id, request.user.id)
EveManager.delete_characters_by_api_id(api_id, request.user.id) EveManager.delete_characters_by_api_id(api_id, request.user.id)
messages.success(request, 'Deleted API key %s' % api_id)
logger.info("Succesfully processed api delete request by user %s for api %s" % (request.user, api_id)) logger.info("Succesfully processed api delete request by user %s for api %s" % (request.user, api_id))
return HttpResponseRedirect("/api_key_management/") return redirect("auth_api_key_management")
@login_required @login_required
def characters_view(request): def characters_view(request):
logger.debug("characters_view called by user %s" % request.user) logger.debug("characters_view called by user %s" % request.user)
render_items = {'characters': EveManager.get_characters_by_owner_id(request.user.id), render_items = {'characters': EveManager.get_characters_by_owner_id(request.user.id),
'authinfo': AuthServicesInfoManager.get_auth_service_info(request.user)} 'authinfo': AuthServicesInfo.objects.get_or_create(user=request.user)[0]}
return render_to_response('registered/characters.html', render_items, context_instance=RequestContext(request)) return render(request, 'registered/characters.html', context=render_items)
@login_required @login_required
def main_character_change(request, char_id): def main_character_change(request, char_id):
logger.debug("main_character_change called by user %s for character id %s" % (request.user, char_id)) logger.debug("main_character_change called by user %s for character id %s" % (request.user, char_id))
if EveManager.check_if_character_owned_by_user(char_id, request.user): if EveManager.check_if_character_owned_by_user(char_id, request.user):
AuthServicesInfoManager.update_main_char_Id(char_id, request.user) AuthServicesInfoManager.update_main_char_id(char_id, request.user)
set_state(request.user) set_state(request.user)
return HttpResponseRedirect("/characters/") messages.success(request, 'Changed main character ID to %s' % char_id)
return HttpResponseRedirect("/characters/") return redirect("auth_characters")
messages.error(request, 'Failed to change main character - selected character is not owned by your account.')
return redirect("auth_characters")
@login_required @login_required
@ -136,9 +103,12 @@ def user_refresh_api(request, api_id):
api_key_pair = EveApiKeyPair.objects.get(api_id=api_id) api_key_pair = EveApiKeyPair.objects.get(api_id=api_id)
if api_key_pair.user == request.user: if api_key_pair.user == request.user:
refresh_api(api_key_pair) refresh_api(api_key_pair)
messages.success(request, 'Refreshed API key %s' % api_id)
set_state(request.user) set_state(request.user)
else: else:
messages.warning(request, 'You are not authorized to refresh that API key.')
logger.warn("User %s not authorized to refresh api id %s" % (request.user, api_id)) logger.warn("User %s not authorized to refresh api id %s" % (request.user, api_id))
else: else:
messages.warning(request, 'Unable to locate API key %s' % api_id)
logger.warn("User %s unable to refresh api id %s - api key not found" % (request.user, api_id)) logger.warn("User %s unable to refresh api id %s - api key not found" % (request.user, api_id))
return HttpResponseRedirect("/api_key_management/") return redirect("auth_api_key_management")

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import Fatlink, Fat from fleetactivitytracking.models import Fatlink, Fat
admin.site.register(Fatlink) admin.site.register(Fatlink)

View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class FatConfig(AppConfig):
name = 'fleetactivitytracking'

View File

@ -1,7 +1,9 @@
from __future__ import unicode_literals
from django import forms from django import forms
from optimer.models import optimer from optimer.models import optimer
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
def get_fleet_list(): def get_fleet_list():
fleets = optimer.objects.all() fleets = optimer.objects.all()
fleetlist = [("None", "None")] fleetlist = [("None", "None")]
@ -13,5 +15,6 @@ def get_fleet_list():
class FatlinkForm(forms.Form): class FatlinkForm(forms.Form):
fatname = forms.CharField(label=_('Name of fat-link'), required=True) fatname = forms.CharField(label=_('Name of fat-link'), required=True)
duration = forms.IntegerField(label=_("Duration of fat-link"), required=True, initial=30, min_value=1, max_value=2147483647) duration = forms.IntegerField(label=_("Duration of fat-link"), required=True, initial=30, min_value=1,
max_value=2147483647)
fleet = forms.ModelChoiceField(label=_("Fleet"), queryset=optimer.objects.all().order_by('operation_name')) fleet = forms.ModelChoiceField(label=_("Fleet"), queryset=optimer.objects.all().order_by('operation_name'))

View File

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:39
from __future__ import unicode_literals
import datetime
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
from django.utils.timezone import utc
import fleetactivitytracking.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('eveonline', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Fat',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('system', models.CharField(max_length=30)),
('shiptype', models.CharField(max_length=30)),
('station', models.CharField(max_length=125)),
('character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')),
],
),
migrations.CreateModel(
name='Fatlink',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fatdatetime', models.DateTimeField(default=datetime.datetime(2016, 9, 5, 21, 39, 17, 307954, tzinfo=utc))),
('duration', models.PositiveIntegerField()),
('fleet', models.CharField(default=b'', max_length=254)),
('name', models.CharField(max_length=254)),
('hash', models.CharField(max_length=254, unique=True)),
('creator', models.ForeignKey(on_delete=models.SET(fleetactivitytracking.models.get_sentinel_user), to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='fat',
name='fatlink',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fleetactivitytracking.Fatlink'),
),
migrations.AddField(
model_name='fat',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='fat',
unique_together=set([('character', 'fatlink')]),
),
]

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 22:20
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('fleetactivitytracking', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='fatlink',
name='fatdatetime',
field=models.DateTimeField(default=datetime.datetime(2016, 9, 5, 22, 20, 2, 999041, tzinfo=utc)),
),
]

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-06 23:54
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('fleetactivitytracking', '0002_auto_20160905_2220'),
]
operations = [
migrations.AlterField(
model_name='fatlink',
name='fatdatetime',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

View File

@ -1,16 +1,18 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from optimer.models import optimer
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
from datetime import datetime
from datetime import date
from django.utils import timezone from django.utils import timezone
def get_sentinel_user(): def get_sentinel_user():
return User.objects.get_or_create(username='deleted')[0] return User.objects.get_or_create(username='deleted')[0]
@python_2_unicode_compatible
class Fatlink(models.Model): class Fatlink(models.Model):
fatdatetime = models.DateTimeField(default=timezone.now()) fatdatetime = models.DateTimeField(default=timezone.now)
duration = models.PositiveIntegerField() duration = models.PositiveIntegerField()
fleet = models.CharField(max_length=254, default="") fleet = models.CharField(max_length=254, default="")
name = models.CharField(max_length=254) name = models.CharField(max_length=254)
@ -21,6 +23,7 @@ class Fatlink(models.Model):
return self.name return self.name
@python_2_unicode_compatible
class Fat(models.Model): class Fat(models.Model):
character = models.ForeignKey(EveCharacter, on_delete=models.CASCADE) character = models.ForeignKey(EveCharacter, on_delete=models.CASCADE)
fatlink = models.ForeignKey(Fatlink) fatlink = models.ForeignKey(Fatlink)

View File

@ -1,19 +1,17 @@
from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.shortcuts import HttpResponseRedirect from django.shortcuts import render, redirect
from django.shortcuts import render_to_response
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.template import RequestContext
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils import timezone from django.utils import timezone
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
from eveonline.models import EveCorporationInfo from eveonline.models import EveCorporationInfo
from eveonline.managers import EveManager from eveonline.managers import EveManager
from util import check_if_user_has_permission from fleetactivitytracking.forms import FatlinkForm
from forms import FatlinkForm from fleetactivitytracking.models import Fatlink, Fat
from models import Fatlink, Fat
from slugify import slugify from slugify import slugify
@ -23,7 +21,6 @@ import string
import random import random
import datetime import datetime
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -41,12 +38,14 @@ class CorpStat(object):
def avg_fat(self): def avg_fat(self):
return "%.2f" % (float(self.n_fats) / float(self.corp.member_count)) return "%.2f" % (float(self.n_fats) / float(self.corp.member_count))
def first_day_of_next_month(year, month): def first_day_of_next_month(year, month):
if month == 12: if month == 12:
return datetime.datetime(year + 1, 1, 1) return datetime.datetime(year + 1, 1, 1)
else: else:
return datetime.datetime(year, month + 1, 1) return datetime.datetime(year, month + 1, 1)
def first_day_of_previous_month(year, month): def first_day_of_previous_month(year, month):
if month == 1: if month == 1:
return datetime.datetime(year - 1, 12, 1) return datetime.datetime(year - 1, 12, 1)
@ -63,14 +62,14 @@ def fatlink_view(request):
logger.debug("fatlink_view called by user %s" % request.user) logger.debug("fatlink_view called by user %s" % request.user)
latest_fats = Fat.objects.filter(user=user).order_by('-id')[:5] latest_fats = Fat.objects.filter(user=user).order_by('-id')[:5]
if check_if_user_has_permission(user, 'fleetactivitytracking'): if user.has_perm('auth.fleetactivitytracking'):
latest_links = Fatlink.objects.all().order_by('-id')[:5] latest_links = Fatlink.objects.all().order_by('-id')[:5]
context = {'user': user, 'fats': latest_fats, 'fatlinks': latest_links} context = {'user': user, 'fats': latest_fats, 'fatlinks': latest_links}
else: else:
context = {'user': user, 'fats': latest_fats} context = {'user': user, 'fats': latest_fats}
return render_to_response('registered/fatlinkview.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkview.html', context=context)
@login_required @login_required
@ -91,7 +90,8 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date
for corp in alliance_corps: for corp in alliance_corps:
fatStats[corp.corporation_name] = CorpStat(corp.corporation_id, corp=corp) fatStats[corp.corporation_name] = CorpStat(corp.corporation_id, corp=corp)
fatlinks_in_span = Fatlink.objects.filter(fatdatetime__gte = start_of_month).filter(fatdatetime__lt = start_of_next_month) fatlinks_in_span = Fatlink.objects.filter(fatdatetime__gte=start_of_month).filter(
fatdatetime__lt=start_of_next_month)
for fatlink in fatlinks_in_span: for fatlink in fatlinks_in_span:
fats_in_fatlink = Fat.objects.filter(fatlink=fatlink) fats_in_fatlink = Fat.objects.filter(fatlink=fatlink)
@ -105,12 +105,13 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date
fatStatsList.sort(key=lambda stat: (stat.n_fats, stat.n_fats / stat.corp.member_count), reverse=True) fatStatsList.sort(key=lambda stat: (stat.n_fats, stat.n_fats / stat.corp.member_count), reverse=True)
if datetime.datetime.now() > start_of_next_month: if datetime.datetime.now() > start_of_next_month:
context = {'fatStats':fatStatsList, 'month':start_of_month.strftime("%B"), 'year':year, 'previous_month': start_of_previous_month,'next_month': start_of_next_month} context = {'fatStats': fatStatsList, 'month': start_of_month.strftime("%B"), 'year': year,
'previous_month': start_of_previous_month, 'next_month': start_of_next_month}
else: else:
context = {'fatStats':fatStatsList, 'month':start_of_month.strftime("%B"), 'year':year, 'previous_month': start_of_previous_month} context = {'fatStats': fatStatsList, 'month': start_of_month.strftime("%B"), 'year': year,
'previous_month': start_of_previous_month}
return render_to_response('registered/fatlinkstatisticsview.html', context, context_instance=RequestContext(request))
return render(request, 'registered/fatlinkstatisticsview.html', context=context)
@login_required @login_required
@ -133,11 +134,12 @@ def fatlink_personal_statistics_view(request, year=datetime.date.today().year, m
monthlystats = [(i + 1, datetime.date(year, i + 1, 1).strftime("%h"), monthlystats[i]) for i in range(12)] monthlystats = [(i + 1, datetime.date(year, i + 1, 1).strftime("%h"), monthlystats[i]) for i in range(12)]
if datetime.datetime.now() > datetime.datetime(year + 1, 1, 1): if datetime.datetime.now() > datetime.datetime(year + 1, 1, 1):
context = {'user':user, 'monthlystats': monthlystats, 'year':year, 'previous_year':year-1, 'next_year':year+1} context = {'user': user, 'monthlystats': monthlystats, 'year': year, 'previous_year': year - 1,
'next_year': year + 1}
else: else:
context = {'user': user, 'monthlystats': monthlystats, 'year': year, 'previous_year': year - 1} context = {'user': user, 'monthlystats': monthlystats, 'year': year, 'previous_year': year - 1}
return render_to_response('registered/fatlinkpersonalstatisticsview.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkpersonalstatisticsview.html', context=context)
@login_required @login_required
@ -148,13 +150,14 @@ def fatlink_monthly_personal_statistics_view(request, year, month, char_id=None)
start_of_next_month = first_day_of_next_month(year, month) start_of_next_month = first_day_of_next_month(year, month)
start_of_previous_month = first_day_of_previous_month(year, month) start_of_previous_month = first_day_of_previous_month(year, month)
if check_if_user_has_permission(request.user, 'fleetactivitytracking_statistics') and char_id: if request.user.has_perm('auth.fleetactivitytracking_statistics') and char_id:
user = EveCharacter.objects.get(character_id=char_id).user user = EveCharacter.objects.get(character_id=char_id).user
else: else:
user = request.user user = request.user
logger.debug("Personal monthly statistics view for user %s called by %s" % (user, request.user)) logger.debug("Personal monthly statistics view for user %s called by %s" % (user, request.user))
personal_fats = Fat.objects.filter(user=user).filter(fatlink__fatdatetime__gte = start_of_month).filter(fatlink__fatdatetime__lt = start_of_next_month) personal_fats = Fat.objects.filter(user=user).filter(fatlink__fatdatetime__gte=start_of_month).filter(
fatlink__fatdatetime__lt=start_of_next_month)
ship_statistics = dict() ship_statistics = dict()
n_fats = 0 n_fats = 0
@ -165,11 +168,12 @@ def fatlink_monthly_personal_statistics_view(request, year, month, char_id=None)
'year': year, 'n_fats': n_fats, 'char_id': char_id, 'previous_month': start_of_previous_month, 'year': year, 'n_fats': n_fats, 'char_id': char_id, 'previous_month': start_of_previous_month,
'next_month': start_of_next_month} 'next_month': start_of_next_month}
created_fats = Fatlink.objects.filter(creator=user).filter(fatdatetime__gte = start_of_month).filter(fatdatetime__lt = start_of_next_month) created_fats = Fatlink.objects.filter(creator=user).filter(fatdatetime__gte=start_of_month).filter(
fatdatetime__lt=start_of_next_month)
context["created_fats"] = created_fats context["created_fats"] = created_fats
context["n_created_fats"] = len(created_fats) context["n_created_fats"] = len(created_fats)
return render_to_response('registered/fatlinkpersonalmonthlystatisticsview.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkpersonalmonthlystatisticsview.html', context=context)
@login_required @login_required
@ -182,10 +186,8 @@ def click_fatlink_view(request, hash, fatname):
# Retrieve the latest fatlink using the hash. # Retrieve the latest fatlink using the hash.
try: try:
fatlink = Fatlink.objects.filter(hash=hash)[0] fatlink = Fatlink.objects.filter(hash=hash)[0]
valid = True
if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration * 60)): if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration * 60)):
active = True
character = EveManager.get_character_by_id(request.META['HTTP_EVE_CHARID']) character = EveManager.get_character_by_id(request.META['HTTP_EVE_CHARID'])
@ -210,15 +212,16 @@ def click_fatlink_view(request, hash, fatname):
messages.append(message[0].decode()) messages.append(message[0].decode())
context = {'trusted': True, 'errormessages': messages} context = {'trusted': True, 'errormessages': messages}
else: else:
context = {'character_id': request.META['HTTP_EVE_CHARID'], 'character_name': request.META['HTTP_EVE_CHARNAME']} context = {'character_id': request.META['HTTP_EVE_CHARID'],
return render_to_response('public/characternotexisting.html', context, context_instance=RequestContext(request)) 'character_name': request.META['HTTP_EVE_CHARNAME']}
return render(request, 'public/characternotexisting.html', context=context)
else: else:
context = {'trusted': True, 'expired': True} context = {'trusted': True, 'expired': True}
except ObjectDoesNotExist: except ObjectDoesNotExist:
context = {'trusted': True} context = {'trusted': True}
else: else:
context = {'trusted': False, 'fatname': fatname} context = {'trusted': False, 'fatname': fatname}
return render_to_response('public/clickfatlinkview.html', context, context_instance=RequestContext(request)) return render(request, 'public/clickfatlinkview.html', context=context)
@login_required @login_required
@ -247,12 +250,12 @@ def create_fatlink_view(request):
for errorname, message in e.message_dict.items(): for errorname, message in e.message_dict.items():
messages.append(message[0].decode()) messages.append(message[0].decode())
context = {'form': form, 'errormessages': messages} context = {'form': form, 'errormessages': messages}
return render_to_response('registered/fatlinkformatter.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkformatter.html', context=context)
else: else:
form = FatlinkForm() form = FatlinkForm()
context = {'form': form, 'badrequest': True} context = {'form': form, 'badrequest': True}
return render_to_response('registered/fatlinkformatter.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkformatter.html', context=context)
return HttpResponseRedirect('/fat/') return redirect('auth_fatlink_view')
else: else:
form = FatlinkForm() form = FatlinkForm()
@ -260,7 +263,7 @@ def create_fatlink_view(request):
context = {'form': form} context = {'form': form}
return render_to_response('registered/fatlinkformatter.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkformatter.html', context=context)
@login_required @login_required
@ -268,25 +271,24 @@ def create_fatlink_view(request):
def modify_fatlink_view(request, hash=""): def modify_fatlink_view(request, hash=""):
logger.debug("modify_fatlink_view called by user %s" % request.user) logger.debug("modify_fatlink_view called by user %s" % request.user)
if not hash: if not hash:
return HttpResponseRedirect('/fat/') return redirect('/fat/')
fatlink = Fatlink.objects.filter(hash=hash)[0] fatlink = Fatlink.objects.filter(hash=hash)[0]
if(request.GET.get('removechar')): if request.GET.get('removechar'):
character_id = request.GET.get('removechar') character_id = request.GET.get('removechar')
character = EveCharacter.objects.get(character_id=character_id) character = EveCharacter.objects.get(character_id=character_id)
logger.debug("Removing character %s from fleetactivitytracking %s" % (character.character_name, fatlink.name)) logger.debug("Removing character %s from fleetactivitytracking %s" % (character.character_name, fatlink.name))
Fat.objects.filter(fatlink=fatlink).filter(character=character).delete() Fat.objects.filter(fatlink=fatlink).filter(character=character).delete()
if(request.GET.get('deletefat')): if request.GET.get('deletefat'):
logger.debug("Removing fleetactivitytracking %s" % fatlink.name) logger.debug("Removing fleetactivitytracking %s" % fatlink.name)
fatlink.delete() fatlink.delete()
return HttpResponseRedirect('/fat/') return redirect('/fat/')
registered_fats = Fat.objects.filter(fatlink=fatlink).order_by('character') registered_fats = Fat.objects.filter(fatlink=fatlink).order_by('character')
context = {'fatlink': fatlink, 'registered_fats': registered_fats} context = {'fatlink': fatlink, 'registered_fats': registered_fats}
return render_to_response('registered/fatlinkmodify.html', context, context_instance=RequestContext(request)) return render(request, 'registered/fatlinkmodify.html', context=context)

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

7
fleetup/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class FleetupConfig(AppConfig):
name = 'fleetup'

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,42 +1,24 @@
from __future__ import unicode_literals
import datetime import datetime
from operator import itemgetter, attrgetter, methodcaller from django.shortcuts import render
from django.utils.timezone import utc
from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import user_passes_test
from django.shortcuts import HttpResponseRedirect
from django.template.defaulttags import register from django.template.defaulttags import register
from django.contrib.humanize.templatetags.humanize import intword
from collections import namedtuple
from authentication.managers import AuthServicesInfoManager
from util import check_if_user_has_permission
from services.managers.eve_api_manager import EveApiManager
from services.managers.fleetup_manager import FleetUpManager from services.managers.fleetup_manager import FleetUpManager
from eveonline.models import EveCorporationInfo from authentication.decorators import members_and_blues
from eveonline.models import EveAllianceInfo
from eveonline.models import EveCharacter
from authentication.models import AuthServicesInfo
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@register.filter @register.filter
def get_item(dictionary, key): def get_item(dictionary, key):
return dictionary.get(key) return dictionary.get(key)
def fleetup_util_test(user):
return check_if_user_has_permission(user, 'member') or check_if_user_has_permission(user, 'blue_member')
@login_required @login_required
@user_passes_test(fleetup_util_test) @members_and_blues()
def fleetup_view(request): def fleetup_view(request):
logger.debug("fleetup_view called by user %s" % request.user) logger.debug("fleetup_view called by user %s" % request.user)
@ -48,7 +30,8 @@ def fleetup_view(request):
"operations_list": sorted(operations_list.items()), "operations_list": sorted(operations_list.items()),
"now": now} "now": now}
return render_to_response('registered/fleetup.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetup.html', context=context)
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
@ -59,18 +42,20 @@ def fleetup_characters(request):
context = {"member_list": sorted(member_list.items())} context = {"member_list": sorted(member_list.items())}
return render_to_response('registered/fleetupcharacters.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetupcharacters.html', context=context)
@login_required @login_required
@user_passes_test(fleetup_util_test) @members_and_blues()
def fleetup_fittings(request): def fleetup_fittings(request):
logger.debug("fleetup_fittings called by user %s" % request.user) logger.debug("fleetup_fittings called by user %s" % request.user)
fitting_list = FleetUpManager.get_fleetup_fittings() fitting_list = FleetUpManager.get_fleetup_fittings()
context = {"fitting_list": sorted(fitting_list.items())} context = {"fitting_list": sorted(fitting_list.items())}
return render_to_response('registered/fleetupfittingsview.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetupfittingsview.html', context=context)
@login_required @login_required
@user_passes_test(fleetup_util_test) @members_and_blues()
def fleetup_fitting(request, fittingnumber): def fleetup_fitting(request, fittingnumber):
logger.debug("fleetup_fitting called by user %s" % request.user) logger.debug("fleetup_fitting called by user %s" % request.user)
fitting_eft = FleetUpManager.get_fleetup_fitting_eft(fittingnumber) fitting_eft = FleetUpManager.get_fleetup_fitting_eft(fittingnumber)
@ -80,22 +65,22 @@ def fleetup_fitting(request, fittingnumber):
context = {"fitting_eft": fitting_eft, context = {"fitting_eft": fitting_eft,
"fitting_data": fitting_data, "fitting_data": fitting_data,
"doctrines_list": doctrines_list} "doctrines_list": doctrines_list}
return render_to_response('registered/fleetupfitting.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetupfitting.html', context=context)
@login_required @login_required
@user_passes_test(fleetup_util_test) @members_and_blues()
def fleetup_doctrines(request): def fleetup_doctrines(request):
logger.debug("fleetup_doctrines called by user %s" % request.user) logger.debug("fleetup_doctrines called by user %s" % request.user)
doctrines_list = FleetUpManager.get_fleetup_doctrines() doctrines_list = FleetUpManager.get_fleetup_doctrines()
context = {"doctrines_list": doctrines_list} context = {"doctrines_list": doctrines_list}
return render_to_response('registered/fleetupdoctrinesview.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetupdoctrinesview.html', context=context)
@login_required @login_required
@user_passes_test(fleetup_util_test) @members_and_blues()
def fleetup_doctrine(request, doctrinenumber): def fleetup_doctrine(request, doctrinenumber):
logger.debug("fleetup_doctrine called by user %s" % request.user) logger.debug("fleetup_doctrine called by user %s" % request.user)
doctrine = FleetUpManager.get_fleetup_doctrine(doctrinenumber) doctrine = FleetUpManager.get_fleetup_doctrine(doctrinenumber)
context = {"doctrine": doctrine} context = {"doctrine": doctrine}
return render_to_response('registered/fleetupdoctrine.html',context, context_instance=RequestContext(request) ) return render(request, 'registered/fleetupdoctrine.html', context=context)

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,9 +1,10 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import GroupDescription from groupmanagement.models import GroupDescription
from models import GroupRequest from groupmanagement.models import GroupRequest
from models import HiddenGroup from groupmanagement.models import HiddenGroup
from models import OpenGroup from groupmanagement.models import OpenGroup
admin.site.register(GroupDescription) admin.site.register(GroupDescription)

7
groupmanagement/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class GroupManagementConfig(AppConfig):
name = 'groupmanagement'

View File

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:39
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0008_alter_user_username_max_length'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('eveonline', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='GroupDescription',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('description', models.CharField(max_length=512)),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group', unique=True)),
],
),
migrations.CreateModel(
name='GroupRequest',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.CharField(max_length=254)),
('leave_request', models.BooleanField(default=0)),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
('main_char', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='HiddenGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group', unique=True)),
],
),
migrations.CreateModel(
name='OpenGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')),
],
),
]

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-06 23:54
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('groupmanagement', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='groupdescription',
name='group',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
),
migrations.AlterField(
model_name='hiddengroup',
name='group',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
),
]

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-09 23:22
from __future__ import unicode_literals
from django.db import migrations
from django.conf import settings
def create_groups(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
Group.objects.get_or_create(name=settings.DEFAULT_AUTH_GROUP)
Group.objects.get_or_create(name=settings.DEFAULT_BLUE_GROUP)
def reverse(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('groupmanagement', '0002_auto_20160906_2354'),
]
operations = [
migrations.RunPython(create_groups, reverse)
]

View File

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
@ -5,14 +7,16 @@ from django.contrib.auth.models import Group
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
@python_2_unicode_compatible
class GroupDescription(models.Model): class GroupDescription(models.Model):
description = models.CharField(max_length=512) description = models.CharField(max_length=512)
group = models.ForeignKey(Group, unique=True) group = models.OneToOneField(Group)
def __str__(self): def __str__(self):
return self.group.name + " - Description" return self.group.name + " - Description"
@python_2_unicode_compatible
class GroupRequest(models.Model): class GroupRequest(models.Model):
status = models.CharField(max_length=254) status = models.CharField(max_length=254)
leave_request = models.BooleanField(default=0) leave_request = models.BooleanField(default=0)
@ -23,12 +27,16 @@ class GroupRequest(models.Model):
def __str__(self): def __str__(self):
return self.user.username + ":" + self.group.name return self.user.username + ":" + self.group.name
@python_2_unicode_compatible
class HiddenGroup(models.Model): class HiddenGroup(models.Model):
group = models.ForeignKey(Group, unique=True) group = models.OneToOneField(Group)
def __str__(self): def __str__(self):
return self.group.name + " - Hidden" return self.group.name + " - Hidden"
@python_2_unicode_compatible
class OpenGroup(models.Model): class OpenGroup(models.Model):
group = models.OneToOneField(Group) group = models.OneToOneField(Group)

View File

@ -1,16 +1,16 @@
from django.template import RequestContext from __future__ import unicode_literals
from django.shortcuts import HttpResponseRedirect from django.shortcuts import render, redirect
from django.shortcuts import render_to_response
from django.conf import settings from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib import messages
from notifications import notify from notifications import notify
from models import GroupDescription from groupmanagement.models import GroupDescription
from models import GroupRequest from groupmanagement.models import GroupRequest
from models import HiddenGroup from groupmanagement.models import HiddenGroup
from models import OpenGroup from groupmanagement.models import OpenGroup
from authentication.managers import AuthServicesInfoManager from authentication.models import AuthServicesInfo
from eveonline.managers import EveManager from eveonline.managers import EveManager
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -18,6 +18,7 @@ import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@login_required @login_required
@permission_required('auth.group_management') @permission_required('auth.group_management')
def group_management(request): def group_management(request):
@ -30,12 +31,12 @@ def group_management(request):
leaverequests.append(grouprequest) leaverequests.append(grouprequest)
else: else:
acceptrequests.append(grouprequest) acceptrequests.append(grouprequest)
logger.debug("Providing user %s with %s acceptrequests and %s leaverequests." % (request.user, len(acceptrequests), len(leaverequests))) logger.debug("Providing user %s with %s acceptrequests and %s leaverequests." % (
request.user, len(acceptrequests), len(leaverequests)))
render_items = {'acceptrequests': acceptrequests, 'leaverequests': leaverequests} render_items = {'acceptrequests': acceptrequests, 'leaverequests': leaverequests}
return render_to_response('registered/groupmanagement.html', return render(request, 'registered/groupmanagement.html', context=render_items)
render_items, context_instance=RequestContext(request))
@login_required @login_required
@ -48,13 +49,20 @@ def group_accept_request(request, group_request_id):
group_request.user.groups.add(group) group_request.user.groups.add(group)
group_request.user.save() group_request.user.save()
group_request.delete() group_request.delete()
logger.info("User %s accepted group request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) logger.info("User %s accepted group request from user %s to group %s" % (
notify(group_request.user, "Group Application Accepted", level="success", message="Your application to %s has been accepted." % group_request.group) request.user, group_request.user, group_request.group.name))
notify(group_request.user, "Group Application Accepted", level="success",
message="Your application to %s has been accepted." % group_request.group)
messages.success(request,
'Accepted application from %s to %s.' % (group_request.main_char, group_request.group))
except: except:
logger.exception("Unhandled exception occured while user %s attempting to accept grouprequest id %s." % (request.user, group_request_id)) messages.error(request, 'An unhandled error occurred while processing the application from %s to %s.' % (
group_request.main_char, group_request.group))
logger.exception("Unhandled exception occurred while user %s attempting to accept grouprequest id %s." % (
request.user, group_request_id))
pass pass
return HttpResponseRedirect("/group/management/") return redirect("auth_group_management")
@login_required @login_required
@ -65,51 +73,74 @@ def group_reject_request(request, group_request_id):
group_request = GroupRequest.objects.get(id=group_request_id) group_request = GroupRequest.objects.get(id=group_request_id)
if group_request: if group_request:
logger.info("User %s rejected group request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) logger.info("User %s rejected group request from user %s to group %s" % (
request.user, group_request.user, group_request.group.name))
group_request.delete() group_request.delete()
notify(group_request.user, "Group Application Rejected", level="danger", message="Your application to %s has been rejected." % group_request.group) notify(group_request.user, "Group Application Rejected", level="danger",
message="Your application to %s has been rejected." % group_request.group)
messages.success(request,
'Rejected application from %s to %s.' % (group_request.main_char, group_request.group))
except: except:
logger.exception("Unhandled exception occured while user %s attempting to reject group request id %s" % (request.user, group_request_id)) messages.error(request, 'An unhandled error occured while processing the application from %s to %s.' % (
group_request.main_char, group_request.group))
logger.exception("Unhandled exception occured while user %s attempting to reject group request id %s" % (
request.user, group_request_id))
pass pass
return HttpResponseRedirect("/group/management/") return redirect("auth_group_management")
@login_required @login_required
@permission_required('auth.group_management') @permission_required('auth.group_management')
def group_leave_accept_request(request, group_request_id): def group_leave_accept_request(request, group_request_id):
logger.debug("group_leave_accept_request called by user %s for group request id %s" % (request.user, group_request_id)) logger.debug(
"group_leave_accept_request called by user %s for group request id %s" % (request.user, group_request_id))
try: try:
group_request = GroupRequest.objects.get(id=group_request_id) group_request = GroupRequest.objects.get(id=group_request_id)
group, created = Group.objects.get_or_create(name=group_request.group.name) group, created = Group.objects.get_or_create(name=group_request.group.name)
group_request.user.groups.remove(group) group_request.user.groups.remove(group)
group_request.user.save() group_request.user.save()
group_request.delete() group_request.delete()
logger.info("User %s accepted group leave request from user %s to group %s" % (request.user, group_request.user, group_request.group.name)) logger.info("User %s accepted group leave request from user %s to group %s" % (
notify(group_request.user, "Group Leave Request Accepted", level="success", message="Your request to leave %s has been accepted." % group_request.group) request.user, group_request.user, group_request.group.name))
notify(group_request.user, "Group Leave Request Accepted", level="success",
message="Your request to leave %s has been accepted." % group_request.group)
messages.success(request,
'Accepted application from %s to leave %s.' % (group_request.main_char, group_request.group))
except: except:
logger.exception("Unhandled exception occured while user %s attempting to accept group leave request id %s" % (request.user, group_request_id)) messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
group_request.main_char, group_request.group))
logger.exception("Unhandled exception occured while user %s attempting to accept group leave request id %s" % (
request.user, group_request_id))
pass pass
return HttpResponseRedirect("/group/management/") return redirect("auth_group_management")
@login_required @login_required
@permission_required('auth.group_management') @permission_required('auth.group_management')
def group_leave_reject_request(request, group_request_id): def group_leave_reject_request(request, group_request_id):
logger.debug("group_leave_reject_request called by user %s for group request id %s" % (request.user, group_request_id)) logger.debug(
"group_leave_reject_request called by user %s for group request id %s" % (request.user, group_request_id))
try: try:
group_request = GroupRequest.objects.get(id=group_request_id) group_request = GroupRequest.objects.get(id=group_request_id)
if group_request: if group_request:
group_request.delete() group_request.delete()
logger.info("User %s rejected group leave request from user %s for group %s" % (request.user, group_request.user, group_request.group.name)) logger.info("User %s rejected group leave request from user %s for group %s" % (
notify(group_request.user, "Group Leave Request Rejected", level="danger", message="Your request to leave %s has been rejected." % group_request.group) request.user, group_request.user, group_request.group.name))
notify(group_request.user, "Group Leave Request Rejected", level="danger",
message="Your request to leave %s has been rejected." % group_request.group)
messages.success(request, 'Rejected application from %s to leave %s.' % (
group_request.main_char, group_request.group))
except: except:
logger.exception("Unhandled exception occured while user %s attempting to reject group leave request id %s" % (request.user, group_request_id)) messages.error(request, 'An unhandled error occured while processing the application from %s to leave %s.' % (
group_request.main_char, group_request.group))
logger.exception("Unhandled exception occured while user %s attempting to reject group leave request id %s" % (
request.user, group_request_id))
pass pass
return HttpResponseRedirect("/group/management/") return redirect("auth_group_management")
@login_required @login_required
@ -131,23 +162,22 @@ def groups_view(request):
pass pass
else: else:
# Get the descriptionn # Get the descriptionn
groupDesc = GroupDescription.objects.filter(group=group) group_desc = GroupDescription.objects.filter(group=group)
groupRequest = GroupRequest.objects.filter(user=request.user).filter(group=group) group_request = GroupRequest.objects.filter(user=request.user).filter(group=group)
if groupDesc: if group_desc:
if groupRequest: if group_request:
paired_list.append((group, groupDesc[0], groupRequest[0])) paired_list.append((group, group_desc[0], group_request[0]))
else: else:
paired_list.append((group, groupDesc[0], "")) paired_list.append((group, group_desc[0], ""))
else: else:
if groupRequest: if group_request:
paired_list.append((group, "", groupRequest[0])) paired_list.append((group, "", group_request[0]))
else: else:
paired_list.append((group, "", "")) paired_list.append((group, "", ""))
render_items = {'pairs': paired_list} render_items = {'pairs': paired_list}
return render_to_response('registered/groups.html', return render(request, 'registered/groups.html', context=render_items)
render_items, context_instance=RequestContext(request))
@login_required @login_required
@ -157,8 +187,8 @@ def group_request_add(request, group_id):
if OpenGroup.objects.filter(group=group).exists(): if OpenGroup.objects.filter(group=group).exists():
logger.info("%s joining %s as is an open group" % (request.user, group)) logger.info("%s joining %s as is an open group" % (request.user, group))
request.user.groups.add(group) request.user.groups.add(group)
return HttpResponseRedirect("/groups") return redirect("auth_groups")
auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
grouprequest = GroupRequest() grouprequest = GroupRequest()
grouprequest.status = _('Pending') grouprequest.status = _('Pending')
grouprequest.group = group grouprequest.group = group
@ -167,7 +197,8 @@ def group_request_add(request, group_id):
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)))
return HttpResponseRedirect("/groups") messages.success(request, 'Applied to group %s.' % group)
return redirect("auth_groups")
@login_required @login_required
@ -177,8 +208,8 @@ def group_request_leave(request, group_id):
if OpenGroup.objects.filter(group=group).exists(): if OpenGroup.objects.filter(group=group).exists():
logger.info("%s leaving %s as is an open group" % (request.user, group)) logger.info("%s leaving %s as is an open group" % (request.user, group))
request.user.groups.remove(group) request.user.groups.remove(group)
return HttpResponseRedirect("/groups") return redirect("auth_groups")
auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0]
grouprequest = GroupRequest() grouprequest = GroupRequest()
grouprequest.status = _('Pending') grouprequest.status = _('Pending')
grouprequest.group = group grouprequest.group = group
@ -187,5 +218,5 @@ def group_request_leave(request, group_id):
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)))
messages.success(request, 'Applied to leave group %s.' % group)
return HttpResponseRedirect("/groups") return redirect("auth_groups")

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,10 +1,11 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import Application from hrapplications.models import Application
from models import ApplicationQuestion from hrapplications.models import ApplicationQuestion
from models import ApplicationForm from hrapplications.models import ApplicationForm
from models import ApplicationResponse from hrapplications.models import ApplicationResponse
from models import ApplicationComment from hrapplications.models import ApplicationComment
admin.site.register(Application) admin.site.register(Application)
admin.site.register(ApplicationComment) admin.site.register(ApplicationComment)

7
hrapplications/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class HRApplicationsConfig(AppConfig):
name = 'hrapplications'

View File

@ -1,8 +1,11 @@
from __future__ import unicode_literals
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
class HRApplicationCommentForm(forms.Form): class HRApplicationCommentForm(forms.Form):
comment = forms.CharField(widget=forms.Textarea, required=False, label=_("Comment")) comment = forms.CharField(widget=forms.Textarea, required=False, label=_("Comment"))
class HRApplicationSearchForm(forms.Form): class HRApplicationSearchForm(forms.Form):
search_string = forms.CharField(max_length=254, required=True, label=_("Search String")) search_string = forms.CharField(max_length=254, required=True, label=_("Search String"))

View File

@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:39
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('eveonline', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Application',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('approved', models.NullBooleanField(default=None)),
('created', models.DateTimeField(auto_now_add=True)),
],
options={
'permissions': (('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'), ('view_apis', 'Can view applicant APIs')),
},
),
migrations.CreateModel(
name='ApplicationComment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField()),
('created', models.DateTimeField(auto_now_add=True)),
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='hrapplications.Application')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='ApplicationForm',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('corp', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
],
),
migrations.CreateModel(
name='ApplicationQuestion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=254)),
('help_text', models.CharField(blank=True, max_length=254, null=True)),
],
),
migrations.CreateModel(
name='ApplicationResponse',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('answer', models.TextField()),
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='responses', to='hrapplications.Application')),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hrapplications.ApplicationQuestion')),
],
),
migrations.CreateModel(
name='HRApplication',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('character_name', models.CharField(default=b'', max_length=254)),
('full_api_id', models.CharField(default=b'', max_length=254)),
('full_api_key', models.CharField(default=b'', max_length=254)),
('is_a_spi', models.CharField(default=b'', max_length=254)),
('about', models.TextField(default=b'')),
('extra', models.TextField(default=b'')),
('approved_denied', models.NullBooleanField()),
('corp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCorporationInfo')),
('reviewer_character', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')),
('reviewer_inprogress_character', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inprogress_character', to='eveonline.EveCharacter')),
('reviewer_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='review_user', to=settings.AUTH_USER_MODEL)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='HRApplicationComment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_on', models.DateTimeField(auto_now_add=True, null=True)),
('comment', models.CharField(default=b'', max_length=254)),
('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hrapplications.HRApplication')),
('commenter_character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')),
('commenter_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='applicationform',
name='questions',
field=models.ManyToManyField(to='hrapplications.ApplicationQuestion'),
),
migrations.AddField(
model_name='application',
name='form',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to='hrapplications.ApplicationForm'),
),
migrations.AddField(
model_name='application',
name='reviewer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='application',
name='reviewer_character',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='eveonline.EveCharacter'),
),
migrations.AddField(
model_name='application',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='applications', to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='applicationresponse',
unique_together=set([('question', 'application')]),
),
migrations.AlterUniqueTogether(
name='application',
unique_together=set([('form', 'user')]),
),
]

View File

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -6,6 +8,8 @@ from eveonline.models import EveCorporationInfo
from eveonline.models import EveApiKeyPair from eveonline.models import EveApiKeyPair
from authentication.models import AuthServicesInfo from authentication.models import AuthServicesInfo
@python_2_unicode_compatible
class ApplicationQuestion(models.Model): class ApplicationQuestion(models.Model):
title = models.CharField(max_length=254) title = models.CharField(max_length=254)
help_text = models.CharField(max_length=254, blank=True, null=True) help_text = models.CharField(max_length=254, blank=True, null=True)
@ -13,6 +17,8 @@ class ApplicationQuestion(models.Model):
def __str__(self): def __str__(self):
return "Question: " + self.title.encode('utf-8') return "Question: " + self.title.encode('utf-8')
@python_2_unicode_compatible
class ApplicationForm(models.Model): class ApplicationForm(models.Model):
questions = models.ManyToManyField(ApplicationQuestion) questions = models.ManyToManyField(ApplicationQuestion)
corp = models.OneToOneField(EveCorporationInfo) corp = models.OneToOneField(EveCorporationInfo)
@ -20,6 +26,8 @@ class ApplicationForm(models.Model):
def __str__(self): def __str__(self):
return str(self.corp) return str(self.corp)
@python_2_unicode_compatible
class Application(models.Model): class Application(models.Model):
form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications') form = models.ForeignKey(ApplicationForm, on_delete=models.CASCADE, related_name='applications')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications') user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications')
@ -32,7 +40,9 @@ class Application(models.Model):
return str(self.user) + " Application To " + str(self.form) return str(self.user) + " Application To " + str(self.form)
class Meta: class Meta:
permissions = (('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'), ('view_apis', 'Can view applicant APIs'),) permissions = (
('approve_application', 'Can approve applications'), ('reject_application', 'Can reject applications'),
('view_apis', 'Can view applicant APIs'),)
unique_together = ('form', 'user') unique_together = ('form', 'user')
@property @property
@ -62,6 +72,7 @@ class Application(models.Model):
return None return None
@python_2_unicode_compatible
class ApplicationResponse(models.Model): class ApplicationResponse(models.Model):
question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE) question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE)
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses') application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses')
@ -73,6 +84,8 @@ class ApplicationResponse(models.Model):
class Meta: class Meta:
unique_together = ('question', 'application') unique_together = ('question', 'application')
@python_2_unicode_compatible
class ApplicationComment(models.Model): class ApplicationComment(models.Model):
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments') application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments')
user = models.ForeignKey(User, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
@ -82,12 +95,11 @@ class ApplicationComment(models.Model):
def __str__(self): def __str__(self):
return str(self.user) + " comment on " + str(self.application) return str(self.user) + " comment on " + str(self.application)
################ ################
# Legacy Models # Legacy Models
################ ################
# Can't delete or evolutions explodes. @python_2_unicode_compatible
# They do nothing.
################
class HRApplication(models.Model): class HRApplication(models.Model):
character_name = models.CharField(max_length=254, default="") character_name = models.CharField(max_length=254, default="")
full_api_id = models.CharField(max_length=254, default="") full_api_id = models.CharField(max_length=254, default="")
@ -109,6 +121,7 @@ class HRApplication(models.Model):
return self.character_name + " - Application" return self.character_name + " - Application"
@python_2_unicode_compatible
class HRApplicationComment(models.Model): class HRApplicationComment(models.Model):
created_on = models.DateTimeField(auto_now_add=True, null=True) created_on = models.DateTimeField(auto_now_add=True, null=True)
comment = models.CharField(max_length=254, default="") comment = models.CharField(max_length=254, default="")

View File

@ -1,30 +1,23 @@
from django.template import RequestContext from __future__ import unicode_literals
from django.shortcuts import render_to_response, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import login_required 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.shortcuts import HttpResponseRedirect
from notifications import notify from notifications import notify
from models import HRApplication from hrapplications.models import ApplicationForm
from models import HRApplicationComment from hrapplications.models import Application
from models import ApplicationForm from hrapplications.models import ApplicationResponse
from models import Application from hrapplications.models import ApplicationComment
from models import ApplicationQuestion from hrapplications.forms import HRApplicationCommentForm
from models import ApplicationResponse from hrapplications.forms import HRApplicationSearchForm
from models import ApplicationComment
from forms import HRApplicationCommentForm
from forms import HRApplicationSearchForm
from eveonline.models import EveCorporationInfo
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
from authentication.models import AuthServicesInfo from authentication.models import AuthServicesInfo
from django.conf import settings
from eveonline.managers import EveManager
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def create_application_test(user): def create_application_test(user):
auth, c = AuthServicesInfo.objects.get_or_create(user=user) auth, c = AuthServicesInfo.objects.get_or_create(user=user)
if auth.main_char_id: if auth.main_char_id:
@ -32,6 +25,7 @@ def create_application_test(user):
else: else:
return False return False
@login_required @login_required
def hr_application_management_view(request): def hr_application_management_view(request):
logger.debug("hr_application_management_view called by user %s" % request.user) logger.debug("hr_application_management_view called by user %s" % request.user)
@ -42,7 +36,7 @@ def hr_application_management_view(request):
if auth_info.main_char_id: if auth_info.main_char_id:
try: try:
main_char = EveCharacter.objects.get(character_id=auth_info.main_char_id) main_char = EveCharacter.objects.get(character_id=auth_info.main_char_id)
except: except EveCharacter.DoesNotExist:
pass pass
if request.user.is_superuser: if request.user.is_superuser:
corp_applications = Application.objects.filter(approved=None) corp_applications = Application.objects.filter(approved=None)
@ -52,7 +46,8 @@ def hr_application_management_view(request):
app_form = ApplicationForm.objects.get(corp__corporation_id=main_char.corporation_id) app_form = ApplicationForm.objects.get(corp__corporation_id=main_char.corporation_id)
corp_applications = Application.objects.filter(form=app_form).filter(approved=None) corp_applications = Application.objects.filter(form=app_form).filter(approved=None)
finished_corp_applications = Application.objects.filter(form=app_form).filter(approved__in=[True, False]) finished_corp_applications = Application.objects.filter(form=app_form).filter(approved__in=[True, False])
logger.debug("Retrieved %s personal, %s corp applications for %s" % (len(request.user.applications.all()), len(corp_applications), request.user)) logger.debug("Retrieved %s personal, %s corp applications for %s" % (
len(request.user.applications.all()), len(corp_applications), request.user))
context = { context = {
'personal_apps': request.user.applications.all(), 'personal_apps': request.user.applications.all(),
'applications': corp_applications, 'applications': corp_applications,
@ -60,7 +55,8 @@ def hr_application_management_view(request):
'search_form': HRApplicationSearchForm(), 'search_form': HRApplicationSearchForm(),
'create': create_application_test(request.user) 'create': create_application_test(request.user)
} }
return render_to_response('registered/hrapplicationmanagement.html', context, context_instance=RequestContext(request)) return render(request, 'registered/hrapplicationmanagement.html', context=context)
@login_required @login_required
@user_passes_test(create_application_test) @user_passes_test(create_application_test)
@ -75,19 +71,22 @@ def hr_application_create_view(request, form_id=None):
application.save() application.save()
for question in app_form.questions.all(): for question in app_form.questions.all():
response = ApplicationResponse(question=question, application=application) response = ApplicationResponse(question=question, application=application)
response.answer = request.POST.get(str(question.pk), "Failed to retrieve answer provided by applicant.") response.answer = request.POST.get(str(question.pk),
"Failed to retrieve answer provided by applicant.")
response.save() response.save()
logger.info("%s created %s" % (request.user, application)) logger.info("%s created %s" % (request.user, application))
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
else: else:
questions = app_form.questions.all() questions = app_form.questions.all()
return render_to_response('registered/hrapplicationcreate.html', {'questions':questions, 'corp':app_form.corp}, context_instance=RequestContext(request)) return render(request, 'registered/hrapplicationcreate.html',
context={'questions': questions, 'corp': app_form.corp})
else: else:
choices = [] choices = []
for app_form in ApplicationForm.objects.all(): for app_form in ApplicationForm.objects.all():
if not Application.objects.filter(user=request.user).filter(form=app_form).exists(): if not Application.objects.filter(user=request.user).filter(form=app_form).exists():
choices.append((app_form.id, app_form.corp.corporation_name)) choices.append((app_form.id, app_form.corp.corporation_name))
return render_to_response('registered/hrapplicationcorpchoice.html', {'choices':choices}, context_instance=RequestContext(request)) return render(request, 'registered/hrapplicationcorpchoice.html', context={'choices': choices})
@login_required @login_required
def hr_application_personal_view(request, app_id): def hr_application_personal_view(request, app_id):
@ -102,7 +101,7 @@ def hr_application_personal_view(request, app_id):
'comment_form': HRApplicationCommentForm(), 'comment_form': HRApplicationCommentForm(),
'apis': [], 'apis': [],
} }
return render_to_response('registered/hrapplicationview.html', context, context_instance=RequestContext(request)) return render(request, 'registered/hrapplicationview.html', context=context)
else: else:
logger.warn("User %s not authorized to view %s" % (request.user, app)) logger.warn("User %s not authorized to view %s" % (request.user, app))
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
@ -113,7 +112,7 @@ def hr_application_personal_removal(request, app_id):
logger.debug("hr_application_personal_removal called by user %s for app id %s" % (request.user, app_id)) logger.debug("hr_application_personal_removal called by user %s for app id %s" % (request.user, app_id))
app = get_object_or_404(Application, pk=app_id) app = get_object_or_404(Application, pk=app_id)
if app.user == request.user: if app.user == request.user:
if app.approved == None: if app.approved is None:
logger.info("User %s deleting %s" % (request.user, app)) logger.info("User %s deleting %s" % (request.user, app))
app.delete() app.delete()
else: else:
@ -122,6 +121,7 @@ def hr_application_personal_removal(request, app_id):
logger.warn("User %s not authorized to delete %s" % (request.user, app)) logger.warn("User %s not authorized to delete %s" % (request.user, app))
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
def hr_application_view(request, app_id): def hr_application_view(request, app_id):
@ -154,7 +154,7 @@ def hr_application_view(request, app_id):
'comments': ApplicationComment.objects.filter(application=app), 'comments': ApplicationComment.objects.filter(application=app),
'comment_form': form, 'comment_form': form,
} }
return render_to_response('registered/hrapplicationview.html', context, context_instance=RequestContext(request)) return render(request, 'registered/hrapplicationview.html', context=context)
@login_required @login_required
@ -168,6 +168,7 @@ def hr_application_remove(request, app_id):
notify(app.user, "Application Deleted", message="Your application to %s was deleted." % app.form.corp) notify(app.user, "Application Deleted", message="Your application to %s was deleted." % app.form.corp)
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
@permission_required('hrapplications.approve_application') @permission_required('hrapplications.approve_application')
@ -178,11 +179,13 @@ def hr_application_approve(request, app_id):
logger.info("User %s approving %s" % (request.user, app)) logger.info("User %s approving %s" % (request.user, app))
app.approved = True app.approved = True
app.save() app.save()
notify(app.user, "Application Accepted", message="Your application to %s has been approved." % app.form.corp, level="success") notify(app.user, "Application Accepted", message="Your application to %s has been approved." % app.form.corp,
level="success")
else: else:
logger.warn("User %s not authorized to approve %s" % (request.user, app)) logger.warn("User %s not authorized to approve %s" % (request.user, app))
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
@permission_required('hrapplications.reject_application') @permission_required('hrapplications.reject_application')
@ -193,11 +196,13 @@ def hr_application_reject(request, app_id):
logger.info("User %s rejecting %s" % (request.user, app)) logger.info("User %s rejecting %s" % (request.user, app))
app.approved = False app.approved = False
app.save() app.save()
notify(app.user, "Application Rejected", message="Your application to %s has been rejected." % app.form.corp, level="danger") notify(app.user, "Application Rejected", message="Your application to %s has been rejected." % app.form.corp,
level="danger")
else: else:
logger.warn("User %s not authorized to reject %s" % (request.user, app)) logger.warn("User %s not authorized to reject %s" % (request.user, app))
return redirect('auth_hrapplications_view') return redirect('auth_hrapplications_view')
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
def hr_application_search(request): def hr_application_search(request):
@ -217,15 +222,16 @@ def hr_application_search(request):
try: try:
character = EveCharacter.objects.get(character_id=auth_info.main_char_id) character = EveCharacter.objects.get(character_id=auth_info.main_char_id)
app_list = Application.objects.filter(form__corp__corporation_id=character.corporation_id) app_list = Application.objects.filter(form__corp__corporation_id=character.corporation_id)
except: except EveCharacter.DoesNotExist:
logger.warn("User %s missing main character model: unable to filter applications to search" % request.user) logger.warn(
"User %s missing main character model: unable to filter applications to search" % request.user)
for application in app_list: for application in app_list:
if application.main_character: if application.main_character:
if searchstring in application.main_character.character_name.lower(): if searchstring in application.main_character.character_name.lower():
applications.add(application) applications.add(application)
if searchstring in application.main_character.corporation_name.lower(): if searchstring in application.main_character.corporation_name.lower():
applications.add(application) applications.add(application)
if searchstring in application.main_character.alliance_name.lower():\ if searchstring in application.main_character.alliance_name.lower():
applications.add(application) applications.add(application)
for character in application.characters: for character in application.characters:
if searchstring in character.character_name.lower(): if searchstring in character.character_name.lower():
@ -236,21 +242,21 @@ def hr_application_search(request):
applications.add(application) applications.add(application)
if searchstring in application.user.username.lower(): if searchstring in application.user.username.lower():
applications.add(application) applications.add(application)
logger.info("Found %s Applications for user %s matching search string %s" % (len(applications), request.user, searchstring)) logger.info("Found %s Applications for user %s matching search string %s" % (
len(applications), request.user, searchstring))
context = {'applications': applications, 'search_form': HRApplicationSearchForm()} context = {'applications': applications, 'search_form': HRApplicationSearchForm()}
return render_to_response('registered/hrapplicationsearchview.html', return render(request, 'registered/hrapplicationsearchview.html', context=context)
context, context_instance=RequestContext(request))
else: else:
logger.debug("Form invalid - returning for user %s to retry." % request.user) logger.debug("Form invalid - returning for user %s to retry." % request.user)
context = {'applications': None, 'search_form': form} context = {'applications': None, 'search_form': form}
return render_to_response('registered/hrapplicationsearchview.html', return render(request, 'registered/hrapplicationsearchview.html', context=context)
context, context_instance=RequestContext(request))
else: else:
logger.debug("Returning empty search form for user %s" % request.user) logger.debug("Returning empty search form for user %s" % request.user)
return HttpResponseRedirect("/hr_application_management/") return redirect("auth_hrapplications_view")
@login_required @login_required
@permission_required('auth.human_resources') @permission_required('auth.human_resources')
@ -262,13 +268,15 @@ def hr_application_mark_in_progress(request, app_id):
auth_info = AuthServicesInfo.objects.get(user=request.user) auth_info = AuthServicesInfo.objects.get(user=request.user)
try: try:
character = EveCharacter.objects.get(character_id=auth_info.main_char_id) character = EveCharacter.objects.get(character_id=auth_info.main_char_id)
except: except EveCharacter.DoesNotExist:
logger.warn("User %s marking %s in review has no main character" % (request.user, app)) logger.warn("User %s marking %s in review has no main character" % (request.user, app))
character = None character = None
app.reviewer = request.user app.reviewer = request.user
app.reviewer_character = character app.reviewer_character = character
app.save() app.save()
notify(app.user, "Application In Progress", message="Your application to %s is being reviewed by %s" % (app.form.corp, app.reviewer_str)) notify(app.user, "Application In Progress",
message="Your application to %s is being reviewed by %s" % (app.form.corp, app.reviewer_str))
else: else:
logger.warn("User %s unable to mark %s in progress: already being reviewed by %s" % (request.user, app, app.reviewer)) logger.warn(
return HttpResponseRedirect("/hr_application_view/" + str(app_id)) "User %s unable to mark %s in progress: already being reviewed by %s" % (request.user, app, app.reviewer))
return redirect("auth_hrapplication_view", app_id)

View File

@ -1,10 +1,23 @@
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import unicode_literals
import os import os
import sys import sys
if __name__ == "__main__": if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings")
try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)

View File

@ -1,11 +1,13 @@
from .models import Notification from __future__ import unicode_literals
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
MAX_NOTIFICATIONS = 50 MAX_NOTIFICATIONS = 50
def notify(user, title, message=None, level='info'): def notify(user, title, message=None, level='info'):
from .models import Notification
if Notification.objects.filter(user=user).count() > MAX_NOTIFICATIONS: if Notification.objects.filter(user=user).count() > MAX_NOTIFICATIONS:
for n in Notification.objects.filter(user=user)[MAX_NOTIFICATIONS:]: for n in Notification.objects.filter(user=user)[MAX_NOTIFICATIONS:]:
n.delete() n.delete()

View File

@ -1,3 +1,4 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from.models import Notification from.models import Notification

7
notifications/apps.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class NotificationsConfig(AppConfig):
name = 'notifications'

View File

@ -1,4 +1,6 @@
from .models import Notification from __future__ import unicode_literals
from notifications.models import Notification
def user_notification_count(request): def user_notification_count(request):
return {'notifications': len(Notification.objects.filter(user__id=request.user.id).filter(viewed=False))} return {'notifications': len(Notification.objects.filter(user__id=request.user.id).filter(viewed=False))}

View File

@ -1,11 +1,13 @@
from __future__ import unicode_literals
import logging import logging
from django.contrib.auth.models import User
from .models import Notification
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class NotificationHandler(logging.Handler): class NotificationHandler(logging.Handler):
def emit(self, record): def emit(self, record):
from django.contrib.auth.models import User
from notifications.models import Notification
for user in User.objects.all(): for user in User.objects.all():
if user.has_perm('auth.logging_notifications'): if user.has_perm('auth.logging_notifications'):
notif = Notification() notif = Notification()
@ -14,7 +16,7 @@ class NotificationHandler(logging.Handler):
notif.level = str([item[0] for item in Notification.LEVEL_CHOICES if item[1] == record.levelname][0]) notif.level = str([item[0] for item in Notification.LEVEL_CHOICES if item[1] == record.levelname][0])
message = record.getMessage() message = record.getMessage()
if record.exc_text: if record.exc_text:
message = message + "\n\n" message += "\n\n"
message = message + record.exc_text message = message + record.exc_text
notif.message = message notif.message = message
notif.save() notif.save()

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-05 21:40
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Notification',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('level', models.CharField(choices=[(b'danger', b'CRITICAL'), (b'danger', b'ERROR'), (b'warning', b'WARN'), (b'info', b'INFO'), (b'success', b'DEBUG')], max_length=10)),
('title', models.CharField(max_length=254)),
('message', models.TextField()),
('timestamp', models.DateTimeField(auto_now_add=True)),
('viewed', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2016-09-10 16:49
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('notifications', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='notification',
options={'ordering': ['-timestamp']},
),
]

View File

View File

@ -1,11 +1,14 @@
from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Notification(models.Model):
@python_2_unicode_compatible
class Notification(models.Model):
LEVEL_CHOICES = ( LEVEL_CHOICES = (
('danger', 'CRITICAL'), ('danger', 'CRITICAL'),
('danger', 'ERROR'), ('danger', 'ERROR'),
@ -26,9 +29,11 @@ class Notification(models.Model):
self.viewed = True self.viewed = True
self.save() self.save()
def __unicode__(self): def __str__(self):
output = "%s: %s" % (self.user, self.title) return "%s: %s" % (self.user, self.title)
return output.encode('utf-8')
def set_level(self, level): def set_level(self, level):
self.level = [item[0] for item in self.LEVEL_CHOICES if item[1] == level][0] self.level = [item[0] for item in self.LEVEL_CHOICES if item[1] == level][0]
class Meta:
ordering = ['-timestamp']

View File

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@ -1,10 +1,13 @@
from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from .models import Notification from .models import Notification
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib import messages
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@login_required @login_required
def notification_list(request): def notification_list(request):
logger.debug("notification_list called by user %s" % request.user) logger.debug("notification_list called by user %s" % request.user)
@ -17,6 +20,7 @@ def notification_list(request):
} }
return render(request, 'registered/notification_list.html', context) return render(request, 'registered/notification_list.html', context)
@login_required @login_required
def notification_view(request, notif_id): def notification_view(request, notif_id):
logger.debug("notification_view called by user %s for notif_id %s" % (request.user, notif_id)) logger.debug("notification_view called by user %s for notif_id %s" % (request.user, notif_id))
@ -27,9 +31,12 @@ def notification_view(request, notif_id):
notif.view() notif.view()
return render(request, 'registered/notification_view.html', context) return render(request, 'registered/notification_view.html', context)
else: else:
logger.warn("User %s not authorized to view notif_id %s belonging to user %s" % (request.user, notif_id, notif.user)) logger.warn(
"User %s not authorized to view notif_id %s belonging to user %s" % (request.user, notif_id, notif.user))
messages.error(request, 'You are not authorized to view that notification.')
return redirect('auth_notification_list') return redirect('auth_notification_list')
@login_required @login_required
def remove_notification(request, notif_id): def remove_notification(request, notif_id):
logger.debug("remove notification called by user %s for notif_id %s" % (request.user, notif_id)) logger.debug("remove notification called by user %s for notif_id %s" % (request.user, notif_id))
@ -38,6 +45,25 @@ def remove_notification(request, notif_id):
if Notification.objects.filter(id=notif_id).exists(): if Notification.objects.filter(id=notif_id).exists():
notif.delete() notif.delete()
logger.info("Deleting notif id %s by user %s" % (notif_id, request.user)) logger.info("Deleting notif id %s by user %s" % (notif_id, request.user))
messages.success(request, 'Deleted notification.')
else: else:
logger.error("Unable to delete notif id %s for user %s - notif matching id not found." % (notif_id, request.user)) logger.error(
"Unable to delete notif id %s for user %s - notif matching id not found." % (notif_id, request.user))
messages.error(request, 'Failed to locate notification.')
return redirect('auth_notification_list')
@login_required
def mark_all_read(request):
logger.debug('mark all notifications read called by user %s' % request.user)
Notification.objects.filter(user=request.user).update(viewed=True)
messages.success(request, 'Marked all notifications as read.')
return redirect('auth_notification_list')
@login_required
def delete_all_read(request):
logger.debug('delete all read notifications called by user %s' % request.user)
Notification.objects.filter(user=request.user).filter(viewed=True).delete()
messages.success(request, 'Deleted all read notifications.')
return redirect('auth_notification_list') return redirect('auth_notification_list')

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals
from django.contrib import admin from django.contrib import admin
from models import optimer from optimer.models import optimer
admin.site.register(optimer) admin.site.register(optimer)
# Register your models here.

Some files were not shown because too many files have changed in this diff Show More