diff --git a/.gitignore b/.gitignore index 9f48ec85..cd472cd5 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,10 @@ nginx_config.txt # custom staticfiles static/* + +#celerybeat +*.pid +celerybeat-schedule + +#pycharm +.idea/* \ No newline at end of file diff --git a/.idea/allianceauth.iml b/.idea/allianceauth.iml index a89267e9..a40b16c4 100755 --- a/.idea/allianceauth.iml +++ b/.idea/allianceauth.iml @@ -4,15 +4,16 @@ - + diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index b7866743..fe8e8466 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -1,30 +1,20 @@ - + mysql com.mysql.jdbc.Driver jdbc:mysql://127.0.0.1:3306/alliance_auth - allianceauth - dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfcbdfdfdfdedfc2 - mysql com.mysql.jdbc.Driver jdbc:mysql://127.0.0.1:3306/alliance_forum - allianceauth - dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfcbdfdfdfdedfc2 - mysql com.mysql.jdbc.Driver jdbc:mysql://127.0.0.1:3306/alliance_mumble - alliancemumble - dfcbdfc6dfc6dfc3dfcbdfc4dfc9dfcfdfc7dfdfdfc7dfc8dfc6dfcf - - - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9e616ddf..c33bd879 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,7 @@ - - - + + + + \ No newline at end of file diff --git a/README.md b/README.md index b600ad1a..ebb6c921 100755 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Join us in-game in the channel allianceauth for help and feature requests. 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: @@ -29,8 +29,7 @@ Note: Requirements: # Django Stuff # - django 1.6.1 - django-evolution + django 1.10.1 django-bootstrap-form django-celery @@ -58,11 +57,9 @@ Vagrant Instructions: 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 | 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 | 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 | 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) diff --git a/alliance_auth/__init__.py b/alliance_auth/__init__.py index e69de29b..519ff49e 100644 --- a/alliance_auth/__init__.py +++ b/alliance_auth/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals \ No newline at end of file diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 22d53359..3fc5f6d7 100644 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -1,43 +1,46 @@ """ -vim: set filetype=python: Django settings for alliance_auth project. +Generated by 'django-admin startproject' using Django 1.10.1. + 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 -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 djcelery +from django.contrib import messages + 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 -# 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! -# Generate a new key here: http://www.miniwebtool.com/django-secret-key-generator/ -SECRET_KEY = os.environ.get('AA_SECRET_KEY', '5xvh4e0x&@-$6(kj%4^80pdo1n5v-!mtx(e(1tw@kn-1le*ts@') +SECRET_KEY = '' # SECURITY WARNING: don't run with debug turned on in production! 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 -INSTALLED_APPS = ( + +INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -45,27 +48,25 @@ INSTALLED_APPS = ( 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', - 'django_evolution', 'djcelery', - 'celerytask', 'bootstrapform', 'authentication', - 'portal', - 'registration', 'services', 'eveonline', 'groupmanagement', 'hrapplications', 'timerboard', 'srp', - 'sigtracker', 'optimer', 'corputils', 'fleetactivitytracking', 'notifications', -) + 'eve_sso', + 'geelweb.django.navhelper', +] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -73,7 +74,9 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.locale.LocaleMiddleware', -) +] + +ROOT_URLCONF = 'alliance_auth.urls' LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale/'), @@ -85,105 +88,75 @@ LANGUAGES = ( ('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' + # Database -# https://docs.djangoproject.com/en/1.6/ref/settings/#databases +# https://docs.djangoproject.com/en/1.10/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'alliance_auth', + 'NAME': 'aa_test', 'USER': os.environ.get('AA_DB_DEFAULT_USER', 'allianceserver'), 'PASSWORD': os.environ.get('AA_DB_DEFAULT_PASSWORD', 'password'), 'HOST': os.environ.get('AA_DB_DEFAULT_HOST', '127.0.0.1'), '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'), - } - } -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.contrib.auth.context_processors.auth', - 'django.core.context_processors.debug', - 'django.core.context_processors.i18n', - 'django.core.context_processors.media', - 'django.core.context_processors.static', - 'django.core.context_processors.tz', - 'django.contrib.messages.context_processors.messages', - 'django.core.context_processors.request', - 'util.context_processors.is_corp', - 'util.context_processors.corp_id', - 'util.context_processors.corp_name', - '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', -) +# Password validation +# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators -TEMPLATE_DIRS = ( - os.path.join(BASE_DIR, 'customization/templates'), - os.path.join(BASE_DIR, 'stock/templates'), -) +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] -STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "customization/static"), - os.path.join(BASE_DIR, "stock/static"), -) +LOGIN_URL = 'auth_login_user' -LOGIN_URL = '/login_user/' +SUPERUSER_STATE_BYPASS = 'True' == os.environ.get('AA_SUPERUSER_STATE_BYPASS', 'True') # 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') @@ -195,11 +168,21 @@ USE_L10N = 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') - ################# # 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', '') EXTERNAL_MEDIA_URL = os.environ.get('AA_EXTERNAL_MEDIA_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 @@ -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_SMF = 'True' == os.environ.get('AA_ENABLE_AUTH_SMF', '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') ##################### @@ -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_SMF = 'True' == os.environ.get('AA_ENABLE_BLUE_SMF', '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') ######################### @@ -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_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 ##################### 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 @@ -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_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 ###################################### @@ -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_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 @@ -597,7 +626,7 @@ LOGGING = { 'level': 'DEBUG', }, 'fleetactivitytracking': { - 'handlers': ['log_file', 'console'], + 'handlers': ['log_file', 'console', 'notifications'], 'level': 'ERROR', }, '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 diff --git a/alliance_auth/urls.py b/alliance_auth/urls.py index 7c89f56b..57a0f3ce 100755 --- a/alliance_auth/urls.py +++ b/alliance_auth/urls.py @@ -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.utils.translation import ugettext_lazy as _ from django.contrib import admin - -admin.autodiscover() +import django.contrib.auth.views +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 -urlpatterns = patterns('', - - # Locale - url(r'^i18n/', include('django.conf.urls.i18n')), +urlpatterns = [ + # Locale + url(r'^i18n/', include('django.conf.urls.i18n')), - # Admin urls - url(r'^admin/', include(admin.site.urls)), + # Admin urls + url(r'^admin/', include(admin.site.urls)), - # Index - url(_(r'^$'), 'portal.views.index_view', name='auth_index'), - - # Authentication - url(r'^logout_user/', 'authentication.views.logout_user', name='auth_logout_user'), + # SSO + url (r'^sso/', include(eve_sso.urls, namespace='eve_sso')), + url (r'^sso/login$', authentication.views.sso_login, name='auth_sso_login'), - # Eve Online - url(r'^main_character_change/(\w+)/$', 'eveonline.views.main_character_change', - name='auth_main_character_change'), + # Index + url(_(r'^$'), authentication.views.index_view, name='auth_index'), - # Forum Service Control - 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'^reset_forum_password/$', 'services.views.reset_forum_password', - name='auth_reset_forum_password'), - url(r'^set_forum_password/$', 'services.views.set_forum_password', name='auth_set_forum_password'), + # Authentication + url(r'^logout_user/', authentication.views.logout_user, name='auth_logout_user'), - # Jabber Service Control - 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'^reset_jabber_password/$', 'services.views.reset_jabber_password', - name='auth_reset_jabber_password'), + # Eve Online + url(r'^main_character_change/(\w+)/$', eveonline.views.main_character_change, + name='auth_main_character_change'), - # Mumble service control - 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'^reset_mumble_password/$', 'services.views.reset_mumble_password', - name='auth_reset_mumble_password'), - url(r'^set_mumble_password/$', 'services.views.set_mumble_password', name='auth_set_mumble_password'), + # Forum Service Control + 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'^reset_forum_password/$', services.views.reset_forum_password, + name='auth_reset_forum_password'), + url(r'^set_forum_password/$', services.views.set_forum_password, name='auth_set_forum_password'), - # Ipboard service control - url(r'^activate_ipboard/$', 'services.views.activate_ipboard_forum', - name='auth_activate_ipboard'), - url(r'^deactivate_ipboard/$', 'services.views.deactivate_ipboard_forum', - name='auth_deactivate_ipboard'), - url(r'^reset_ipboard_password/$', 'services.views.reset_ipboard_password', - name='auth_reset_ipboard_password'), - url(r'^set_ipboard_password/$', 'services.views.set_ipboard_password', name='auth_set_ipboard_password'), + # Jabber Service Control + 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'^reset_jabber_password/$', services.views.reset_jabber_password, + name='auth_reset_jabber_password'), - # XenForo service control - url(r'^activate_xenforo/$', 'services.views.activate_xenforo_forum', - name='auth_activate_xenforo'), - url(r'^deactivate_xenforo/$', 'services.views.deactivate_xenforo_forum', - name='auth_deactivate_xenforo'), - url(r'^reset_xenforo_password/$', 'services.views.reset_xenforo_password', - name='auth_reset_xenforo_password'), - url(r'^set_xenforo_password/$', 'services.views.set_xenforo_password', name='auth_set_xenforo_password'), + # Mumble service control + 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'^reset_mumble_password/$', services.views.reset_mumble_password, + name='auth_reset_mumble_password'), + url(r'^set_mumble_password/$', services.views.set_mumble_password, name='auth_set_mumble_password'), - # Teamspeak3 service control - url(r'^activate_teamspeak3/$', 'services.views.activate_teamspeak3', - name='auth_activate_teamspeak3'), - url(r'^deactivate_teamspeak3/$', 'services.views.deactivate_teamspeak3', - name='auth_deactivate_teamspeak3'), - url(r'reset_teamspeak3_perm/$', 'services.views.reset_teamspeak3_perm', - name='auth_reset_teamspeak3_perm'), + # Ipboard service control + url(r'^activate_ipboard/$', services.views.activate_ipboard_forum, + name='auth_activate_ipboard'), + url(r'^deactivate_ipboard/$', services.views.deactivate_ipboard_forum, + name='auth_deactivate_ipboard'), + url(r'^reset_ipboard_password/$', services.views.reset_ipboard_password, + name='auth_reset_ipboard_password'), + url(r'^set_ipboard_password/$', services.views.set_ipboard_password, name='auth_set_ipboard_password'), - # Discord Service Control - 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'^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_add_bot/$', 'services.views.discord_add_bot', name='auth_discord_add_bot'), - - # Discourse Service Control - url(r'^activate_discourse/$', 'services.views.activate_discourse', name='auth_activate_discourse'), - url(r'^deactivate_discourse/$', 'services.views.deactivate_discourse', name='auth_deactivate_discourse'), + # XenForo service control + url(r'^activate_xenforo/$', services.views.activate_xenforo_forum, + name='auth_activate_xenforo'), + url(r'^deactivate_xenforo/$', services.views.deactivate_xenforo_forum, + name='auth_deactivate_xenforo'), + url(r'^reset_xenforo_password/$', services.views.reset_xenforo_password, + name='auth_reset_xenforo_password'), + url(r'^set_xenforo_password/$', services.views.set_xenforo_password, name='auth_set_xenforo_password'), - # IPS4 Service Control - url(r'^activate_ips4/$', 'services.views.activate_ips4', - name='auth_activate_ips4'), - url(r'^deactivate_ips4/$', 'services.views.deactivate_ips4', - name='auth_deactivate_ips4'), - url(r'^reset_ips4_password/$', 'services.views.reset_ips4_password', - name='auth_reset_ips4_password'), - url(r'^set_ips4_password/$', 'services.views.set_ips4_password', name='auth_set_ips4_password'), + # Teamspeak3 service control + url(r'^activate_teamspeak3/$', services.views.activate_teamspeak3, + name='auth_activate_teamspeak3'), + url(r'^deactivate_teamspeak3/$', services.views.deactivate_teamspeak3, + name='auth_deactivate_teamspeak3'), + url(r'reset_teamspeak3_perm/$', services.views.reset_teamspeak3_perm, + name='auth_reset_teamspeak3_perm'), - # SMF Service Control - 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'^reset_smf_password/$', 'services.views.reset_smf_password', - name='auth_reset_smf_password'), - url(r'^set_smf_password/$', 'services.views.set_smf_password', name='auth_set_smf_password'), + # Discord Service Control + 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'^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_add_bot/$', services.views.discord_add_bot, name='auth_discord_add_bot'), - # Alliance Market Control - 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'^reset_market_password/$', 'services.views.reset_market_password', - name='auth_reset_market_password'), - url(r'^set_market_password/$', 'services.views.set_market_password', name='auth_set_market_password'), + # Discourse Service Control + url(r'^activate_discourse/$', services.views.activate_discourse, name='auth_activate_discourse'), + url(r'^deactivate_discourse/$', services.views.deactivate_discourse, name='auth_deactivate_discourse'), - # 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'), + # IPS4 Service Control + url(r'^activate_ips4/$', services.views.activate_ips4, + name='auth_activate_ips4'), + url(r'^deactivate_ips4/$', services.views.deactivate_ips4, + name='auth_deactivate_ips4'), + url(r'^reset_ips4_password/$', services.views.reset_ips4_password, + name='auth_reset_ips4_password'), + url(r'^set_ips4_password/$', services.views.set_ips4_password, name='auth_set_ips4_password'), - # SRP URLS - 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_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', - name='auth_srp_fleet_mark_completed'), - url(r'^srp_fleet_mark_uncompleted/(\w+)', 'srp.views.srp_fleet_mark_uncompleted', - name='auth_srp_fleet_mark_uncompleted'), - url(r'^srp_request_remove/(\w+)', 'srp.views.srp_request_remove', - name="auth_srp_request_remove"), - url(r'srp_request_approve/(\w+)', 'srp.views.srp_request_approve', - name='auth_srp_request_approve'), - url(r'srp_request_reject/(\w+)', 'srp.views.srp_request_reject', name='auth_srp_request_reject'), + # SMF Service Control + 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'^reset_smf_password/$', services.views.reset_smf_password, + name='auth_reset_smf_password'), + url(r'^set_smf_password/$', services.views.set_smf_password, name='auth_set_smf_password'), - # Notifications - url(r'^remove_notifications/(\w+)/$', 'notifications.views.remove_notification', name='auth_remove_notification'), -) + # Alliance Market Control + 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'^reset_market_password/$', services.views.reset_market_password, + name='auth_reset_market_password'), + url(r'^set_market_password/$', services.views.set_market_password, name='auth_set_market_password'), + + # SRP URLS + 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_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, + name='auth_srp_fleet_mark_completed'), + url(r'^srp_fleet_mark_uncompleted/(\w+)', srp.views.srp_fleet_mark_uncompleted, + name='auth_srp_fleet_mark_uncompleted'), + url(r'^srp_request_remove/(\w+)', srp.views.srp_request_remove, + name="auth_srp_request_remove"), + url(r'srp_request_approve/(\w+)', srp.views.srp_request_approve, + name='auth_srp_request_approve'), + url(r'srp_request_reject/(\w+)', srp.views.srp_request_reject, name='auth_srp_request_reject'), + + # Notifications + 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 -urlpatterns += i18n_patterns('', +urlpatterns += i18n_patterns( - #corputils - url(r'^corputils/$', 'corputils.views.corp_member_view', name='auth_corputils'), - url(r'^corputils/(?P[0-9]+)/$', 'corputils.views.corp_member_view'), - url(r'^corputils/(?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)/$', 'corputils.views.corp_member_view', name='auth_corputils_month'), - url(r'^corputils/search/$', 'corputils.views.corputils_search', name="auth_corputils_search"), - url(r'^corputils/search/(?P[0-9]+)/$', 'corputils.views.corputils_search'), + # corputils + url(r'^corputils/$', corputils.views.corp_member_view, name='auth_corputils'), + url(r'^corputils/(?P[0-9]+)/$', corputils.views.corp_member_view, name='auth_corputils_corp_view'), + url(r'^corputils/(?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)/$', corputils.views.corp_member_view, + name='auth_corputils_month'), + url(r'^corputils/search/$', corputils.views.corputils_search, name="auth_corputils_search"), + url(r'^corputils/search/(?P[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 - 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/(?P[0-9]+)/$', 'fleetup.views.fleetup_fitting'), - 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/doctrines/(?P[0-9]+)/$', 'fleetup.views.fleetup_doctrine'), + # Fleetup + 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/(?P[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/characters/$', fleetup.views.fleetup_characters, name='auth_fleetup_characters'), + url(r'^fleetup/doctrines/(?P[0-9]+)/$', fleetup.views.fleetup_doctrine, name='auth_fleetup_doctrine'), - # Authentication - 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'^user/password/$'), 'django.contrib.auth.views.password_change', name='password_change'), - url(_(r'^user/password/done/$'), 'django.contrib.auth.views.password_change_done', - name='password_change_done'), - url(_(r'^user/password/reset/$'), 'django.contrib.auth.views.password_reset', - name='password_reset'), - url(_(r'^user/password/password/reset/done/$'), 'django.contrib.auth.views.password_reset_done', - name='password_reset_done'), - url(_(r'^user/password/reset/complete/$'), 'django.contrib.auth.views.password_reset_complete', - name='password_reset_complete'), - url(_(r'^user/password/reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P.+)/$'), - 'django.contrib.auth.views.password_reset_confirm', name='password_reset_confirm'), - - # Portal Urls - url(_(r'^dashboard/$'), 'portal.views.dashboard_view', name='auth_dashboard'), - url(_(r'^help/$'), 'portal.views.help_view', name='auth_help'), - - # Eveonline Urls - 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', - name='auth_api_key_management'), - 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'^characters/'), 'eveonline.views.characters_view', name='auth_characters'), + # Authentication + url(_(r'^login_user/'), authentication.views.login_user, name='auth_login_user'), + url(_(r'^register_user/'), authentication.views.register_user_view, name='auth_register_user'), - # Group management - url(_(r'^groups/'), 'groupmanagement.views.groups_view', name='auth_groups'), - url(_(r'^group/management/'), 'groupmanagement.views.group_management', - name='auth_group_management'), - url(_(r'^group/request_add/(\w+)'), 'groupmanagement.views.group_request_add', - name='auth_group_request_add'), - url(_(r'^group/request/accept/(\w+)'), 'groupmanagement.views.group_accept_request', - name='auth_group_accept_request'), - url(_(r'^group/request/reject/(\w+)'), 'groupmanagement.views.group_reject_request', - name='auth_group_reject_request'), + 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, + name='password_change_done'), + url(_(r'^user/password/reset/$'), django.contrib.auth.views.password_reset, + name='password_reset'), + url(_(r'^user/password/password/reset/done/$'), django.contrib.auth.views.password_reset_done, + name='password_reset_done'), + url(_(r'^user/password/reset/complete/$'), django.contrib.auth.views.password_reset_complete, + name='password_reset_complete'), + url(_(r'^user/password/reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P.+)/$'), + django.contrib.auth.views.password_reset_confirm, name='password_reset_confirm'), - url(_(r'^group/request_leave/(\w+)'), 'groupmanagement.views.group_request_leave', - name='auth_group_request_leave'), - url(_(r'group/leave_request/accept/(\w+)'), 'groupmanagement.views.group_leave_accept_request', - name='auth_group_leave_accept_request'), - url(_(r'^group/leave_request/reject/(\w+)'), 'groupmanagement.views.group_leave_reject_request', - name='auth_group_leave_reject_request'), + # Portal Urls + url(_(r'^dashboard/$'), authentication.views.dashboard_view, name='auth_dashboard'), + url(_(r'^help/$'), authentication.views.help_view, name='auth_help'), - # HR Application Management - url(_(r'^hr_application_management/'), 'hrapplications.views.hr_application_management_view', - name="auth_hrapplications_view"), - url(_(r'^hr_application_create/$'), 'hrapplications.views.hr_application_create_view', - name="auth_hrapplication_create_view"), - url(_(r'^hr_application_create/(\d+)'), 'hrapplications.views.hr_application_create_view', - name="auth_hrapplication_create_view"), - url(_(r'^hr_application_remove/(\w+)'), 'hrapplications.views.hr_application_remove', - name="auth_hrapplication_remove"), - url(_(r'hr_application_view/(\w+)'), 'hrapplications.views.hr_application_view', - name="auth_hrapplication_view"), - url(_(r'hr_application_personal_view/(\w+)'), 'hrapplications.views.hr_application_personal_view', - name="auth_hrapplication_personal_view"), - url(_(r'hr_application_personal_removal/(\w+)'), - 'hrapplications.views.hr_application_personal_removal', - name="auth_hrapplication_personal_removal"), - url(_(r'hr_application_approve/(\w+)'), 'hrapplications.views.hr_application_approve', - name="auth_hrapplication_approve"), - url(_(r'hr_application_reject/(\w+)'), 'hrapplications.views.hr_application_reject', - name="auth_hrapplication_reject"), - url(_(r'hr_application_search/'), 'hrapplications.views.hr_application_search', - name="auth_hrapplication_search"), - url(_(r'hr_mark_in_progress/(\w+)'), 'hrapplications.views.hr_application_mark_in_progress', - name="auth_hrapplication_mark_in_progress"), - - # Fleet Operations Timers - 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'^remove_optimer/(\w+)'), 'optimer.views.remove_optimer', name='auth_remove_optimer'), - url(_(r'^edit_optimer/(\w+)$'), 'optimer.views.edit_optimer', name='auth_edit_optimer'), + # Eveonline Urls + 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, + name='auth_api_key_management'), + 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'^characters/'), eveonline.views.characters_view, name='auth_characters'), - # Service Urls - url(_(r'^services/$'), 'services.views.services_view', name='auth_services'), - url(_(r'^services/jabber_broadcast/$'), 'services.views.jabber_broadcast_view', - name='auth_jabber_broadcast_view'), + # Group management + url(_(r'^groups/'), groupmanagement.views.groups_view, name='auth_groups'), + url(_(r'^group/management/'), groupmanagement.views.group_management, + name='auth_group_management'), + url(_(r'^group/request_add/(\w+)'), groupmanagement.views.group_request_add, + name='auth_group_request_add'), + url(_(r'^group/request/accept/(\w+)'), groupmanagement.views.group_accept_request, + name='auth_group_accept_request'), + url(_(r'^group/request/reject/(\w+)'), groupmanagement.views.group_reject_request, + name='auth_group_reject_request'), - #Teamspeak Urls - url(r'verify_teamspeak3/$', 'services.views.verify_teamspeak3', name='auth_verify_teamspeak3'), - - #corputils - url(_(r'^corputils/$'), 'corputils.views.corp_member_view', name='auth_corputils'), - url(_(r'^corputils/(?P[0-9]+)/$'), 'corputils.views.corp_member_view'), - url(_(r'^corputils/search/$'), 'corputils.views.corputils_search', name="auth_corputils_search"), - url(_(r'^corputils/search/(?P[0-9]+)/$'), 'corputils.views.corputils_search'), - - # Timer URLS - 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'^remove_timer/(\w+)'), 'timerboard.views.remove_timer', name='auth_remove_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 - 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_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_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_amount_update/(\w+)'), 'srp.views.srp_request_update_amount_view', - name="auth_srp_request_update_amount_view"), - - # Tools - url(_(r'^tool/fleet_formatter_tool/$'), 'services.views.fleet_formatter_view', - name='auth_fleet_format_tool_view'), + url(_(r'^group/request_leave/(\w+)'), groupmanagement.views.group_request_leave, + name='auth_group_request_leave'), + url(_(r'group/leave_request/accept/(\w+)'), groupmanagement.views.group_leave_accept_request, + name='auth_group_leave_accept_request'), + url(_(r'^group/leave_request/reject/(\w+)'), groupmanagement.views.group_leave_reject_request, + name='auth_group_leave_reject_request'), - # Notifications - url(_(r'^notifications/$'), 'notifications.views.notification_list', name='auth_notification_list'), - url(_(r'^notifications/(\w+)/$'), 'notifications.views.notification_view', name='auth_notification_view'), - - #Jabber - 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) - 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/(?P[0-9]+)/(?P[0-9]+)/$', 'fleetactivitytracking.views.fatlink_statistics_view', name='auth_fatlink_view_statistics_month'), - url(r'^fat/user/statistics/$', 'fleetactivitytracking.views.fatlink_personal_statistics_view', name='auth_fatlink_view_personal_statistics'), - url(r'^fat/user/statistics/(?P[0-9]+)/$', 'fleetactivitytracking.views.fatlink_personal_statistics_view', name='auth_fatlink_view_personal_statistics_year'), - url(r'^fat/user/statistics/(?P[0-9]+)/(?P[0-9]+)/$', 'fleetactivitytracking.views.fatlink_monthly_personal_statistics_view', - name='auth_fatlink_view_personal_statistics_month'), - url(r'^fat/user/(?P[0-9]+)/statistics/(?P[0-9]+)/(?P[0-9]+)/$', 'fleetactivitytracking.views.fatlink_monthly_personal_statistics_view', - name='auth_fatlink_view_user_statistics_month'), - 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/(?P[a-zA-Z0-9_-]+)/([a-z0-9_-]+)$', - 'fleetactivitytracking.views.modify_fatlink_view'), - url(r'^fat/link/$', 'fleetactivitytracking.views.fatlink_view', name='auth_click_fatlink_view'), - url(r'^fat/link/(?P[a-zA-Z0-9]+)/(?P[a-z0-9_-]+)/$', - 'fleetactivitytracking.views.click_fatlink_view'), + # HR Application Management + url(_(r'^hr_application_management/'), hrapplications.views.hr_application_management_view, + name="auth_hrapplications_view"), + url(_(r'^hr_application_create/$'), hrapplications.views.hr_application_create_view, + name="auth_hrapplication_create_view"), + url(_(r'^hr_application_create/(\d+)'), hrapplications.views.hr_application_create_view, + name="auth_hrapplication_create_view"), + url(_(r'^hr_application_remove/(\w+)'), hrapplications.views.hr_application_remove, + name="auth_hrapplication_remove"), + url(_(r'hr_application_view/(\w+)'), hrapplications.views.hr_application_view, + name="auth_hrapplication_view"), + url(_(r'hr_application_personal_view/(\w+)'), hrapplications.views.hr_application_personal_view, + name="auth_hrapplication_personal_view"), + url(_(r'hr_application_personal_removal/(\w+)'), + hrapplications.views.hr_application_personal_removal, + name="auth_hrapplication_personal_removal"), + url(_(r'hr_application_approve/(\w+)'), hrapplications.views.hr_application_approve, + name="auth_hrapplication_approve"), + url(_(r'hr_application_reject/(\w+)'), hrapplications.views.hr_application_reject, + name="auth_hrapplication_reject"), + url(_(r'hr_application_search/'), hrapplications.views.hr_application_search, + name="auth_hrapplication_search"), + url(_(r'hr_mark_in_progress/(\w+)'), hrapplications.views.hr_application_mark_in_progress, + name="auth_hrapplication_mark_in_progress"), + + # Fleet Operations Timers + 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'^remove_optimer/(\w+)'), optimer.views.remove_optimer, name='auth_remove_optimer'), + url(_(r'^edit_optimer/(\w+)$'), optimer.views.edit_optimer, name='auth_edit_optimer'), + + # Service Urls + url(_(r'^services/$'), services.views.services_view, name='auth_services'), + url(_(r'^services/jabber_broadcast/$'), services.views.jabber_broadcast_view, + name='auth_jabber_broadcast_view'), + + # Teamspeak Urls + url(r'verify_teamspeak3/$', services.views.verify_teamspeak3, name='auth_verify_teamspeak3'), + + # corputils + url(_(r'^corputils/$'), corputils.views.corp_member_view, name='auth_corputils'), + url(_(r'^corputils/(?P[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/(?P[0-9]+)/$'), corputils.views.corputils_search, name='auth_corputils_search_corp'), + + # Timer URLS + 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'^remove_timer/(\w+)'), timerboard.views.remove_timer, name='auth_remove_timer'), + url(_(r'^edit_timer/(\w+)$'), timerboard.views.edit_timer, name='auth_edit_timer'), + + # SRP URLS + 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_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_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_amount_update/(\w+)'), srp.views.srp_request_update_amount_view, + name="auth_srp_request_update_amount_view"), + + # Tools + url(_(r'^tool/fleet_formatter_tool/$'), services.views.fleet_formatter_view, + name='auth_fleet_format_tool_view'), + + # Notifications + url(_(r'^notifications/$'), notifications.views.notification_list, name='auth_notification_list'), + url(_(r'^notifications/(\w+)/$'), notifications.views.notification_view, name='auth_notification_view'), + + # Jabber + url(_(r'^set_jabber_password/$'), services.views.set_jabber_password, name='auth_set_jabber_password'), + + # FleetActivityTracking (FAT) + 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/(?P[0-9]+)/(?P[0-9]+)/$', fleetactivitytracking.views.fatlink_statistics_view, + name='auth_fatlink_view_statistics_month'), + url(r'^fat/user/statistics/$', fleetactivitytracking.views.fatlink_personal_statistics_view, + name='auth_fatlink_view_personal_statistics'), + url(r'^fat/user/statistics/(?P[0-9]+)/$', fleetactivitytracking.views.fatlink_personal_statistics_view, + name='auth_fatlink_view_personal_statistics_year'), + url(r'^fat/user/statistics/(?P[0-9]+)/(?P[0-9]+)/$', + fleetactivitytracking.views.fatlink_monthly_personal_statistics_view, + name='auth_fatlink_view_personal_statistics_month'), + url(r'^fat/user/(?P[0-9]+)/statistics/(?P[0-9]+)/(?P[0-9]+)/$', + fleetactivitytracking.views.fatlink_monthly_personal_statistics_view, + name='auth_fatlink_view_user_statistics_month'), + 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/(?P[a-zA-Z0-9_-]+)/([a-z0-9_-]+)$', + fleetactivitytracking.views.modify_fatlink_view), + url(r'^fat/link/$', fleetactivitytracking.views.fatlink_view, name='auth_click_fatlink_view'), + url(r'^fat/link/(?P[a-zA-Z0-9]+)/(?P[a-z0-9_-]+)/$', + fleetactivitytracking.views.click_fatlink_view), ) - diff --git a/alliance_auth/wsgi.py b/alliance_auth/wsgi.py index cd1742c0..a5087167 100644 --- a/alliance_auth/wsgi.py +++ b/alliance_auth/wsgi.py @@ -8,14 +8,13 @@ https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ """ import os +from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings") -from django.core.wsgi import get_wsgi_application - -# virtualenv wrapper -#activate_env=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'env/bin/activate_this.py') -#execfile(activate_env, dict(__file__=activate_env)) +# virtualenv wrapper, uncomment below to activate +# activate_env=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'env/bin/activate_this.py') +# execfile(activate_env, dict(__file__=activate_env)) application = get_wsgi_application() diff --git a/authentication/__init__.py b/authentication/__init__.py index e69de29b..8c013e8e 100644 --- a/authentication/__init__.py +++ b/authentication/__init__.py @@ -0,0 +1,2 @@ +from __future__ import unicode_literals +default_app_config = 'authentication.apps.AuthenticationConfig' diff --git a/authentication/admin.py b/authentication/admin.py index 5c40a0d5..dc41e4f8 100644 --- a/authentication/admin.py +++ b/authentication/admin.py @@ -1,7 +1,146 @@ +from __future__ import unicode_literals + 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.site.register(AuthServicesInfo) \ No newline at end of file +@admin.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') diff --git a/authentication/apps.py b/authentication/apps.py new file mode 100644 index 00000000..7fb56f6e --- /dev/null +++ b/authentication/apps.py @@ -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 diff --git a/authentication/context_processors.py b/authentication/context_processors.py new file mode 100644 index 00000000..d403df83 --- /dev/null +++ b/authentication/context_processors.py @@ -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, + } diff --git a/authentication/decorators.py b/authentication/decorators.py new file mode 100644 index 00000000..1d3167cb --- /dev/null +++ b/authentication/decorators.py @@ -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) diff --git a/authentication/forms.py b/authentication/forms.py index 3774277b..76aa3771 100644 --- a/authentication/forms.py +++ b/authentication/forms.py @@ -1,7 +1,42 @@ +from __future__ import unicode_literals from django import forms from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.models import User +import re class LoginForm(forms.Form): username = forms.CharField(label=_('Username'), max_length=32, required=True) - password = forms.CharField(label=_('Password'), widget=forms.PasswordInput()) \ No newline at end of file + 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 diff --git a/authentication/managers.py b/authentication/managers.py index 1ab279b0..f9376a42 100755 --- a/authentication/managers.py +++ b/authentication/managers.py @@ -1,40 +1,22 @@ +from __future__ import unicode_literals from django.contrib.auth.models import User -from models import AuthServicesInfo +from authentication.models import AuthServicesInfo import logging logger = logging.getLogger(__name__) + class AuthServicesInfoManager: def __init__(self): pass @staticmethod - def __get_or_create(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): + def update_main_char_id(char_id, user): if User.objects.filter(username=user.username).exists(): 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.save(update_fields=['main_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)) @staticmethod - def update_user_forum_info(username, password, user): + def update_user_forum_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['forum_username', 'forum_password']) + authserviceinfo.save(update_fields=['forum_username']) logger.info("Updated user %s forum info in authservicesinfo model." % user) else: logger.error("Failed to update user %s forum info: user does not exist." % user) @staticmethod - def update_user_jabber_info(username, password, user): + def update_user_jabber_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['jabber_username', 'jabber_password']) + authserviceinfo.save(update_fields=['jabber_username']) logger.info("Updated user %s jabber info in authservicesinfo model." % user) else: logger.error("Failed to update user %s jabber info: user does not exist." % user) - @staticmethod - def update_user_mumble_info(username, password, user): + def update_user_mumble_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['mumble_username', 'mumble_password']) + authserviceinfo.save(update_fields=['mumble_username']) logger.info("Updated user %s mumble info in authservicesinfo model." % user) else: logger.error("Failed to update user %s mumble info: user does not exist." % user) @staticmethod - def update_user_ipboard_info(username, password, user): + def update_user_ipboard_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['ipboard_username', 'ipboard_password']) + authserviceinfo.save(update_fields=['ipboard_username']) logger.info("Updated user %s ipboard info in authservicesinfo model." % user) else: logger.error("Failed to update user %s ipboard info: user does not exist." % user) @staticmethod - def update_user_xenforo_info(username, password, user): + def update_user_xenforo_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['xenforo_username', 'xenforo_password']) + authserviceinfo.save(update_fields=['xenforo_username']) logger.info("Updated user %s xenforo info in authservicesinfo model." % user) else: 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): if User.objects.filter(username=user.username).exists(): 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_perm_key = perm_key authserviceinfo.save(update_fields=['teamspeak3_uid', 'teamspeak3_perm_key']) @@ -118,7 +94,7 @@ class AuthServicesInfoManager: def update_is_blue(is_blue, user): if User.objects.filter(username=user.username).exists(): 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.save(update_fields=['is_blue']) logger.info("Updated user %s blue status to %s in authservicesinfo model." % (user, is_blue)) @@ -127,70 +103,54 @@ class AuthServicesInfoManager: def update_user_discord_info(user_id, user): if User.objects.filter(username=user.username).exists(): 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.save(update_fields=['discord_uid']) logger.info("Updated user %s discord info in authservicesinfo model." % user) else: logger.error("Failed to update user %s discord info: user does not exist." % user) - + @staticmethod - def update_user_discourse_info(username, password, user): + def update_user_discourse_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['discourse_username', 'discourse_password']) + authserviceinfo.save(update_fields=['discourse_username']) logger.info("Updated user %s discourse info in authservicesinfo model." % user) else: logger.error("Failed to update user %s discourse info: user does not exist." % user) @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(): 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_password = password 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) else: logger.error("Failed to update user %s IPS4 info: user does not exist." % user) @staticmethod - def update_user_smf_info(username, password, user): + def update_user_smf_info(username, user): if User.objects.filter(username=user.username).exists(): 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_password = password - authserviceinfo.save(update_fields=['smf_username', 'smf_password']) + authserviceinfo.save(update_fields=['smf_username']) logger.info("Updated user %s smf info in authservicesinfo model." % user) else: logger.error("Failed to update user %s smf info: user does not exist." % user) @staticmethod - def update_user_market_info(username, password, user): + def update_user_market_info(username, 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 = AuthServicesInfo.objects.get_or_create(user=user)[0] authserviceinfo.market_username = username - authserviceinfo.market_password = password - authserviceinfo.save(update_fields=['market_username', 'market_password']) + authserviceinfo.save(update_fields=['market_username']) logger.info("Updated user %s market info in authservicesinfo model." % user) else: 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) diff --git a/authentication/migrations/0001_initial.py b/authentication/migrations/0001_initial.py new file mode 100644 index 00000000..8c5f1f2a --- /dev/null +++ b/authentication/migrations/0001_initial.py @@ -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)), + ], + ), + ] diff --git a/authentication/migrations/0002_auto_20160907_1914.py b/authentication/migrations/0002_auto_20160907_1914.py new file mode 100644 index 00000000..c6614a92 --- /dev/null +++ b/authentication/migrations/0002_auto_20160907_1914.py @@ -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', + ), + ] diff --git a/authentication/migrations/0003_authservicesinfo_state.py b/authentication/migrations/0003_authservicesinfo_state.py new file mode 100644 index 00000000..cac17cd3 --- /dev/null +++ b/authentication/migrations/0003_authservicesinfo_state.py @@ -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), + ), + ] diff --git a/authentication/migrations/0004_create_permissions.py b/authentication/migrations/0004_create_permissions.py new file mode 100644 index 00000000..3dc4acfb --- /dev/null +++ b/authentication/migrations/0004_create_permissions.py @@ -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) + ] diff --git a/authentication/migrations/0005_delete_perms.py b/authentication/migrations/0005_delete_perms.py new file mode 100644 index 00000000..e10f4253 --- /dev/null +++ b/authentication/migrations/0005_delete_perms.py @@ -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), + ] diff --git a/authentication/migrations/0006_auto_20160910_0542.py b/authentication/migrations/0006_auto_20160910_0542.py new file mode 100644 index 00000000..d7a24797 --- /dev/null +++ b/authentication/migrations/0006_auto_20160910_0542.py @@ -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', + ), + ] diff --git a/authentication/migrations/0007_remove_authservicesinfo_is_blue.py b/authentication/migrations/0007_remove_authservicesinfo_is_blue.py new file mode 100644 index 00000000..037c2092 --- /dev/null +++ b/authentication/migrations/0007_remove_authservicesinfo_is_blue.py @@ -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', + ), + ] diff --git a/authentication/migrations/0008_set_state.py b/authentication/migrations/0008_set_state.py new file mode 100644 index 00000000..91eccaf7 --- /dev/null +++ b/authentication/migrations/0008_set_state.py @@ -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) + ] diff --git a/portal/__init__.py b/authentication/migrations/__init__.py similarity index 100% rename from portal/__init__.py rename to authentication/migrations/__init__.py diff --git a/authentication/models.py b/authentication/models.py index aaed9119..b9a69bde 100755 --- a/authentication/models.py +++ b/authentication/models.py @@ -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.contrib.auth.models import User +from authentication.states import MEMBER_STATE, BLUE_STATE, NONE_STATE +@python_2_unicode_compatible 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_password = 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_password = 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_password = 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="") discord_uid = 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_password = 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_password = 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="") - is_blue = models.BooleanField(default=False) user = models.ForeignKey(User) + state = models.CharField(blank=True, null=True, choices=STATE_CHOICES, default=NONE_STATE, max_length=10) def __str__(self): return self.user.username + ' - AuthInfo' diff --git a/authentication/signals.py b/authentication/signals.py new file mode 100644 index 00000000..929eea6f --- /dev/null +++ b/authentication/signals.py @@ -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) diff --git a/authentication/states.py b/authentication/states.py new file mode 100644 index 00000000..48c76952 --- /dev/null +++ b/authentication/states.py @@ -0,0 +1,4 @@ +from __future__ import unicode_literals +MEMBER_STATE = 'Member' +BLUE_STATE = 'Blue' +NONE_STATE = None diff --git a/authentication/tasks.py b/authentication/tasks.py new file mode 100644 index 00000000..4e7ff355 --- /dev/null +++ b/authentication/tasks.py @@ -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) diff --git a/authentication/views.py b/authentication/views.py index 0d250b8e..6093c119 100644 --- a/authentication/views.py +++ b/authentication/views.py @@ -1,17 +1,21 @@ +from __future__ import unicode_literals from django.contrib.auth import login from django.contrib.auth import logout from django.contrib.auth import authenticate -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils import translation - -from forms import LoginForm - +from django.shortcuts import render, redirect +from django.contrib.auth.decorators import login_required +from eveonline.managers import EveManager +from eveonline.models import EveCharacter +from authentication.models import AuthServicesInfo +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 logger = logging.getLogger(__name__) + def login_user(request): logger.debug("login_user called by user %s" % request.user) if request.method == 'POST': @@ -24,24 +28,89 @@ def login_user(request): if user.is_active: logger.info("Successful login attempt from user %s" % user) login(request, user) - return HttpResponseRedirect("/dashboard/") + return redirect("auth_dashboard") else: logger.info("Login attempt failed for user %s: user marked inactive." % user) + messages.warning(request, 'Your account has been disabled.') else: logger.info("Failed login attempt: provided username %s" % form.cleaned_data['username']) - - return render_to_response('public/login.html', {'form': form, 'error': True}, - context_instance=RequestContext(request)) + messages.error(request, 'Username/password invalid.') + return render(request, 'public/login.html', context={'form': form}) else: logger.debug("Providing new login form.") 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): logger.debug("logout_user called by user %s" % request.user) - logoutUser = request.user + temp_user = request.user logout(request) - logger.info("Successful logout for user %s" % logoutUser) - return HttpResponseRedirect("/") \ No newline at end of file + logger.info("Successful logout for user %s" % temp_user) + 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) diff --git a/celerytask/__init__.py b/celerytask/__init__.py deleted file mode 100644 index b31856c4..00000000 --- a/celerytask/__init__.py +++ /dev/null @@ -1 +0,0 @@ -import signals diff --git a/celerytask/admin.py b/celerytask/admin.py deleted file mode 100644 index c608d24f..00000000 --- a/celerytask/admin.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.contrib import admin - -from models import SyncGroupCache - - -# Register your models here. -admin.site.register(SyncGroupCache) \ No newline at end of file diff --git a/celerytask/models.py b/celerytask/models.py deleted file mode 100755 index 3d14398a..00000000 --- a/celerytask/models.py +++ /dev/null @@ -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' diff --git a/celerytask/tasks.py b/celerytask/tasks.py deleted file mode 100644 index 40725a30..00000000 --- a/celerytask/tasks.py +++ /dev/null @@ -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() diff --git a/celerytask/tests.py b/celerytask/tests.py deleted file mode 100644 index a39b155a..00000000 --- a/celerytask/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/celerytask/views.py b/celerytask/views.py deleted file mode 100644 index 60f00ef0..00000000 --- a/celerytask/views.py +++ /dev/null @@ -1 +0,0 @@ -# Create your views here. diff --git a/corputils/__init__.py b/corputils/__init__.py index e69de29b..baffc488 100644 --- a/corputils/__init__.py +++ b/corputils/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/corputils/admin.py b/corputils/admin.py index e69de29b..baffc488 100644 --- a/corputils/admin.py +++ b/corputils/admin.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/corputils/apps.py b/corputils/apps.py new file mode 100644 index 00000000..677d5fcb --- /dev/null +++ b/corputils/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class CorpUtilsConfig(AppConfig): + name = 'corputils' diff --git a/corputils/forms.py b/corputils/forms.py index d58129f9..0a05bd8a 100644 --- a/corputils/forms.py +++ b/corputils/forms.py @@ -1,9 +1,8 @@ +from __future__ import unicode_literals from django import forms -from django.conf import settings from django.utils.translation import ugettext_lazy as _ -from eveonline.models import EveCorporationInfo -from eveonline.models import EveAllianceInfo 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...')})) diff --git a/corputils/models.py b/corputils/models.py index e69de29b..baffc488 100644 --- a/corputils/models.py +++ b/corputils/models.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/corputils/views.py b/corputils/views.py index 5038a961..99335206 100644 --- a/corputils/views.py +++ b/corputils/views.py @@ -1,12 +1,11 @@ +from __future__ import unicode_literals 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.shortcuts import HttpResponseRedirect +from django.shortcuts import render, redirect 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.evewho_manager import EveWhoManager from eveonline.models import EveCorporationInfo @@ -14,14 +13,15 @@ from eveonline.models import EveAllianceInfo from eveonline.models import EveCharacter from eveonline.models import EveApiKeyPair from fleetactivitytracking.models import Fat -from util import check_if_user_has_permission -from forms import CorputilsSearchForm +from corputils.forms import CorputilsSearchForm from evelink.api import APIError import logging import datetime logger = logging.getLogger(__name__) + + class Player(object): def __init__(self, main, user, maincorp, maincorpid, altlist, apilist, n_fats): self.main = main @@ -32,21 +32,23 @@ class Player(object): self.apilist = apilist self.n_fats = n_fats + def first_day_of_next_month(year, month): if month == 12: - return datetime.datetime(year+1,1,1) + return datetime.datetime(year + 1, 1, 1) else: - return datetime.datetime(year, month+1, 1) + return datetime.datetime(year, month + 1, 1) + def first_day_of_previous_month(year, month): if month == 1: - return datetime.datetime(year-1,12,1) + return datetime.datetime(year - 1, 12, 1) else: - return datetime.datetime(year, month-1, 1) + return datetime.datetime(year, month - 1, 1) @login_required -def corp_member_view(request, corpid = None, year=datetime.date.today().year, month=datetime.date.today().month): +def corp_member_view(request, corpid=None, year=datetime.date.today().year, month=datetime.date.today().month): year = int(year) month = int(month) start_of_month = datetime.datetime(year, month, 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) 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) except (ValueError, EveCharacter.DoesNotExist): user_corp_id = settings.CORP_ID - if not settings.IS_CORP: alliance = EveAllianceInfo.objects.get(alliance_id=settings.ALLIANCE_ID) 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]) 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 if not corpid: - if(settings.IS_CORP): + if settings.IS_CORP: corpid = settings.CORP_ID elif 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) - 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") 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_owner = char.user 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) mainname = mainchar.character_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." maincorpid = None api_pair = None - num_registered_characters = num_registered_characters + 1 + num_registered_characters += 1 characters_with_api.setdefault(mainname, Player(main=mainchar, user=char_owner, maincorp=maincorp, @@ -132,7 +136,7 @@ def corp_member_view(request, corpid = None, year=datetime.date.today().year, mo if 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"]}) 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) char_owner = char.user 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) mainname = mainchar.character_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." maincorpid = None api_pair = None - num_registered_characters = num_registered_characters + 1 + num_registered_characters += 1 characters_with_api.setdefault(mainname, Player(main=mainchar, user=char_owner, 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)) 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) if start_of_next_month > datetime.datetime.now(): start_of_next_month = None - if not settings.IS_CORP: context = {"membercorplist": membercorplist, "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["this_month"] = start_of_month - return render_to_response('registered/corputils.html',context, context_instance=RequestContext(request) ) - return HttpResponseRedirect("/dashboard/") + return render(request, 'registered/corputils.html', context=context) + return redirect("auth_dashboard") @login_required @@ -208,13 +212,15 @@ def corputils_search(request, corpid=settings.CORP_ID): authorized = False try: - user_main = EveCharacter.objects.get(character_id=AuthServicesInfoManager.get_auth_service_info(user=request.user).main_char_id) - 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)): + user_main = EveCharacter.objects.get( + 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") authorized = True except (ValueError, EveCharacter.DoesNotExist): - if check_if_user_has_permission(request.user, 'alliance_apis'): - logger.debug("Retreiving and sending API-information") + if request.user.has_perm('auth.alliance_apis'): + logger.debug("Retrieving and sending API-information") authorized = True if authorized: @@ -229,14 +235,16 @@ def corputils_search(request, corpid=settings.CORP_ID): if settings.IS_CORP: 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: logger.debug("Corp API does not have membertracking scope, using EveWho data instead.") member_list = EveWhoManager.get_corporation_members(corpid) else: 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 = [] for memberid, member_data in member_list.items(): @@ -244,7 +252,7 @@ def corputils_search(request, corpid=settings.CORP_ID): try: char = EveCharacter.objects.get(character_name=member_data["name"]) 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) api_registered = True apiinfo = EveApiKeyPair.objects.get(api_id=char.api_id) @@ -254,25 +262,24 @@ def corputils_search(request, corpid=settings.CORP_ID): main = "" apiinfo = None - searchresults.append(SearchResult(name=member_data["name"], id=memberid, main=main, api_registered=api_registered, - character=char, apiinfo=apiinfo)) + searchresults.append(SearchResult(name=member_data["name"], id=memberid, main=main, + api_registered=api_registered, + 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_to_response('registered/corputilssearchview.html', - context, context_instance=RequestContext(request)) + return render(request, 'registered/corputilssearchview.html', + context=context) else: logger.debug("Form invalid - returning for user %s to retry." % request.user) context = {'corp': corp, 'members': None, 'search_form': CorputilsSearchForm()} - return render_to_response('registered/corputilssearchview.html', - context, context_instance=RequestContext(request)) + return render(request, 'registered/corputilssearchview.html', context=context) else: logger.debug("Returning empty search form for user %s" % request.user) - return HttpResponseRedirect("/corputils/") - return HttpResponseRedirect("/dashboard/") - - + return redirect("auth_corputils") + return redirect("auth_dashboard") diff --git a/eveonline/__init__.py b/eveonline/__init__.py index e69de29b..baffc488 100644 --- a/eveonline/__init__.py +++ b/eveonline/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/eveonline/admin.py b/eveonline/admin.py index 7b0e7f22..5586c875 100644 --- a/eveonline/admin.py +++ b/eveonline/admin.py @@ -1,24 +1,28 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import EveCharacter -from models import EveApiKeyPair -from models import EveAllianceInfo -from models import EveCorporationInfo -from authentication.managers import AuthServicesInfoManager +from eveonline.models import EveCharacter +from eveonline.models import EveApiKeyPair +from eveonline.models import EveAllianceInfo +from eveonline.models import EveCorporationInfo +from authentication.models import AuthServicesInfo admin.site.register(EveAllianceInfo) admin.site.register(EveCorporationInfo) + class EveApiKeyPairAdmin(admin.ModelAdmin): search_fields = ['api_id', 'user__username'] list_display = ['api_id', 'user'] + class EveCharacterAdmin(admin.ModelAdmin): search_fields = ['character_name', 'corporation_name', 'alliance_name', 'user__username', 'api_id'] list_display = ('character_name', 'corporation_name', 'alliance_name', 'user', 'main_character') - def main_character(self, obj): - auth = AuthServicesInfoManager.get_auth_service_info(obj.user) + @staticmethod + def main_character(obj): + auth = AuthServicesInfo.objects.get_or_create(user=obj.user)[0] if auth and auth.main_char_id: try: return EveCharacter.objects.get(character_id=auth.main_char_id) @@ -26,5 +30,6 @@ class EveCharacterAdmin(admin.ModelAdmin): pass return None + admin.site.register(EveCharacter, EveCharacterAdmin) admin.site.register(EveApiKeyPair, EveApiKeyPairAdmin) diff --git a/eveonline/apps.py b/eveonline/apps.py new file mode 100644 index 00000000..866e59e8 --- /dev/null +++ b/eveonline/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class EveonlineConfig(AppConfig): + name = 'eveonline' diff --git a/eveonline/forms.py b/eveonline/forms.py index eff7a873..7588fdbc 100644 --- a/eveonline/forms.py +++ b/eveonline/forms.py @@ -1,23 +1,24 @@ +from __future__ import unicode_literals from django import forms from django.conf import settings from services.managers.eve_api_manager import EveApiManager from eveonline.managers import EveManager -from eveonline.models import EveCharacter import evelink -from celerytask.tasks import determine_membership_by_character - import logging 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_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): try: api_id = int(self.cleaned_data['api_id']) @@ -28,38 +29,21 @@ class UpdateKeyForm(forms.Form): def clean(self): 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']): - logger.debug("UpdateKeyForm failed cleaning as API id %s already exists." % self.cleaned_data['api_id']) - raise forms.ValidationError(u'API key already exist') - if EveApiManager.api_key_is_valid(self.cleaned_data['api_id'], self.cleaned_data['api_key']) is False: - raise forms.ValidationError(u'API key is invalid') - if (settings.REJECT_OLD_APIS and - EveManager.check_if_api_key_pair_is_new(self.cleaned_data['api_id'], settings.REJECT_OLD_APIS_MARGIN) is False): - raise forms.ValidationError(u'API key is too old. Please create a new key') - chars = EveApiManager.get_characters_from_api(self.cleaned_data['api_id'], self.cleaned_data['api_key']).result - 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 - except evelink.api.APIError as e: - logger.debug("Got error code %s while validating API %s" % (e.code, self.cleaned_data['api_id'])) - if int(e.code) in [221, 222]: - raise forms.ValidationError("API key failed validation") - else: - raise forms.ValidationError("Failed to reach API servers") + 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']) + raise forms.ValidationError('API key already exist') + if settings.REJECT_OLD_APIS and not EveManager.check_if_api_key_pair_is_new( + self.cleaned_data['api_id'], + settings.REJECT_OLD_APIS_MARGIN): + raise forms.ValidationError('API key is too old. Please create a new key') + try: + EveApiManager.validate_api(self.cleaned_data['api_id'], self.cleaned_data['api_key'], self.user) + return self.cleaned_data + except EveApiManager.ApiValidationError as e: + raise forms.ValidationError(str(e)) + except evelink.api.APIError as e: + logger.debug("Got error code %s while validating API %s" % (e.code, self.cleaned_data['api_id'])) + if int(e.code) in [221, 222]: + raise forms.ValidationError("API key failed validation") + else: + raise forms.ValidationError("Failed to reach API servers") diff --git a/eveonline/managers.py b/eveonline/managers.py index ebf249c6..214433e4 100644 --- a/eveonline/managers.py +++ b/eveonline/managers.py @@ -1,13 +1,15 @@ -from models import EveCharacter -from models import EveApiKeyPair -from models import EveAllianceInfo -from models import EveCorporationInfo +from __future__ import unicode_literals +from eveonline.models import EveCharacter +from eveonline.models import EveApiKeyPair +from eveonline.models import EveAllianceInfo +from eveonline.models import EveCorporationInfo from services.managers.eve_api_manager import EveApiManager import logging logger = logging.getLogger(__name__) + class EveManager: def __init__(self): pass @@ -64,8 +66,8 @@ class EveManager: eve_char.save() logger.info("Updated character model %s" % eve_char) 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 def create_api_keypair(api_id, api_key, user_id): @@ -163,10 +165,10 @@ class EveManager: return True latest_api_id = int(EveApiKeyPair.objects.order_by('-api_id')[0].api_id) - fudge_factor if latest_api_id >= api_id: - logger.debug("api key (%d) is older than latest API key (%d). Rejecting" % (api_id, latest_api_id) ) + logger.debug("api key (%d) is older than latest API key (%d). Rejecting" % (api_id, latest_api_id)) return False else: - logger.debug("api key (%d) is new. Accepting" % api_id ) + logger.debug("api key (%d) is new. Accepting" % api_id) return True @staticmethod @@ -179,7 +181,9 @@ class EveManager: logger.info("Deleted user %s api key id %s" % (user_id, api_id)) apikeypair.delete() 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: 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)) char.delete() 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 def check_if_character_exist(char_name): diff --git a/eveonline/migrations/0001_initial.py b/eveonline/migrations/0001_initial.py new file mode 100644 index 00000000..cf3ebde0 --- /dev/null +++ b/eveonline/migrations/0001_initial.py @@ -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')), + ], + ), + ] diff --git a/eveonline/migrations/0002_remove_eveapikeypair_error_count.py b/eveonline/migrations/0002_remove_eveapikeypair_error_count.py new file mode 100644 index 00000000..52fca062 --- /dev/null +++ b/eveonline/migrations/0002_remove_eveapikeypair_error_count.py @@ -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', + ), + ] diff --git a/registration/__init__.py b/eveonline/migrations/__init__.py similarity index 100% rename from registration/__init__.py rename to eveonline/migrations/__init__.py diff --git a/eveonline/models.py b/eveonline/models.py index f55b4b11..f3926a6f 100644 --- a/eveonline/models.py +++ b/eveonline/models.py @@ -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.contrib.auth.models import User +@python_2_unicode_compatible class EveCharacter(models.Model): character_id = models.CharField(max_length=254) character_name = models.CharField(max_length=254) @@ -17,16 +20,17 @@ class EveCharacter(models.Model): return self.character_name +@python_2_unicode_compatible class EveApiKeyPair(models.Model): api_id = models.CharField(max_length=254) api_key = models.CharField(max_length=254) user = models.ForeignKey(User) - error_count = models.PositiveIntegerField(default=0) def __str__(self): return self.user.username + " - ApiKeyPair" +@python_2_unicode_compatible class EveAllianceInfo(models.Model): alliance_id = models.CharField(max_length=254) alliance_name = models.CharField(max_length=254) @@ -39,6 +43,7 @@ class EveAllianceInfo(models.Model): return self.alliance_name +@python_2_unicode_compatible class EveCorporationInfo(models.Model): corporation_id = models.CharField(max_length=254) corporation_name = models.CharField(max_length=254) diff --git a/eveonline/tasks.py b/eveonline/tasks.py new file mode 100644 index 00000000..48ee7c89 --- /dev/null +++ b/eveonline/tasks.py @@ -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) diff --git a/eveonline/views.py b/eveonline/views.py index 4b65ecb9..d224d3c1 100755 --- a/eveonline/views.py +++ b/eveonline/views.py @@ -1,59 +1,27 @@ -from django.conf import settings -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response -from django.template import RequestContext +from __future__ import unicode_literals +from django.shortcuts import render, redirect 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 util import remove_member_permission -from util import check_if_user_has_permission -from forms import UpdateKeyForm -from managers import EveManager +from eveonline.forms import UpdateKeyForm +from eveonline.managers import EveManager from authentication.managers import AuthServicesInfoManager 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 authentication.models import AuthServicesInfo -from celerytask.tasks import determine_membership_by_user -from celerytask.tasks import set_state -from celerytask.tasks import refresh_api +from authentication.tasks import set_state +from eveonline.tasks import refresh_api import logging 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 def add_api_key(request): logger.debug("add_api_key called by user %s" % request.user) - user_state = determine_membership_by_user(request.user) if request.method == 'POST': - form = UpdateKeyForm(request.POST) - form.user_state=user_state + form = UpdateKeyForm(request.user, request.POST) logger.debug("Request type POST with form valid: %s" % form.is_valid()) if form.is_valid(): EveManager.create_api_keypair(form.cleaned_data['api_id'], @@ -65,16 +33,18 @@ def add_api_key(request): form.cleaned_data['api_key']) 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) - 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: logger.debug("Form invalid: returning to form.") else: logger.debug("Providing empty update key form for user %s" % request.user) - form = UpdateKeyForm() - form.user_state = user_state + form = UpdateKeyForm(request.user) context = {'form': form, 'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} - return render_to_response('registered/addapikey.html', context, - context_instance=RequestContext(request)) + return render(request, 'registered/addapikey.html', context=context) @login_required @@ -82,51 +52,48 @@ def api_key_management_view(request): logger.debug("api_key_management_view called by user %s" % request.user) context = {'apikeypairs': EveManager.get_api_key_pairs(request.user.id)} - return render_to_response('registered/apikeymanagment.html', context, - context_instance=RequestContext(request)) + return render(request, 'registered/apikeymanagment.html', context=context) @login_required def api_key_removal(request, 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 characters = EveManager.get_characters_by_owner_id(request.user.id) if characters is not None: for character in characters: if character.character_id == authinfo.main_char_id: if character.api_id == api_id: - # TODO: Remove services also - if authinfo.is_blue: - logger.debug("Blue user %s deleting api for main character. Disabling." % 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) + messages.warning(request, + 'You have deleted your main character. Please select a new main character.') + set_state(request.user) EveManager.delete_api_key_pair(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)) - return HttpResponseRedirect("/api_key_management/") + return redirect("auth_api_key_management") @login_required def characters_view(request): logger.debug("characters_view called by user %s" % request.user) render_items = {'characters': EveManager.get_characters_by_owner_id(request.user.id), - 'authinfo': AuthServicesInfoManager.get_auth_service_info(request.user)} - return render_to_response('registered/characters.html', render_items, context_instance=RequestContext(request)) + 'authinfo': AuthServicesInfo.objects.get_or_create(user=request.user)[0]} + return render(request, 'registered/characters.html', context=render_items) @login_required def main_character_change(request, 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): - AuthServicesInfoManager.update_main_char_Id(char_id, request.user) + AuthServicesInfoManager.update_main_char_id(char_id, request.user) set_state(request.user) - return HttpResponseRedirect("/characters/") - return HttpResponseRedirect("/characters/") - + messages.success(request, 'Changed main character ID to %s' % char_id) + 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 @@ -136,9 +103,12 @@ def user_refresh_api(request, api_id): api_key_pair = EveApiKeyPair.objects.get(api_id=api_id) if api_key_pair.user == request.user: refresh_api(api_key_pair) + messages.success(request, 'Refreshed API key %s' % api_id) set_state(request.user) 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)) 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)) - return HttpResponseRedirect("/api_key_management/") + return redirect("auth_api_key_management") diff --git a/fleetactivitytracking/__init__.py b/fleetactivitytracking/__init__.py index e69de29b..baffc488 100644 --- a/fleetactivitytracking/__init__.py +++ b/fleetactivitytracking/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/fleetactivitytracking/admin.py b/fleetactivitytracking/admin.py index 19a3a4ce..b000d7f2 100644 --- a/fleetactivitytracking/admin.py +++ b/fleetactivitytracking/admin.py @@ -1,5 +1,6 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import Fatlink, Fat +from fleetactivitytracking.models import Fatlink, Fat admin.site.register(Fatlink) diff --git a/fleetactivitytracking/apps.py b/fleetactivitytracking/apps.py new file mode 100644 index 00000000..219e0b38 --- /dev/null +++ b/fleetactivitytracking/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class FatConfig(AppConfig): + name = 'fleetactivitytracking' diff --git a/fleetactivitytracking/forms.py b/fleetactivitytracking/forms.py index 20dfc9c3..4d5c256d 100644 --- a/fleetactivitytracking/forms.py +++ b/fleetactivitytracking/forms.py @@ -1,7 +1,9 @@ +from __future__ import unicode_literals from django import forms from optimer.models import optimer from django.utils.translation import ugettext_lazy as _ + def get_fleet_list(): fleets = optimer.objects.all() fleetlist = [("None", "None")] @@ -13,5 +15,6 @@ def get_fleet_list(): class FatlinkForm(forms.Form): 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) - fleet = forms.ModelChoiceField(label=_("Fleet"), queryset=optimer.objects.all().order_by('operation_name')) \ No newline at end of file + 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')) diff --git a/fleetactivitytracking/migrations/0001_initial.py b/fleetactivitytracking/migrations/0001_initial.py new file mode 100644 index 00000000..75671c1a --- /dev/null +++ b/fleetactivitytracking/migrations/0001_initial.py @@ -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')]), + ), + ] diff --git a/fleetactivitytracking/migrations/0002_auto_20160905_2220.py b/fleetactivitytracking/migrations/0002_auto_20160905_2220.py new file mode 100644 index 00000000..8036c208 --- /dev/null +++ b/fleetactivitytracking/migrations/0002_auto_20160905_2220.py @@ -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)), + ), + ] diff --git a/fleetactivitytracking/migrations/0003_auto_20160906_2354.py b/fleetactivitytracking/migrations/0003_auto_20160906_2354.py new file mode 100644 index 00000000..63e30401 --- /dev/null +++ b/fleetactivitytracking/migrations/0003_auto_20160906_2354.py @@ -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), + ), + ] diff --git a/sigtracker/__init__.py b/fleetactivitytracking/migrations/__init__.py similarity index 100% rename from sigtracker/__init__.py rename to fleetactivitytracking/migrations/__init__.py diff --git a/fleetactivitytracking/models.py b/fleetactivitytracking/models.py index d10806a1..acd4c50c 100644 --- a/fleetactivitytracking/models.py +++ b/fleetactivitytracking/models.py @@ -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.contrib.auth.models import User -from optimer.models import optimer from eveonline.models import EveCharacter -from datetime import datetime -from datetime import date from django.utils import timezone + def get_sentinel_user(): return User.objects.get_or_create(username='deleted')[0] + +@python_2_unicode_compatible class Fatlink(models.Model): - fatdatetime = models.DateTimeField(default=timezone.now()) + fatdatetime = models.DateTimeField(default=timezone.now) duration = models.PositiveIntegerField() fleet = models.CharField(max_length=254, default="") name = models.CharField(max_length=254) @@ -21,6 +23,7 @@ class Fatlink(models.Model): return self.name +@python_2_unicode_compatible class Fat(models.Model): character = models.ForeignKey(EveCharacter, on_delete=models.CASCADE) fatlink = models.ForeignKey(Fatlink) diff --git a/fleetactivitytracking/views.py b/fleetactivitytracking/views.py index 919c45f8..467efb84 100644 --- a/fleetactivitytracking/views.py +++ b/fleetactivitytracking/views.py @@ -1,19 +1,17 @@ +from __future__ import unicode_literals from django.conf import settings -from django.shortcuts import HttpResponseRedirect -from django.shortcuts import render_to_response +from django.shortcuts import render, redirect from django.core.exceptions import ObjectDoesNotExist from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required -from django.template import RequestContext from django.core.exceptions import ValidationError from django.utils import timezone from eveonline.models import EveCharacter from eveonline.models import EveCorporationInfo from eveonline.managers import EveManager -from util import check_if_user_has_permission -from forms import FatlinkForm -from models import Fatlink, Fat +from fleetactivitytracking.forms import FatlinkForm +from fleetactivitytracking.models import Fatlink, Fat from slugify import slugify @@ -23,7 +21,6 @@ import string import random import datetime - import logging logger = logging.getLogger(__name__) @@ -34,24 +31,26 @@ class CorpStat(object): if corp: self.corp = corp else: - self.corp = EveCorporationInfo.objects.get(corporation_id=corp_id) + self.corp = EveCorporationInfo.objects.get(corporation_id=corp_id) self.n_fats = 0 self.blue = blue 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): if month == 12: - return datetime.datetime(year+1,1,1) + return datetime.datetime(year + 1, 1, 1) else: - return datetime.datetime(year, month+1, 1) + return datetime.datetime(year, month + 1, 1) + def first_day_of_previous_month(year, month): if month == 1: - return datetime.datetime(year-1,12,1) + return datetime.datetime(year - 1, 12, 1) else: - return datetime.datetime(year, month-1, 1) + return datetime.datetime(year, month - 1, 1) @login_required @@ -63,14 +62,14 @@ def fatlink_view(request): logger.debug("fatlink_view called by user %s" % request.user) 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] - context = {'user':user, 'fats': latest_fats, 'fatlinks': latest_links} + context = {'user': user, 'fats': latest_fats, 'fatlinks': latest_links} 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 @@ -91,7 +90,8 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date for corp in alliance_corps: 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: fats_in_fatlink = Fat.objects.filter(fatlink=fatlink) @@ -102,15 +102,16 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date fatStatsList = [fatStat for corp_name, fatStat in fatStats.items()] fatStatsList.sort(key=lambda stat: stat.corp.corporation_name) - 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: - 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: - 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)) + context = {'fatStats': fatStatsList, 'month': start_of_month.strftime("%B"), 'year': year, + 'previous_month': start_of_previous_month} + return render(request, 'registered/fatlinkstatisticsview.html', context=context) @login_required @@ -123,21 +124,22 @@ def fatlink_personal_statistics_view(request, year=datetime.date.today().year, m personal_fats = Fat.objects.filter(user=user).order_by('id') - monthlystats = [0 for month in range(1,13)] + monthlystats = [0 for month in range(1, 13)] for fat in personal_fats: fatdate = fat.fatlink.fatdatetime if fatdate.year == year: - monthlystats[fatdate.month-1] += 1 + monthlystats[fatdate.month - 1] += 1 - 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): - context = {'user':user, 'monthlystats': monthlystats, 'year':year, 'previous_year':year-1, 'next_year':year+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} 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 @@ -148,28 +150,30 @@ 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_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 else: 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() n_fats = 0 for fat in personal_fats: ship_statistics[fat.shiptype] = ship_statistics.setdefault(fat.shiptype, 0) + 1 n_fats += 1 - context = {'user': user, 'shipStats':sorted(ship_statistics.items()), 'month':start_of_month.strftime("%h"), - 'year':year, 'n_fats': n_fats, 'char_id': char_id, 'previous_month': start_of_previous_month, + context = {'user': user, 'shipStats': sorted(ship_statistics.items()), 'month': start_of_month.strftime("%h"), + 'year': year, 'n_fats': n_fats, 'char_id': char_id, 'previous_month': start_of_previous_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["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 @@ -182,10 +186,8 @@ def click_fatlink_view(request, hash, fatname): # Retrieve the latest fatlink using the hash. try: fatlink = Fatlink.objects.filter(hash=hash)[0] - valid = True - if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration*60)): - active = True + if (timezone.now() - fatlink.fatdatetime) < datetime.timedelta(seconds=(fatlink.duration * 60)): 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()) context = {'trusted': True, 'errormessages': messages} else: - context = {'character_id': request.META['HTTP_EVE_CHARID'], 'character_name': request.META['HTTP_EVE_CHARNAME']} - return render_to_response('public/characternotexisting.html', context, context_instance=RequestContext(request)) + context = {'character_id': request.META['HTTP_EVE_CHARID'], + 'character_name': request.META['HTTP_EVE_CHARNAME']} + return render(request, 'public/characternotexisting.html', context=context) else: context = {'trusted': True, 'expired': True} except ObjectDoesNotExist: context = {'trusted': True} else: 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 @@ -237,7 +240,7 @@ def create_fatlink_view(request): fatlink.duration = form.cleaned_data["duration"] fatlink.fatdatetime = timezone.now() fatlink.creator = request.user - fatlink.hash = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(10)) + fatlink.hash = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(10)) try: fatlink.full_clean() fatlink.save() @@ -247,12 +250,12 @@ def create_fatlink_view(request): for errorname, message in e.message_dict.items(): messages.append(message[0].decode()) 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: form = FatlinkForm() context = {'form': form, 'badrequest': True} - return render_to_response('registered/fatlinkformatter.html', context, context_instance=RequestContext(request)) - return HttpResponseRedirect('/fat/') + return render(request, 'registered/fatlinkformatter.html', context=context) + return redirect('auth_fatlink_view') else: form = FatlinkForm() @@ -260,7 +263,7 @@ def create_fatlink_view(request): 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 @@ -268,25 +271,24 @@ def create_fatlink_view(request): def modify_fatlink_view(request, hash=""): logger.debug("modify_fatlink_view called by user %s" % request.user) if not hash: - return HttpResponseRedirect('/fat/') + return redirect('/fat/') fatlink = Fatlink.objects.filter(hash=hash)[0] - if(request.GET.get('removechar')): + if request.GET.get('removechar'): character_id = request.GET.get('removechar') 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() - if(request.GET.get('deletefat')): + if request.GET.get('deletefat'): logger.debug("Removing fleetactivitytracking %s" % fatlink.name) fatlink.delete() - return HttpResponseRedirect('/fat/') + return redirect('/fat/') registered_fats = Fat.objects.filter(fatlink=fatlink).order_by('character') - context = {'fatlink':fatlink, 'registered_fats':registered_fats} - - return render_to_response('registered/fatlinkmodify.html', context, context_instance=RequestContext(request)) + context = {'fatlink': fatlink, 'registered_fats': registered_fats} + return render(request, 'registered/fatlinkmodify.html', context=context) diff --git a/fleetup/__init__.py b/fleetup/__init__.py index e69de29b..baffc488 100755 --- a/fleetup/__init__.py +++ b/fleetup/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/fleetup/admin.py b/fleetup/admin.py index e69de29b..baffc488 100755 --- a/fleetup/admin.py +++ b/fleetup/admin.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/fleetup/apps.py b/fleetup/apps.py new file mode 100644 index 00000000..e8b5a203 --- /dev/null +++ b/fleetup/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class FleetupConfig(AppConfig): + name = 'fleetup' diff --git a/fleetup/forms.py b/fleetup/forms.py index e69de29b..baffc488 100755 --- a/fleetup/forms.py +++ b/fleetup/forms.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/fleetup/models.py b/fleetup/models.py index e69de29b..baffc488 100755 --- a/fleetup/models.py +++ b/fleetup/models.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/fleetup/views.py b/fleetup/views.py index 8c2bc0a8..b92fe451 100755 --- a/fleetup/views.py +++ b/fleetup/views.py @@ -1,42 +1,24 @@ +from __future__ import unicode_literals import datetime -from operator import itemgetter, attrgetter, methodcaller - -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.shortcuts import render from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required -from django.contrib.auth.decorators import user_passes_test -from django.shortcuts import HttpResponseRedirect 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 eveonline.models import EveCorporationInfo -from eveonline.models import EveAllianceInfo -from eveonline.models import EveCharacter -from authentication.models import AuthServicesInfo +from authentication.decorators import members_and_blues import logging logger = logging.getLogger(__name__) + @register.filter def get_item(dictionary, 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 -@user_passes_test(fleetup_util_test) +@members_and_blues() def fleetup_view(request): logger.debug("fleetup_view called by user %s" % request.user) @@ -48,7 +30,8 @@ def fleetup_view(request): "operations_list": sorted(operations_list.items()), "now": now} - return render_to_response('registered/fleetup.html',context, context_instance=RequestContext(request) ) + return render(request, 'registered/fleetup.html', context=context) + @login_required @permission_required('auth.human_resources') @@ -59,18 +42,20 @@ def fleetup_characters(request): 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 -@user_passes_test(fleetup_util_test) +@members_and_blues() def fleetup_fittings(request): logger.debug("fleetup_fittings called by user %s" % request.user) fitting_list = FleetUpManager.get_fleetup_fittings() 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 -@user_passes_test(fleetup_util_test) +@members_and_blues() def fleetup_fitting(request, fittingnumber): logger.debug("fleetup_fitting called by user %s" % request.user) fitting_eft = FleetUpManager.get_fleetup_fitting_eft(fittingnumber) @@ -80,22 +65,22 @@ def fleetup_fitting(request, fittingnumber): context = {"fitting_eft": fitting_eft, "fitting_data": fitting_data, "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 -@user_passes_test(fleetup_util_test) +@members_and_blues() def fleetup_doctrines(request): logger.debug("fleetup_doctrines called by user %s" % request.user) doctrines_list = FleetUpManager.get_fleetup_doctrines() 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 -@user_passes_test(fleetup_util_test) +@members_and_blues() def fleetup_doctrine(request, doctrinenumber): logger.debug("fleetup_doctrine called by user %s" % request.user) doctrine = FleetUpManager.get_fleetup_doctrine(doctrinenumber) context = {"doctrine": doctrine} - return render_to_response('registered/fleetupdoctrine.html',context, context_instance=RequestContext(request) ) - + return render(request, 'registered/fleetupdoctrine.html', context=context) diff --git a/groupmanagement/__init__.py b/groupmanagement/__init__.py index e69de29b..baffc488 100644 --- a/groupmanagement/__init__.py +++ b/groupmanagement/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/groupmanagement/admin.py b/groupmanagement/admin.py index 27e1ae99..4d21a00f 100644 --- a/groupmanagement/admin.py +++ b/groupmanagement/admin.py @@ -1,9 +1,10 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import GroupDescription -from models import GroupRequest -from models import HiddenGroup -from models import OpenGroup +from groupmanagement.models import GroupDescription +from groupmanagement.models import GroupRequest +from groupmanagement.models import HiddenGroup +from groupmanagement.models import OpenGroup admin.site.register(GroupDescription) diff --git a/groupmanagement/apps.py b/groupmanagement/apps.py new file mode 100644 index 00000000..74482d3d --- /dev/null +++ b/groupmanagement/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class GroupManagementConfig(AppConfig): + name = 'groupmanagement' diff --git a/groupmanagement/migrations/0001_initial.py b/groupmanagement/migrations/0001_initial.py new file mode 100644 index 00000000..60298099 --- /dev/null +++ b/groupmanagement/migrations/0001_initial.py @@ -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')), + ], + ), + ] diff --git a/groupmanagement/migrations/0002_auto_20160906_2354.py b/groupmanagement/migrations/0002_auto_20160906_2354.py new file mode 100644 index 00000000..4b8db963 --- /dev/null +++ b/groupmanagement/migrations/0002_auto_20160906_2354.py @@ -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'), + ), + ] diff --git a/groupmanagement/migrations/0003_default_groups.py b/groupmanagement/migrations/0003_default_groups.py new file mode 100644 index 00000000..c2af1db1 --- /dev/null +++ b/groupmanagement/migrations/0003_default_groups.py @@ -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) + ] diff --git a/groupmanagement/migrations/__init__.py b/groupmanagement/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/groupmanagement/models.py b/groupmanagement/models.py index 93776a48..ffad61aa 100644 --- a/groupmanagement/models.py +++ b/groupmanagement/models.py @@ -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.contrib.auth.models import User from django.contrib.auth.models import Group @@ -5,14 +7,16 @@ from django.contrib.auth.models import Group from eveonline.models import EveCharacter +@python_2_unicode_compatible class GroupDescription(models.Model): description = models.CharField(max_length=512) - group = models.ForeignKey(Group, unique=True) + group = models.OneToOneField(Group) def __str__(self): return self.group.name + " - Description" +@python_2_unicode_compatible class GroupRequest(models.Model): status = models.CharField(max_length=254) leave_request = models.BooleanField(default=0) @@ -23,12 +27,16 @@ class GroupRequest(models.Model): def __str__(self): return self.user.username + ":" + self.group.name + +@python_2_unicode_compatible class HiddenGroup(models.Model): - group = models.ForeignKey(Group, unique=True) + group = models.OneToOneField(Group) def __str__(self): return self.group.name + " - Hidden" + +@python_2_unicode_compatible class OpenGroup(models.Model): group = models.OneToOneField(Group) diff --git a/groupmanagement/views.py b/groupmanagement/views.py index 214e9530..9a9eaf91 100755 --- a/groupmanagement/views.py +++ b/groupmanagement/views.py @@ -1,16 +1,16 @@ -from django.template import RequestContext -from django.shortcuts import HttpResponseRedirect -from django.shortcuts import render_to_response +from __future__ import unicode_literals +from django.shortcuts import render, redirect from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required from django.contrib.auth.models import Group +from django.contrib import messages from notifications import notify -from models import GroupDescription -from models import GroupRequest -from models import HiddenGroup -from models import OpenGroup -from authentication.managers import AuthServicesInfoManager +from groupmanagement.models import GroupDescription +from groupmanagement.models import GroupRequest +from groupmanagement.models import HiddenGroup +from groupmanagement.models import OpenGroup +from authentication.models import AuthServicesInfo from eveonline.managers import EveManager from django.utils.translation import ugettext_lazy as _ @@ -18,6 +18,7 @@ import logging logger = logging.getLogger(__name__) + @login_required @permission_required('auth.group_management') def group_management(request): @@ -30,12 +31,12 @@ def group_management(request): leaverequests.append(grouprequest) else: 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} - return render_to_response('registered/groupmanagement.html', - render_items, context_instance=RequestContext(request)) + return render(request, 'registered/groupmanagement.html', context=render_items) @login_required @@ -48,13 +49,20 @@ def group_accept_request(request, group_request_id): group_request.user.groups.add(group) group_request.user.save() 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)) - notify(group_request.user, "Group Application Accepted", level="success", message="Your application to %s has been accepted." % group_request.group) + logger.info("User %s accepted group request from user %s to group %s" % ( + 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: - 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 - return HttpResponseRedirect("/group/management/") + return redirect("auth_group_management") @login_required @@ -65,51 +73,74 @@ def group_reject_request(request, group_request_id): group_request = GroupRequest.objects.get(id=group_request_id) 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() - 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: - 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 - return HttpResponseRedirect("/group/management/") + return redirect("auth_group_management") @login_required @permission_required('auth.group_management') 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: group_request = GroupRequest.objects.get(id=group_request_id) group, created = Group.objects.get_or_create(name=group_request.group.name) group_request.user.groups.remove(group) group_request.user.save() 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)) - notify(group_request.user, "Group Leave Request Accepted", level="success", message="Your request to leave %s has been accepted." % group_request.group) + logger.info("User %s accepted group leave request from user %s to group %s" % ( + 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: - 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 - return HttpResponseRedirect("/group/management/") + return redirect("auth_group_management") @login_required @permission_required('auth.group_management') 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: group_request = GroupRequest.objects.get(id=group_request_id) if group_request: 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)) - notify(group_request.user, "Group Leave Request Rejected", level="danger", message="Your request to leave %s has been rejected." % group_request.group) + logger.info("User %s rejected group leave request from user %s for group %s" % ( + 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: - 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 - return HttpResponseRedirect("/group/management/") + return redirect("auth_group_management") @login_required @@ -131,23 +162,22 @@ def groups_view(request): pass else: # Get the descriptionn - groupDesc = GroupDescription.objects.filter(group=group) - groupRequest = GroupRequest.objects.filter(user=request.user).filter(group=group) + group_desc = GroupDescription.objects.filter(group=group) + group_request = GroupRequest.objects.filter(user=request.user).filter(group=group) - if groupDesc: - if groupRequest: - paired_list.append((group, groupDesc[0], groupRequest[0])) + if group_desc: + if group_request: + paired_list.append((group, group_desc[0], group_request[0])) else: - paired_list.append((group, groupDesc[0], "")) + paired_list.append((group, group_desc[0], "")) else: - if groupRequest: - paired_list.append((group, "", groupRequest[0])) + if group_request: + paired_list.append((group, "", group_request[0])) else: paired_list.append((group, "", "")) render_items = {'pairs': paired_list} - return render_to_response('registered/groups.html', - render_items, context_instance=RequestContext(request)) + return render(request, 'registered/groups.html', context=render_items) @login_required @@ -157,8 +187,8 @@ def group_request_add(request, group_id): if OpenGroup.objects.filter(group=group).exists(): logger.info("%s joining %s as is an open group" % (request.user, group)) request.user.groups.add(group) - return HttpResponseRedirect("/groups") - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) + return redirect("auth_groups") + auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0] grouprequest = GroupRequest() grouprequest.status = _('Pending') grouprequest.group = group @@ -167,7 +197,8 @@ def group_request_add(request, group_id): grouprequest.leave_request = False grouprequest.save() 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 @@ -177,8 +208,8 @@ def group_request_leave(request, group_id): if OpenGroup.objects.filter(group=group).exists(): logger.info("%s leaving %s as is an open group" % (request.user, group)) request.user.groups.remove(group) - return HttpResponseRedirect("/groups") - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) + return redirect("auth_groups") + auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0] grouprequest = GroupRequest() grouprequest.status = _('Pending') grouprequest.group = group @@ -187,5 +218,5 @@ def group_request_leave(request, group_id): grouprequest.leave_request = True grouprequest.save() logger.info("Created group leave request for user %s to group %s" % (request.user, Group.objects.get(id=group_id))) - - return HttpResponseRedirect("/groups") + messages.success(request, 'Applied to leave group %s.' % group) + return redirect("auth_groups") diff --git a/hrapplications/__init__.py b/hrapplications/__init__.py index e69de29b..baffc488 100644 --- a/hrapplications/__init__.py +++ b/hrapplications/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/hrapplications/admin.py b/hrapplications/admin.py index 5b7e89aa..c334cad2 100755 --- a/hrapplications/admin.py +++ b/hrapplications/admin.py @@ -1,10 +1,11 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import Application -from models import ApplicationQuestion -from models import ApplicationForm -from models import ApplicationResponse -from models import ApplicationComment +from hrapplications.models import Application +from hrapplications.models import ApplicationQuestion +from hrapplications.models import ApplicationForm +from hrapplications.models import ApplicationResponse +from hrapplications.models import ApplicationComment admin.site.register(Application) admin.site.register(ApplicationComment) diff --git a/hrapplications/apps.py b/hrapplications/apps.py new file mode 100644 index 00000000..5d99de86 --- /dev/null +++ b/hrapplications/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class HRApplicationsConfig(AppConfig): + name = 'hrapplications' diff --git a/hrapplications/forms.py b/hrapplications/forms.py index 91330c4b..70842acb 100755 --- a/hrapplications/forms.py +++ b/hrapplications/forms.py @@ -1,8 +1,11 @@ +from __future__ import unicode_literals from django import forms from django.utils.translation import ugettext_lazy as _ + class HRApplicationCommentForm(forms.Form): comment = forms.CharField(widget=forms.Textarea, required=False, label=_("Comment")) + class HRApplicationSearchForm(forms.Form): search_string = forms.CharField(max_length=254, required=True, label=_("Search String")) diff --git a/hrapplications/migrations/0001_initial.py b/hrapplications/migrations/0001_initial.py new file mode 100644 index 00000000..7733ce58 --- /dev/null +++ b/hrapplications/migrations/0001_initial.py @@ -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')]), + ), + ] diff --git a/hrapplications/migrations/__init__.py b/hrapplications/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hrapplications/models.py b/hrapplications/models.py index e0824bae..85372faa 100755 --- a/hrapplications/models.py +++ b/hrapplications/models.py @@ -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.contrib.auth.models import User @@ -6,6 +8,8 @@ from eveonline.models import EveCorporationInfo from eveonline.models import EveApiKeyPair from authentication.models import AuthServicesInfo + +@python_2_unicode_compatible class ApplicationQuestion(models.Model): title = models.CharField(max_length=254) help_text = models.CharField(max_length=254, blank=True, null=True) @@ -13,6 +17,8 @@ class ApplicationQuestion(models.Model): def __str__(self): return "Question: " + self.title.encode('utf-8') + +@python_2_unicode_compatible class ApplicationForm(models.Model): questions = models.ManyToManyField(ApplicationQuestion) corp = models.OneToOneField(EveCorporationInfo) @@ -20,6 +26,8 @@ class ApplicationForm(models.Model): def __str__(self): return str(self.corp) + +@python_2_unicode_compatible class Application(models.Model): form = models.ForeignKey(ApplicationForm, 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) 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') @property @@ -62,6 +72,7 @@ class Application(models.Model): return None +@python_2_unicode_compatible class ApplicationResponse(models.Model): question = models.ForeignKey(ApplicationQuestion, on_delete=models.CASCADE) application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='responses') @@ -73,6 +84,8 @@ class ApplicationResponse(models.Model): class Meta: unique_together = ('question', 'application') + +@python_2_unicode_compatible class ApplicationComment(models.Model): application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name='comments') user = models.ForeignKey(User, on_delete=models.CASCADE) @@ -82,12 +95,11 @@ class ApplicationComment(models.Model): def __str__(self): return str(self.user) + " comment on " + str(self.application) + ################ # Legacy Models ################ -# Can't delete or evolutions explodes. -# They do nothing. -################ +@python_2_unicode_compatible class HRApplication(models.Model): character_name = 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" +@python_2_unicode_compatible class HRApplicationComment(models.Model): created_on = models.DateTimeField(auto_now_add=True, null=True) comment = models.CharField(max_length=254, default="") diff --git a/hrapplications/views.py b/hrapplications/views.py index 11bbebec..68787bac 100755 --- a/hrapplications/views.py +++ b/hrapplications/views.py @@ -1,30 +1,23 @@ -from django.template import RequestContext -from django.shortcuts import render_to_response, get_object_or_404, redirect +from __future__ import unicode_literals +from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import user_passes_test -from django.shortcuts import HttpResponseRedirect from notifications import notify -from models import HRApplication -from models import HRApplicationComment -from models import ApplicationForm -from models import Application -from models import ApplicationQuestion -from models import ApplicationResponse -from models import ApplicationComment -from forms import HRApplicationCommentForm -from forms import HRApplicationSearchForm -from eveonline.models import EveCorporationInfo +from hrapplications.models import ApplicationForm +from hrapplications.models import Application +from hrapplications.models import ApplicationResponse +from hrapplications.models import ApplicationComment +from hrapplications.forms import HRApplicationCommentForm +from hrapplications.forms import HRApplicationSearchForm from eveonline.models import EveCharacter from authentication.models import AuthServicesInfo -from django.conf import settings -from eveonline.managers import EveManager - import logging logger = logging.getLogger(__name__) + def create_application_test(user): auth, c = AuthServicesInfo.objects.get_or_create(user=user) if auth.main_char_id: @@ -32,6 +25,7 @@ def create_application_test(user): else: return False + @login_required def hr_application_management_view(request): 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: try: main_char = EveCharacter.objects.get(character_id=auth_info.main_char_id) - except: + except EveCharacter.DoesNotExist: pass if request.user.is_superuser: 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) 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]) - 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 = { 'personal_apps': request.user.applications.all(), 'applications': corp_applications, @@ -60,7 +55,8 @@ def hr_application_management_view(request): 'search_form': HRApplicationSearchForm(), '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 @user_passes_test(create_application_test) @@ -75,19 +71,22 @@ def hr_application_create_view(request, form_id=None): application.save() for question in app_form.questions.all(): 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() logger.info("%s created %s" % (request.user, application)) return redirect('auth_hrapplications_view') else: 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: choices = [] for app_form in ApplicationForm.objects.all(): if not Application.objects.filter(user=request.user).filter(form=app_form).exists(): 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 def hr_application_personal_view(request, app_id): @@ -102,18 +101,18 @@ def hr_application_personal_view(request, app_id): 'comment_form': HRApplicationCommentForm(), 'apis': [], } - return render_to_response('registered/hrapplicationview.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/hrapplicationview.html', context=context) else: logger.warn("User %s not authorized to view %s" % (request.user, app)) return redirect('auth_hrapplications_view') - + @login_required 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)) app = get_object_or_404(Application, pk=app_id) if app.user == request.user: - if app.approved == None: + if app.approved is None: logger.info("User %s deleting %s" % (request.user, app)) app.delete() 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)) return redirect('auth_hrapplications_view') + @login_required @permission_required('auth.human_resources') def hr_application_view(request, app_id): @@ -154,7 +154,7 @@ def hr_application_view(request, app_id): 'comments': ApplicationComment.objects.filter(application=app), '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 @@ -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) return redirect('auth_hrapplications_view') + @login_required @permission_required('auth.human_resources') @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)) app.approved = True 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: logger.warn("User %s not authorized to approve %s" % (request.user, app)) return redirect('auth_hrapplications_view') + @login_required @permission_required('auth.human_resources') @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)) app.approved = False 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: logger.warn("User %s not authorized to reject %s" % (request.user, app)) return redirect('auth_hrapplications_view') + @login_required @permission_required('auth.human_resources') def hr_application_search(request): @@ -217,15 +222,16 @@ def hr_application_search(request): try: character = EveCharacter.objects.get(character_id=auth_info.main_char_id) app_list = Application.objects.filter(form__corp__corporation_id=character.corporation_id) - except: - logger.warn("User %s missing main character model: unable to filter applications to search" % request.user) + except EveCharacter.DoesNotExist: + logger.warn( + "User %s missing main character model: unable to filter applications to search" % request.user) for application in app_list: if application.main_character: if searchstring in application.main_character.character_name.lower(): applications.add(application) if searchstring in application.main_character.corporation_name.lower(): applications.add(application) - if searchstring in application.main_character.alliance_name.lower():\ + if searchstring in application.main_character.alliance_name.lower(): applications.add(application) for character in application.characters: if searchstring in character.character_name.lower(): @@ -236,21 +242,21 @@ def hr_application_search(request): applications.add(application) if searchstring in application.user.username.lower(): 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()} - return render_to_response('registered/hrapplicationsearchview.html', - context, context_instance=RequestContext(request)) + return render(request, 'registered/hrapplicationsearchview.html', context=context) else: logger.debug("Form invalid - returning for user %s to retry." % request.user) context = {'applications': None, 'search_form': form} - return render_to_response('registered/hrapplicationsearchview.html', - context, context_instance=RequestContext(request)) + return render(request, 'registered/hrapplicationsearchview.html', context=context) else: logger.debug("Returning empty search form for user %s" % request.user) - return HttpResponseRedirect("/hr_application_management/") + return redirect("auth_hrapplications_view") + @login_required @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) try: 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)) character = None app.reviewer = request.user app.reviewer_character = character 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: - logger.warn("User %s unable to mark %s in progress: already being reviewed by %s" % (request.user, app, app.reviewer)) - return HttpResponseRedirect("/hr_application_view/" + str(app_id)) + logger.warn( + "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) diff --git a/manage.py b/manage.py index 7cb0a0af..b65130b0 100644 --- a/manage.py +++ b/manage.py @@ -1,10 +1,23 @@ #!/usr/bin/env python +from __future__ import unicode_literals import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alliance_auth.settings") - - from django.core.management import execute_from_command_line - + try: + 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) diff --git a/notifications/__init__.py b/notifications/__init__.py index 67bb4cca..be26720d 100644 --- a/notifications/__init__.py +++ b/notifications/__init__.py @@ -1,11 +1,13 @@ -from .models import Notification +from __future__ import unicode_literals import logging logger = logging.getLogger(__name__) MAX_NOTIFICATIONS = 50 + def notify(user, title, message=None, level='info'): + from .models import Notification if Notification.objects.filter(user=user).count() > MAX_NOTIFICATIONS: for n in Notification.objects.filter(user=user)[MAX_NOTIFICATIONS:]: n.delete() diff --git a/notifications/admin.py b/notifications/admin.py index 56893293..c9bd4f21 100644 --- a/notifications/admin.py +++ b/notifications/admin.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from django.contrib import admin from.models import Notification diff --git a/notifications/apps.py b/notifications/apps.py new file mode 100644 index 00000000..6e5c9743 --- /dev/null +++ b/notifications/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class NotificationsConfig(AppConfig): + name = 'notifications' diff --git a/notifications/context_processors.py b/notifications/context_processors.py index 1c9a5385..97d05923 100644 --- a/notifications/context_processors.py +++ b/notifications/context_processors.py @@ -1,4 +1,6 @@ -from .models import Notification +from __future__ import unicode_literals +from notifications.models import Notification + 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))} diff --git a/notifications/handlers.py b/notifications/handlers.py index 720ed07c..6330fc49 100644 --- a/notifications/handlers.py +++ b/notifications/handlers.py @@ -1,11 +1,13 @@ +from __future__ import unicode_literals import logging -from django.contrib.auth.models import User -from .models import Notification logger = logging.getLogger(__name__) + class NotificationHandler(logging.Handler): def emit(self, record): + from django.contrib.auth.models import User + from notifications.models import Notification for user in User.objects.all(): if user.has_perm('auth.logging_notifications'): 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]) message = record.getMessage() if record.exc_text: - message = message + "\n\n" + message += "\n\n" message = message + record.exc_text notif.message = message notif.save() diff --git a/notifications/migrations/0001_initial.py b/notifications/migrations/0001_initial.py new file mode 100644 index 00000000..68fdd90e --- /dev/null +++ b/notifications/migrations/0001_initial.py @@ -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)), + ], + ), + ] diff --git a/notifications/migrations/0002_auto_20160910_1649.py b/notifications/migrations/0002_auto_20160910_1649.py new file mode 100644 index 00000000..f077fec0 --- /dev/null +++ b/notifications/migrations/0002_auto_20160910_1649.py @@ -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']}, + ), + ] diff --git a/notifications/migrations/__init__.py b/notifications/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/notifications/models.py b/notifications/models.py index cf0d688d..a102139f 100644 --- a/notifications/models.py +++ b/notifications/models.py @@ -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.contrib.auth.models import User import logging logger = logging.getLogger(__name__) -class Notification(models.Model): +@python_2_unicode_compatible +class Notification(models.Model): LEVEL_CHOICES = ( ('danger', 'CRITICAL'), ('danger', 'ERROR'), @@ -26,9 +29,11 @@ class Notification(models.Model): self.viewed = True self.save() - def __unicode__(self): - output = "%s: %s" % (self.user, self.title) - return output.encode('utf-8') + def __str__(self): + return "%s: %s" % (self.user, self.title) def set_level(self, level): self.level = [item[0] for item in self.LEVEL_CHOICES if item[1] == level][0] + + class Meta: + ordering = ['-timestamp'] diff --git a/notifications/tests.py b/notifications/tests.py index 7ce503c2..a39b155a 100644 --- a/notifications/tests.py +++ b/notifications/tests.py @@ -1,3 +1 @@ -from django.test import TestCase - # Create your tests here. diff --git a/notifications/views.py b/notifications/views.py index c6252cb7..201d7c9f 100644 --- a/notifications/views.py +++ b/notifications/views.py @@ -1,10 +1,13 @@ +from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404, redirect from .models import Notification from django.contrib.auth.decorators import login_required +from django.contrib import messages import logging logger = logging.getLogger(__name__) + @login_required def notification_list(request): 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) + @login_required def notification_view(request, 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() return render(request, 'registered/notification_view.html', context) 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') + @login_required def remove_notification(request, 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(): notif.delete() logger.info("Deleting notif id %s by user %s" % (notif_id, request.user)) + messages.success(request, 'Deleted notification.') 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') diff --git a/optimer/__init__.py b/optimer/__init__.py index e69de29b..baffc488 100644 --- a/optimer/__init__.py +++ b/optimer/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/optimer/admin.py b/optimer/admin.py index 85271e70..fd962cbe 100644 --- a/optimer/admin.py +++ b/optimer/admin.py @@ -1,6 +1,6 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import optimer +from optimer.models import optimer admin.site.register(optimer) -# Register your models here. diff --git a/optimer/apps.py b/optimer/apps.py new file mode 100644 index 00000000..9b2a9052 --- /dev/null +++ b/optimer/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class OptimerConfig(AppConfig): + name = 'optimer' diff --git a/optimer/form.py b/optimer/form.py index fbf15e13..6e476677 100644 --- a/optimer/form.py +++ b/optimer/form.py @@ -1,11 +1,9 @@ +from __future__ import unicode_literals from django import forms -from django.core.validators import MaxValueValidator, MinValueValidator from django.utils.translation import ugettext_lazy as _ - class opForm(forms.Form): - doctrine = forms.CharField(max_length=254, required=True, label=_('Doctrine')) system = forms.CharField(max_length=254, required=True, label=_("System")) location = forms.CharField(max_length=254, required=True, label=_("Location")) diff --git a/optimer/migrations/0001_initial.py b/optimer/migrations/0001_initial.py new file mode 100644 index 00000000..3b31c2ac --- /dev/null +++ b/optimer/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-05 21:40 +from __future__ import unicode_literals + +import datetime +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('eveonline', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='optimer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('doctrine', models.CharField(default=b'', max_length=254)), + ('system', models.CharField(default=b'', max_length=254)), + ('location', models.CharField(default=b'', max_length=254)), + ('start', models.DateTimeField(default=datetime.datetime.now)), + ('duration', models.CharField(default=b'', max_length=25)), + ('operation_name', models.CharField(default=b'', max_length=254)), + ('fc', models.CharField(default=b'', max_length=254)), + ('details', models.CharField(default=b'', max_length=254)), + ('post_time', models.DateTimeField(default=django.utils.timezone.now)), + ('eve_character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')), + ], + options={ + 'ordering': ['start'], + }, + ), + ] diff --git a/optimer/migrations/__init__.py b/optimer/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/optimer/models.py b/optimer/models.py index 583997cf..32670bf0 100644 --- a/optimer/models.py +++ b/optimer/models.py @@ -1,14 +1,16 @@ +from __future__ import unicode_literals +from django.utils.encoding import python_2_unicode_compatible from django.db import models -from django.contrib.auth.models import User from django.utils import timezone from eveonline.models import EveCharacter -from eveonline.models import EveCorporationInfo from datetime import datetime +@python_2_unicode_compatible class optimer(models.Model): class Meta: ordering = ['start'] + doctrine = models.CharField(max_length=254, default="") system = models.CharField(max_length=254, default="") location = models.CharField(max_length=254, default="") @@ -23,4 +25,3 @@ class optimer(models.Model): def __str__(self): output = self.operation_name return output.encode('utf-8') - diff --git a/optimer/views.py b/optimer/views.py index 6d130fe3..558a9397 100644 --- a/optimer/views.py +++ b/optimer/views.py @@ -1,38 +1,29 @@ - - -from django.http import HttpResponseRedirect -from django.template import RequestContext -from django.shortcuts import render_to_response +from __future__ import unicode_literals from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required -from django.contrib.auth.decorators import user_passes_test from django.utils import timezone from django.shortcuts import get_object_or_404 - -from util import check_if_user_has_permission -from authentication.managers import AuthServicesInfoManager +from django.shortcuts import render, redirect +from django.contrib import messages +from authentication.models import AuthServicesInfo from eveonline.managers import EveManager -from form import opForm -from models import optimer - +from optimer.form import opForm +from optimer.models import optimer +from authentication.decorators import members_and_blues import logging logger = logging.getLogger(__name__) -def optimer_util_test(user): - return check_if_user_has_permission(user, 'member') or check_if_user_has_permission(user, 'blue_member') - @login_required -@user_passes_test(optimer_util_test) +@members_and_blues() @permission_required('auth.optimer_view') def optimer_view(request): logger.debug("optimer_view called by user %s" % request.user) - optimer_list = optimer.objects.all() - render_items = {'optimer': optimer.objects.all(),} + render_items = {'optimer': optimer.objects.all(), } - return render_to_response('registered/operationmanagement.html', render_items, context_instance=RequestContext(request)) + return render(request, 'registered/operationmanagement.html', context=render_items) @login_required @@ -40,13 +31,13 @@ def optimer_view(request): def add_optimer_view(request): logger.debug("add_optimer_view called by user %s" % request.user) if request.method == 'POST': - form = opForm(request.POST) - logger.debug("Request type POST contains form valid: %s" % form.is_valid()) + form = opForm(request.POST) + logger.debug("Request type POST contains form valid: %s" % form.is_valid()) if form.is_valid(): - #Get Current Time + # Get Current Time post_time = timezone.now() # Get character - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) + auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(auth_info.main_char_id) # handle valid form op = optimer() @@ -62,14 +53,15 @@ def add_optimer_view(request): op.eve_character = character op.save() logger.info("User %s created op timer with name %s" % (request.user, op.operation_name)) - return HttpResponseRedirect("/optimer/") + messages.success(request, 'Created operation timer for %s.' % op.operation_name) + return redirect("/optimer/") else: logger.debug("Returning new opForm") form = opForm() render_items = {'form': form} - return render_to_response('registered/addoperation.html', render_items, context_instance=RequestContext(request)) + return render(request, 'registered/addoperation.html', context=render_items) @login_required @@ -80,9 +72,12 @@ def remove_optimer(request, optimer_id): op = optimer.objects.get(id=optimer_id) op.delete() logger.info("Deleting optimer id %s by user %s" % (optimer_id, request.user)) + messages.success(request, 'Removed operation timer for %s.' % op.operation_name) else: - logger.error("Unable to delete optimer id %s for user %s - operation matching id not found." % (optimer_id, request.user)) - return HttpResponseRedirect("/optimer/") + logger.error("Unable to delete optimer id %s for user %s - operation matching id not found." % ( + optimer_id, request.user)) + return redirect("auth_optimer_view") + @login_required @permission_required('auth.optimer_management') @@ -93,7 +88,7 @@ def edit_optimer(request, optimer_id): form = opForm(request.POST) logger.debug("Received POST request containing update optimer form, is valid: %s" % form.is_valid()) if form.is_valid(): - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) + auth_info = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(auth_info.main_char_id) op.doctrine = form.cleaned_data['doctrine'] op.system = form.cleaned_data['system'] @@ -106,9 +101,8 @@ def edit_optimer(request, optimer_id): op.eve_character = character logger.info("User %s updating optimer id %s " % (request.user, optimer_id)) op.save() - - logger.debug("Detected no changes between optimer id %s and supplied form." % optimer_id) - return HttpResponseRedirect("/optimer/") + messages.success(request, 'Saved changes to operation timer for %s.' % op.operation_name) + return redirect("auth_optimer_view") else: data = { 'doctrine': op.doctrine, @@ -120,5 +114,5 @@ def edit_optimer(request, optimer_id): 'fc': op.fc, 'details': op.details, } - form = opForm(initial= data) - return render_to_response('registered/optimerupdate.html', {'form':form}, context_instance=RequestContext(request)) + form = opForm(initial=data) + return render(request, 'registered/optimerupdate.html', context={'form': form}) diff --git a/portal/admin.py b/portal/admin.py deleted file mode 100644 index 846f6b40..00000000 --- a/portal/admin.py +++ /dev/null @@ -1 +0,0 @@ -# Register your models here. diff --git a/portal/models.py b/portal/models.py deleted file mode 100644 index 6b202199..00000000 --- a/portal/models.py +++ /dev/null @@ -1 +0,0 @@ -# Create your models here. diff --git a/portal/tests.py b/portal/tests.py deleted file mode 100644 index a39b155a..00000000 --- a/portal/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/portal/views.py b/portal/views.py deleted file mode 100755 index 32ec7309..00000000 --- a/portal/views.py +++ /dev/null @@ -1,30 +0,0 @@ -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.contrib.auth.decorators import login_required - -from eveonline.managers import EveManager -from authentication.managers import AuthServicesInfoManager - -import logging - -logger = logging.getLogger(__name__) - - -# Create your views here. -def index_view(request): - logger.debug("index_view called by user %s" % request.user) - return render_to_response('public/index.html', None, context_instance=RequestContext(request)) - - -@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': AuthServicesInfoManager.get_auth_service_info(request.user)} - return render_to_response('registered/dashboard.html', render_items, context_instance=RequestContext(request)) - - -@login_required -def help_view(request): - logger.debug("help_view called by user %s" % request.user) - return render_to_response('registered/help.html', None, context_instance=RequestContext(request)) diff --git a/registration/admin.py b/registration/admin.py deleted file mode 100644 index 846f6b40..00000000 --- a/registration/admin.py +++ /dev/null @@ -1 +0,0 @@ -# Register your models here. diff --git a/registration/forms.py b/registration/forms.py deleted file mode 100644 index f0a39931..00000000 --- a/registration/forms.py +++ /dev/null @@ -1,44 +0,0 @@ -from django import forms -from django.contrib.auth.models import User -from django.utils.translation import ugettext_lazy as _ -import re - -import logging - -logger = logging.getLogger(__name__) - -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']: - logger.debug("RegistrationForm username contains spaces. Raising ValidationError. Username: %s" % self.cleaned_data['username']) - raise forms.ValidationError(u'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']) - logger.debug("RegistrationForm email already registered. Raising ValidationError") - raise forms.ValidationError(u'Email as already been used') - except: - pass - - if not re.match("^\w+$", self.cleaned_data['username']): - logger.debug("RegistrationForm username contains non-alphanumeric characters. Raising ValueError. Username: %s" % self.cleaned_data['username']) - raise forms.ValidationError(u'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']: - logger.debug("RegistrationForm password mismatch. Raising ValueError") - raise forms.ValidationError(u'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']: - logger.debug("RegistrationForm email mismatch. Raising ValidationError") - raise forms.ValidationError(u'Emails do not match') - - return self.cleaned_data diff --git a/registration/models.py b/registration/models.py deleted file mode 100644 index 6b202199..00000000 --- a/registration/models.py +++ /dev/null @@ -1 +0,0 @@ -# Create your models here. diff --git a/registration/tests.py b/registration/tests.py deleted file mode 100644 index a39b155a..00000000 --- a/registration/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/registration/views.py b/registration/views.py deleted file mode 100644 index 59e0658a..00000000 --- a/registration/views.py +++ /dev/null @@ -1,40 +0,0 @@ -from django.contrib.auth.models import User -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response -from django.template import RequestContext -from django.utils import translation - -from forms import RegistrationForm - -import logging - -logger = logging.getLogger(__name__) - -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) - - return HttpResponseRedirect("/dashboard/") - - else: - logger.error("Unable to register new user: username %s already exists." % form.cleaned_data['username']) - return render_to_response('public/register.html', {'form': form, 'error': True} - , context_instance=RequestContext(request)) - 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_to_response('public/register.html', {'form': form}, context_instance=RequestContext(request)) diff --git a/requirements.txt b/requirements.txt index 23106c9a..e4223b4c 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,21 +1,25 @@ # Python Stuff # - see bootstrap.sh -mysql-python mysqlclient evelink dnspython passlib requests>=2.9.1 bcrypt -zeroc-ice +#zeroc-ice slugify requests-oauthlib +sleekxmpp # Django Stuff # -django==1.6.5 -django-evolution +django>=1.10,<2.0 django-bootstrap-form -django-celery +django-navhelper + +# awating release for fix to celery/django-celery#447 +# django-celery +git+https://github.com/celery/django-celery git+git://github.com/nikdoof/python-ts3.git -git+git://github.com/seamus-45/openfire-restapi.git -git+https://github.com/ArchipelProject/xmpppy +git+https://github.com/pyghassen/openfire-restapi + +git+https://github.com/adarnof/adarnauth-eve-sso diff --git a/run_alliance_corp_update.py b/run_alliance_corp_update.py index 05b31ecc..938961d9 100644 --- a/run_alliance_corp_update.py +++ b/run_alliance_corp_update.py @@ -1,6 +1,5 @@ -from util import bootstrap_permissions -from celerytask.tasks import run_corp_update +from __future__ import unicode_literals +from eveonline.tasks import run_corp_update -bootstrap_permissions() run_corp_update() quit() diff --git a/services/__init__.py b/services/__init__.py index e69de29b..5f118bbb 100644 --- a/services/__init__.py +++ b/services/__init__.py @@ -0,0 +1,2 @@ +from __future__ import unicode_literals +default_app_config = 'services.apps.ServicesConfig' diff --git a/services/admin.py b/services/admin.py index 1ea2f541..cfb11651 100644 --- a/services/admin.py +++ b/services/admin.py @@ -1,13 +1,15 @@ +from __future__ import unicode_literals from django.contrib import admin -from .models import AuthTS -from .models import DiscordAuthToken -from .models import MumbleUser -from .models import GroupCache +from services.models import AuthTS +from services.models import MumbleUser +from services.models import GroupCache + class AuthTSgroupAdmin(admin.ModelAdmin): - fields = ['auth_group','ts_group'] + fields = ['auth_group', 'ts_group'] filter_horizontal = ('ts_group',) + admin.site.register(AuthTS, AuthTSgroupAdmin) admin.site.register(MumbleUser) diff --git a/services/apps.py b/services/apps.py new file mode 100644 index 00000000..7b4755de --- /dev/null +++ b/services/apps.py @@ -0,0 +1,10 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class ServicesConfig(AppConfig): + name = 'services' + + def ready(self): + import services.signals \ No newline at end of file diff --git a/services/context_processors.py b/services/context_processors.py new file mode 100644 index 00000000..35bfadfc --- /dev/null +++ b/services/context_processors.py @@ -0,0 +1,31 @@ +from __future__ import unicode_literals +from django.conf import settings +from django.utils import timezone + + +def auth_settings(request): + return { + 'DOMAIN': settings.DOMAIN, + 'MUMBLE_URL': settings.MUMBLE_URL, + 'FORUM_URL': settings.FORUM_URL, + 'TEAMSPEAK3_PUBLIC_URL': settings.TEAMSPEAK3_PUBLIC_URL, + 'JACK_KNIFE_URL': settings.JACK_KNIFE_URL, + 'DISCORD_SERVER_ID': settings.DISCORD_GUILD_ID, + 'KILLBOARD_URL': settings.KILLBOARD_URL, + 'DISCOURSE_URL': settings.DISCOURSE_URL, + 'IPS4_URL': settings.IPS4_URL, + 'SMF_URL': settings.SMF_URL, + 'MARKET_URL': settings.MARKET_URL, + 'EXTERNAL_MEDIA_URL': settings.EXTERNAL_MEDIA_URL, + 'CURRENT_UTC_TIME': timezone.now(), + 'BLUE_API_MASK': settings.BLUE_API_MASK, + 'BLUE_API_ACCOUNT': settings.BLUE_API_ACCOUNT, + 'MEMBER_API_MASK': settings.MEMBER_API_MASK, + 'MEMBER_API_ACCOUNT': settings.MEMBER_API_ACCOUNT, + 'JABBER_URL': settings.JABBER_URL, + 'ALLIANCE_NAME': settings.ALLIANCE_NAME, + 'ALLIANCE_ID': settings.ALLIANCE_ID, + 'CORP_NAME': settings.CORP_NAME, + 'CORP_ID': settings.CORP_ID, + 'IS_CORP': settings.IS_CORP, + } \ No newline at end of file diff --git a/services/forms.py b/services/forms.py index 19501a29..4d97c738 100644 --- a/services/forms.py +++ b/services/forms.py @@ -1,7 +1,9 @@ +from __future__ import unicode_literals from django import forms from services.managers.teamspeak3_manager import Teamspeak3Manager from django.utils.translation import ugettext_lazy as _ + class JabberBroadcastForm(forms.Form): group = forms.ChoiceField(label=_('Group'), widget=forms.Select) message = forms.CharField(label=_('Message'), widget=forms.Textarea) @@ -17,23 +19,29 @@ class FleetFormatterForm(forms.Form): formup_time = forms.CharField(label=_('Formup Time:'), required=True) expected_duration = forms.CharField(label=_('Expected Duration:'), required=True) purpose = forms.CharField(label=_('Purpose:'), required=True) - reimbursable = forms.ChoiceField(label=_('Reimbursable?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], required=True) - important = forms.ChoiceField(label=_('Important?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], required=True) + reimbursable = forms.ChoiceField(label=_('Reimbursable?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], + required=True) + important = forms.ChoiceField(label=_('Important?*'), choices=[(_('Yes'), _('Yes')), (_('No'), _('No'))], + required=True) comments = forms.CharField(label=_('Comments'), widget=forms.Textarea, required=False) + class DiscordForm(forms.Form): email = forms.CharField(label=_("Email Address"), required=True) password = forms.CharField(label=_("Password"), required=True, widget=forms.PasswordInput) update_avatar = forms.BooleanField(label=_("Update Avatar"), required=False, initial=True) + class ServicePasswordForm(forms.Form): password = forms.CharField(label=_("Password"), required=True) + def clean_password(self): password = self.cleaned_data['password'] if not len(password) >= 8: raise forms.ValidationError(_("Password must be at least 8 characters long.")) return password + class TeamspeakJoinForm(forms.Form): username = forms.CharField(widget=forms.HiddenInput()) diff --git a/services/managers/__init__.py b/services/managers/__init__.py index e69de29b..baffc488 100644 --- a/services/managers/__init__.py +++ b/services/managers/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/services/managers/discord_manager.py b/services/managers/discord_manager.py index 5bc66e1c..4e5ee2cd 100644 --- a/services/managers/discord_manager.py +++ b/services/managers/discord_manager.py @@ -1,11 +1,9 @@ +from __future__ import unicode_literals import requests import json -from django.conf import settings import re -import os -import urllib -import base64 -from services.models import DiscordAuthToken, GroupCache +from django.conf import settings +from services.models import GroupCache from requests_oauthlib import OAuth2Session import logging import datetime @@ -16,442 +14,10 @@ logger = logging.getLogger(__name__) DISCORD_URL = "https://discordapp.com/api" EVE_IMAGE_SERVER = "https://image.eveonline.com" -class DiscordAPIManager: - - def __init__(self, server_id, email, password, user=None): - self.token = DiscordAPIManager.get_token_by_user(email, password, user) - self.email = email - self.password = password - self.server_id = server_id - logger.debug("Initialized DiscordAPIManager with server id %s" % self.server_id) - - @staticmethod - def validate_token(token): - custom_headers = {'accept': 'application/json', 'authorization': token} - path = DISCORD_URL + "/users/@me" - r = requests.get(path, headers=custom_headers) - if r.status_code == 200: - logger.debug("Token starting with %s passed validation." % token[0:5]) - return True - else: - logger.debug("Token starting with %s failed validation with status code %s" % (token[0:5], r.status_code)) - return False - - @staticmethod - def get_auth_token(): - data = { - "email" : settings.DISCORD_USER_EMAIL, - "password": settings.DISCORD_USER_PASSWORD, - } - custom_headers = {'content-type':'application/json'} - path = DISCORD_URL + "/auth/login" - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - logger.debug("Received status code %s during token generation for settings discord user." % r.status_code) - r.raise_for_status() - return r.json()['token'] - - def add_server(self, name): - data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds" - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - def rename_server(self, name): - data = {"name": name} - custom_headers = {'content-type':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - def delete_server(self): - custom_headers = {'content-type':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - def get_members(self): - custom_headers = {'accept':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members" - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - def get_bans(self): - custom_headers = {'accept':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans" - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - def ban_user(self, user_id, delete_message_age=0): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans/" + str(user_id) + "?delete-message-days=" + str(delete_message_age) - r = requests.put(path, headers=custom_headers) - logger.debug("Received status code %s after banning user %s" % (r.status_code, user_id)) - r.raise_for_status() - - def unban_user(self, user_id): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/bans/" + str(user_id) - r = requests.delete(path, headers=custom_headers) - logger.debug("Received status code %s after deleting ban for user %s" % (r.status_code, user_id)) - r.raise_for_status() - - def generate_role(self): - custom_headers = {'accept':'application/json', 'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles" - r = requests.post(path, headers=custom_headers) - logger.debug("Received status code %s after generating new role." % r.status_code) - r.raise_for_status() - return r.json() - - def edit_role(self, role_id, name, color=0, hoist=True, permissions=36785152): - custom_headers = {'content-type':'application/json', 'authorization': self.token} - data = { - 'color': color, - 'hoist': hoist, - 'name': name, - 'permissions': permissions, - } - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles/" + str(role_id) - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - logger.debug("Received status code %s after editing role id %s" % (r.status_code, role_id)) - r.raise_for_status() - return r.json() - - def delete_role(self, role_id): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles/" + str(role_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - @staticmethod - def get_invite(invite_id): - custom_headers = {'accept': 'application/json'} - path = DISCORD_URL + "/invite/" + str(invite_id) - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - def accept_invite(self, invite_id): - custom_headers = {'accept': 'application/json', 'authorization': self.token} - path = DISCORD_URL + "/invite/" + str(invite_id) - r = requests.post(path, headers=custom_headers) - logger.debug("Received status code %s after accepting invite." % r.status_code) - r.raise_for_status() - return r.json() - - def create_invite(self, max_age=600, max_uses=1, temporary=True, xkcdpass=False): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/channels/" + str(self.server_id) + "/invites" - data = { - 'max_age': max_age, - 'max_uses': max_uses, - 'temporary': temporary, - 'xkcdpass': xkcdpass, - } - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - logger.debug("Received status code %s after creating invite." % r.status_code) - r.raise_for_status() - return r.json() - - def delete_invite(self, invite_id): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/invite/" + str(invite_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - def set_roles(self, user_id, role_ids): - custom_headers = {'authorization': self.token, 'content-type':'application/json'} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members/" + str(user_id) - data = { 'roles': role_ids } - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - logger.debug("Received status code %s after setting roles of user %s to %s" % (r.status_code, user_id, role_ids)) - r.raise_for_status() - - @staticmethod - def register_user(server_id, username, invite_code, password, email): - custom_headers = {'content-type': 'application/json'} - data = { - 'fingerprint': None, - 'username': username, - 'invite': invite_code, - 'password': password, - 'email': email, - } - path = DISCORD_URL + "/auth/register" - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - - def kick_user(self, user_id): - custom_headers = {'authorization': self.token} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members/" + str(user_id) - r = requests.delete(path, headers=custom_headers) - r.raise_for_status() - - def get_members(self): - custom_headers = {'authorization': self.token, 'accept':'application/json'} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/members" - r = requests.get(path, headers=custom_headers) - r.raise_for_status() - return r.json() - - def get_user_id(self, username): - all_members = self.get_members() - for member in all_members: - if member['user']['username'] == username: - return member['user']['id'] - raise KeyError('User not found on server: ' + username) - - def get_roles(self): - custom_headers = {'authorization': self.token, 'accept':'application/json'} - path = DISCORD_URL + "/guilds/" + str(self.server_id) + "/roles" - r = requests.get(path, headers=custom_headers) - logger.debug("Received status code %s after retrieving role list from server." % r.status_code) - r.raise_for_status() - return r.json() - - def get_group_id(self, group_name): - logger.debug("Determining role id for group name %s" % group_name) - all_roles = self.get_roles() - logger.debug("Retrieved role list for server: %s" % all_roles) - for role in all_roles: - logger.debug("Checking role %s" % role) - if role['name'] == group_name: - logger.debug("Found role matching name: %s" % role['id']) - return role['id'] - logger.debug("Role not found on server. Raising KeyError") - raise KeyError('Group not found on server: ' + group_name) - - @staticmethod - def get_token_by_user(email, password, user): - if DiscordAuthToken.objects.filter(email=email).exists(): - auth = DiscordAuthToken.objects.get(email=email) - if not auth.user == user: - raise ValueError("User mismatch while validating DiscordAuthToken for email %s - user %s, requesting user %s" % (email, auth.user, user)) - logger.debug("Discord auth token cached for supplied email starting with %s" % email[0:3]) - auth = DiscordAuthToken.objects.get(email=email, user=user) - if DiscordAPIManager.validate_token(auth.token): - logger.debug("Token still valid. Returning token starting with %s" % auth.token[0:5]) - return auth.token - else: - logger.debug("Token has expired. Deleting.") - auth.delete() - logger.debug("Generating auth token for email starting with %s user %s and password of length %s" % (email[0:3], user, len(password))) - data = { - "email" : email, - "password": password, - } - custom_headers = {'content-type':'application/json'} - path = DISCORD_URL + "/auth/login" - r = requests.post(path, headers=custom_headers, data=json.dumps(data)) - logger.debug("Received status code %s after generating auth token for custom user." % r.status_code) - r.raise_for_status() - token = r.json()['token'] - auth = DiscordAuthToken(email=email, token=token, user=user) - auth.save() - logger.debug("Created cached token for email starting with %s" % email[0:3]) - return token - - def get_profile(self): - custom_headers = {'accept': 'application/json', 'authorization': self.token} - path = DISCORD_URL + "/users/@me" - r = requests.get(path, headers=custom_headers) - logger.debug("Received status code %s after retrieving user profile with email %s" % (r.status_code, self.email[0:3])) - r.raise_for_status() - return r.json() - - @staticmethod - def get_user_profile(email, password, user): - token = DiscordAPIManager.get_token_by_user(email, password, user) - custom_headers = {'accept': 'application/json', 'authorization': token} - path = DISCORD_URL + "/users/@me" - r = requests.get(path, headers=custom_headers) - logger.debug("Received status code %s after retrieving user profile with email %s" % (r.status_code, email[0:3])) - r.raise_for_status() - return r.json() - - @staticmethod - def set_user_password(email, current_password, new_password, user): - profile = DiscordAPIManager.get_user_profile(email, current_password, user) - avatar = profile['avatar'] - username = profile['username'] - data = { - 'avatar': avatar, - 'username': username, - 'password': current_password, - 'new_password': new_password, - 'email': email, - } - path = DISCORD_URL + "/users/@me" - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password)} - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - @staticmethod - def set_user_avatar(email, current_password, user, avatar_url): - profile = DiscordAPIManager.get_user_profile(email, current_password, user) - avatar = "data:image/jpeg;base64," + base64.b64encode(urllib.urlopen(avatar_url).read()) - username = profile['username'] - data = { - 'avatar': avatar, - 'username': username, - 'password': current_password, - 'email': email - } - path = DISCORD_URL + "/users/@me" - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password, user)} - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status() - return r.json() - - @staticmethod - def destroy_user(email, current_password): - data = { - 'avatar': None, - 'username': os.urandom(8).encode('hex'), - 'password': current_password, - 'email': os.urandom(8).encode('hex') + '@test.com', - } - path = DISCORD_URL + "/users/@me" - custom_headers = {'content-type':'application/json', 'authorization': DiscordAPIManager.get_token_by_user(email, current_password)} - r = requests.patch(path, headers=custom_headers, data=json.dumps(data)) - r.raise_for_status - return r.json() - - def check_if_user_banned(self, user_id): - bans = self.get_bans() - for b in bans: - if b['user']['id'] == str(user_id): - return True - return False - -class DiscordManager: - def __init__(self): - pass - - @staticmethod - def __sanatize_username(username): - clean = re.sub(r'[^\w]','_', username) - return clean - - @staticmethod - def __generate_random_pass(): - return os.urandom(8).encode('hex') - - @staticmethod - def update_groups(user_id, groups): - logger.debug("Updating groups for user_id %s: %s" % (user_id, groups)) - group_ids = [] - api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - if len(groups) == 0: - logger.debug("No groups provided - generating empty array of group ids.") - group_ids = [] - else: - for g in groups: - try: - logger.debug("Retrieving group id for group %s" % g) - group_id = api.get_group_id(g) - group_ids.append(group_id) - logger.debug("Got id %s" % group_id) - except: - logger.debug("Group id retrieval generated exception - generating new group on discord server.", exc_info=True) - group_ids.append(DiscordManager.create_group(g)) - logger.info("Setting discord groups for user %s to %s" % (user_id, group_ids)) - api.set_roles(user_id, group_ids) - - @staticmethod - def create_group(groupname): - logger.debug("Creating new group %s" % groupname) - api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - new_group = api.generate_role() - logger.debug("Created new role on server with id %s: %s" % (new_group['id'], new_group)) - named_group = api.edit_role(new_group['id'], groupname) - logger.debug("Renamed group id %s to %s" % (new_group['id'], groupname)) - logger.info("Created new group on discord server with name %s" % groupname) - return named_group['id'] - - @staticmethod - def lock_user(user_id): - try: - api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - api.ban_user(user_id) - return True - except: - return False - - @staticmethod - def unlock_user(user_id): - try: - api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - api.unban_user(user_id) - return True - except: - return False - - @staticmethod - def update_user_password(email, current_password, user): - new_password = DiscordManager.__generate_random_pass() - try: - profile = DiscordAPIManager.set_user_password(email, current_password, new_password, user) - return new_password - except: - return current_password - - @staticmethod - def update_user_avatar(email, password, user, char_id): - try: - char_url = EVE_IMAGE_SERVER + "/character/" + str(char_id) + "_256.jpg" - logger.debug("Character image URL for %s: %s" % (user, char_url)) - DiscordAPIManager.set_user_avatar(email, password, user, char_url) - return True - except: - return False - - @staticmethod - def add_user(email, password, user): - try: - logger.debug("Adding new user %s to discord with email %s and password of length %s" % (user, email[0:3], len(password))) - server_api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - user_api = DiscordAPIManager(settings.DISCORD_SERVER_ID, email, password, user=user) - profile = user_api.get_profile() - logger.debug("Got profile for user: %s" % profile) - user_id = profile['id'] - logger.debug("Determined user id: %s" % user_id) - - if server_api.check_if_user_banned(user_id): - logger.debug("User is currently banned. Unbanning %s" % user_id) - server_api.unban_user(user_id) - invite_code = server_api.create_invite()['code'] - logger.debug("Generated invite code beginning with %s" % invite_code[0:5]) - user_api.accept_invite(invite_code) - logger.info("Added user to discord server %s with id %s" % (settings.DISCORD_SERVER_ID, user_id)) - return user_id - except: - logger.exception("An unhandled exception has occured.") - return "" - - @staticmethod - def delete_user(user_id): - try: - logger.debug("Deleting user with id %s from discord server." % user_id) - api = DiscordAPIManager(settings.DISCORD_SERVER_ID, settings.DISCORD_USER_EMAIL, settings.DISCORD_USER_PASSWORD) - DiscordManager.update_groups(user_id, []) - api.ban_user(user_id) - logger.info("Deleted user with id %s from discord server id %s" % (user_id, settings.DISCORD_SERVER_ID)) - return True - except: - logger.exception("An unhandled exception has occured.") - return False - AUTH_URL = "https://discordapp.com/api/oauth2/authorize" TOKEN_URL = "https://discordapp.com/api/oauth2/token" -# kick, manage roles +# kick, manage roles, manage nicknames BOT_PERMISSIONS = 0x00000002 + 0x10000000 + 0x08000000 # get user ID, accept invite @@ -462,7 +28,16 @@ SCOPES = [ GROUP_CACHE_MAX_AGE = datetime.timedelta(minutes=30) + class DiscordOAuthManager: + def __init__(self): + pass + + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w.-]', '', name) + @staticmethod def generate_bot_add_url(): return AUTH_URL + '?client_id=' + settings.DISCORD_APP_ID + '&scope=bot&permissions=' + str(BOT_PERMISSIONS) @@ -506,11 +81,12 @@ class DiscordOAuthManager: @staticmethod def update_nickname(user_id, nickname): try: - custom_headers = {'content-type':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} - data = { 'nick': nickname, } + custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} + data = {'nick': nickname, } path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/members/" + str(user_id) r = requests.patch(path, headers=custom_headers, json=data) - logger.debug("Got status code %s after setting nickname for Discord user ID %s (%s)" % (r.status_code, user_id, nickname)) + logger.debug("Got status code %s after setting nickname for Discord user ID %s (%s)" % ( + r.status_code, user_id, nickname)) if r.status_code == 404: logger.warn("Discord user ID %s could not be found in server." % user_id) return True @@ -584,7 +160,7 @@ class DiscordOAuthManager: @staticmethod def __generate_role(): - custom_headers = {'accept':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} + custom_headers = {'accept': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles" r = requests.post(path, headers=custom_headers) logger.debug("Received status code %s after generating new role." % r.status_code) @@ -593,11 +169,11 @@ class DiscordOAuthManager: @staticmethod def __edit_role(role_id, name, color=0, hoist=True, permissions=36785152): - custom_headers = {'content-type':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} + custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} data = { 'color': color, 'hoist': hoist, - 'name': name, + 'name': name, 'permissions': permissions, } path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/roles/" + str(role_id) @@ -609,13 +185,13 @@ class DiscordOAuthManager: @staticmethod def __create_group(name): role = DiscordOAuthManager.__generate_role() - new_role = DiscordOAuthManager.__edit_role(role['id'], name) + DiscordOAuthManager.__edit_role(role['id'], name) DiscordOAuthManager.__update_group_cache() @staticmethod def update_groups(user_id, groups): - custom_headers = {'content-type':'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} - group_ids = [DiscordOAuthManager.__group_name_to_id(g) for g in groups] + custom_headers = {'content-type': 'application/json', 'authorization': 'Bot ' + settings.DISCORD_BOT_TOKEN} + group_ids = [DiscordOAuthManager.__group_name_to_id(DiscordOAuthManager._sanitize_groupname(g)) for g in groups] path = DISCORD_URL + "/guilds/" + str(settings.DISCORD_GUILD_ID) + "/members/" + str(user_id) data = {'roles': group_ids} r = requests.patch(path, headers=custom_headers, json=data) diff --git a/services/managers/discourse_manager.py b/services/managers/discourse_manager.py index 047963fa..779a315f 100644 --- a/services/managers/discourse_manager.py +++ b/services/managers/discourse_manager.py @@ -1,8 +1,10 @@ +from __future__ import unicode_literals import logging import requests import os import datetime import json +import re from django.conf import settings from django.utils import timezone from services.models import GroupCache @@ -113,7 +115,11 @@ ENDPOINTS = { }, } + class DiscourseManager: + def __init__(self): + pass + GROUP_CACHE_MAX_AGE = datetime.timedelta(minutes=30) REVOKED_EMAIL = 'revoked@' + settings.DOMAIN SUSPEND_DAYS = 99999 @@ -136,7 +142,7 @@ class DiscourseManager: if arg in kwargs: data[arg] = kwargs[arg] for arg in kwargs: - if not arg in endpoint['args']['required'] and not arg in endpoint['args']['optional']: + if arg not in endpoint['args']['required'] and arg not in endpoint['args']['optional']: logger.warn("Received unrecognized kwarg %s for endpoint %s" % (arg, endpoint)) r = endpoint['method'](settings.DISCOURSE_URL + path, params=params, json=data) out = r.text @@ -218,10 +224,10 @@ class DiscourseManager: @staticmethod def __generate_group_dict(names): - dict = {} + group_dict = {} for name in names: - dict[name] = DiscourseManager.__group_name_to_id(name) - return dict + group_dict[name] = DiscourseManager.__group_name_to_id(name) + return group_dict @staticmethod def __get_user_groups(username): @@ -271,7 +277,8 @@ class DiscourseManager: def __suspend_user(username): id = DiscourseManager.__user_name_to_id(username) endpoint = ENDPOINTS['users']['suspend'] - return DiscourseManager.__exc(endpoint, id, duration=DiscourseManager.SUSPEND_DAYS, reason=DiscourseManager.SUSPEND_REASON) + return DiscourseManager.__exc(endpoint, id, duration=DiscourseManager.SUSPEND_DAYS, + reason=DiscourseManager.SUSPEND_REASON) @staticmethod def __unsuspend(username): @@ -287,9 +294,15 @@ class DiscourseManager: @staticmethod def _sanatize_username(username): sanatized = username.replace(" ", "_") + sanatized = sanatized.strip(' _') sanatized = sanatized.replace("'", "") return sanatized + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w]', '', name) + @staticmethod def add_user(username, email): logger.debug("Adding new discourse user %s" % username) @@ -306,7 +319,7 @@ class DiscourseManager: return safe_username, password except: logger.exception("Failed to add new discourse user %s" % username) - return "","" + return "", "" @staticmethod def delete_user(username): @@ -323,15 +336,16 @@ class DiscourseManager: def update_groups(username, raw_groups): groups = [] for g in raw_groups: - groups.append(g[:20]) + groups.append(DiscourseManager._sanitize_groupname(g[:20])) logger.debug("Updating discourse user %s groups to %s" % (username, groups)) group_dict = DiscourseManager.__generate_group_dict(groups) - inv_group_dict = {v:k for k,v in group_dict.items()} + inv_group_dict = {v: k for k, v in group_dict.items()} user_groups = DiscourseManager.__get_user_groups(username) add_groups = [group_dict[x] for x in group_dict if not group_dict[x] in user_groups] rem_groups = [x for x in user_groups if not inv_group_dict[x] in groups] if add_groups or rem_groups: - logger.info("Updating discourse user %s groups: adding %s, removing %s" % (username, add_groups, rem_groups)) + logger.info( + "Updating discourse user %s groups: adding %s, removing %s" % (username, add_groups, rem_groups)) for g in add_groups: DiscourseManager.__add_user_to_group(g, username) for g in rem_groups: diff --git a/services/managers/eve_api_manager.py b/services/managers/eve_api_manager.py index 171b934c..7f86021f 100644 --- a/services/managers/eve_api_manager.py +++ b/services/managers/eve_api_manager.py @@ -1,20 +1,48 @@ +from __future__ import unicode_literals import evelink.api import evelink.char import evelink.eve - +from authentication.states import MEMBER_STATE, BLUE_STATE +from authentication.models import AuthServicesInfo +from eveonline.models import EveCharacter from django.conf import settings import logging logger = logging.getLogger(__name__) -class EveApiManager(): + +class EveApiManager: def __init__(self): pass + class ApiValidationError(Exception): + def __init__(self, msg, api_id): + self.msg = msg + self.api_id = api_id + + def __str__(self): + return self.msg + + class ApiMaskValidationError(ApiValidationError): + def __init__(self, required_mask, api_mask, api_id): + msg = 'Insufficient API mask provided. Required: %s Got: %s' % (required_mask, api_mask) + self.required_mask = required_mask + self.api_mask = api_mask + super(EveApiManager.ApiMaskValidationError, self).__init__(msg, api_id) + + class ApiAccountValidationError(ApiValidationError): + def __init__(self, api_id): + msg = 'Insufficient API access provided. Full account access is required, got character restricted.' + super(EveApiManager.ApiAccountValidationError, self).__init__(msg, api_id) + + class ApiInvalidError(ApiValidationError): + def __init__(self, api_id): + msg = 'Key is invalid.' + super(EveApiManager.ApiInvalidError, self).__init__(msg, api_id) + @staticmethod def get_characters_from_api(api_id, api_key): - chars = [] logger.debug("Getting characters from api id %s" % api_id) api = evelink.api.API(api_key=(api_id, api_key)) # Should get characters @@ -26,7 +54,6 @@ class EveApiManager(): @staticmethod def get_corporation_ticker_from_id(corp_id): logger.debug("Getting ticker for corp id %s" % corp_id) - ticker = "" api = evelink.api.API() corp = evelink.corp.Corp(api) response = corp.corporation_sheet(corp_id) @@ -37,7 +64,6 @@ class EveApiManager(): @staticmethod def get_alliance_information(alliance_id): - results = {} logger.debug("Getting info for alliance with id %s" % alliance_id) api = evelink.api.API() eve = evelink.eve.EVE(api=api) @@ -49,7 +75,6 @@ class EveApiManager(): @staticmethod def get_corporation_information(corp_id): logger.debug("Getting info for corp with id %s" % corp_id) - results = {} api = evelink.api.API() corp = evelink.corp.Corp(api=api) corpinfo = corp.corporation_sheet(corp_id=int(corp_id)) @@ -57,6 +82,12 @@ class EveApiManager(): logger.debug("Got corp info %s" % results) return results + @staticmethod + def get_api_info(api_id, api_key): + api = evelink.api.API(api_key=(api_id, api_key)) + account = evelink.account.Account(api=api) + return account.key_info()[0] + @staticmethod def check_api_is_type_account(api_id, api_key): logger.debug("Checking if api id %s is account." % api_id) @@ -83,7 +114,7 @@ class EveApiManager(): info = account.key_info() logger.debug("API has mask %s, required is %s" % (info[0]['access_mask'], settings.BLUE_API_MASK)) return info[0]['access_mask'] & int(settings.BLUE_API_MASK) == int(settings.BLUE_API_MASK) - + @staticmethod def get_api_info(api_id, api_key): logger.debug("Getting api info for key id %s" % api_id) @@ -98,7 +129,7 @@ class EveApiManager(): logger.debug("Checking if api id %s is valid." % api_id) api = evelink.api.API(api_key=(api_id, api_key)) account = evelink.account.Account(api=api) - info = account.key_info() + account.key_info() logger.info("Verified api id %s is still valid." % api_id) return True @@ -108,10 +139,10 @@ class EveApiManager(): try: api = evelink.api.API() server = evelink.server.Server(api=api) - info = server.server_status() + server.server_status() logger.info("Verified API server is online and reachable.") return True - except evelink.api.APIError as error: + except evelink.api.APIError: logger.exception("APIError occured while trying to query api server. Possibly offline?") logger.warn("Unable to reach API server.") @@ -124,7 +155,7 @@ class EveApiManager(): api = evelink.api.API() corp = evelink.corp.Corp(api=api) corpinfo = corp.corporation_sheet(corp_id=int(corp_id)) - results = corpinfo[0] + assert corpinfo[0] logger.debug("Confirmed id %s is a corp." % corp_id) return True except evelink.api.APIError as error: @@ -160,11 +191,10 @@ class EveApiManager(): results = membertracking.result logger.debug("Got corp membertracking from settings: %s" % results) return results - except evelink.api.APIError as error: + except evelink.api.APIError: logger.exception("Unhandled APIError occured.") return {} - @staticmethod def check_if_id_is_alliance(alliance_id): logger.debug("Checking if id %s is an alliance." % alliance_id) @@ -176,8 +206,9 @@ class EveApiManager(): if results: logger.debug("Confirmed id %s is an alliance." % alliance_id) return True - except evelink.api.APIError as error: - logger.exception("APIError occured while checking if id %s is an alliance. Possibly not alliance?" % alliance_id) + except evelink.api.APIError: + logger.exception( + "APIError occured while checking if id %s is an alliance. Possibly not alliance?" % alliance_id) except KeyError: logger.debug("Alliance with id %s not found in active alliance list." % alliance_id) return False @@ -194,8 +225,10 @@ class EveApiManager(): if results: logger.debug("Confirmed id %s is a character." % character_id) return True - except evelink.api.APIError as error: - logger.debug("APIError occured while checking if id %s is a character. Possibly not character?" % character_id, exc_info=True) + except evelink.api.APIError: + logger.debug( + "APIError occured while checking if id %s is a character. Possibly not character?" % character_id, + exc_info=True) logger.debug("Unable to verify id %s is a character." % character_id) return False @@ -213,15 +246,16 @@ class EveApiManager(): else: logger.debug("Verified alliance id %s does not exist." % alliance_id) return False - except evelink.api.APIError as error: + except evelink.api.APIError: logger.exception("Unhandled APIError occured.") return False - except ValueError as error: - #attempts to catch error resulting from checking alliance_of nonetype models + except ValueError: + # attempts to catch error resulting from checking alliance_of nonetype models logger.exception("Unhandled ValueError occured. Possible nonetype alliance model.") return False - logger.warn("Exception prevented verification of alliance id %s existance. Assuming false." % alliance_id) - return False + except: + logger.warn("Exception prevented verification of alliance id %s existance. Assuming false." % alliance_id) + return False @staticmethod def check_if_corp_exists(corp_id): @@ -231,17 +265,20 @@ class EveApiManager(): corp = evelink.corp.Corp(api=api) corpinfo = corp.corporation_sheet(corp_id=corp_id) if corpinfo[0]['members']['current'] > 0: - logger.debug("Verified corp id %s exists with member count %s" % (corp_id, corpinfo[0]['members']['current'])) + logger.debug( + "Verified corp id %s exists with member count %s" % (corp_id, corpinfo[0]['members']['current'])) return True else: - logger.debug("Verified corp id %s has closed. Member count %s" % (corp_id, corpinfo[0]['members']['current'])) + logger.debug( + "Verified corp id %s has closed. Member count %s" % (corp_id, corpinfo[0]['members']['current'])) return False - except evelink.api.APIError as error: - #could be smart and check for error code523 to verify error due to no corp instead of catch-all + except evelink.api.APIError: + # could be smart and check for error code523 to verify error due to no corp instead of catch-all logger.exception("Unhandled APIError occured.") return False - logger.warn("Exception prevented verification of corp id %s existance. Assuming false." % corp_id) - return False + except: + logger.warn("Exception prevented verification of corp id %s existance. Assuming false." % corp_id) + return False @staticmethod def validate_member_api(api_id, api_key): @@ -249,7 +286,7 @@ class EveApiManager(): if EveApiManager.check_api_is_type_account(api_id, api_key) is False: logger.info("Api id %s is not type account as required for members - failed validation." % api_id) return False - + if EveApiManager.check_api_is_full(api_id, api_key) is False: logger.info("Api id %s does not meet member access mask requirements - failed validation." % api_id) return False @@ -265,3 +302,40 @@ class EveApiManager(): logger.info("Api id %s does not meet minimum blue access mask requirements - failed validation." % api_id) return False return True + + @staticmethod + def validate_api(api_id, api_key, user): + try: + info = EveApiManager.get_api_info(api_id, api_key).result + chars = EveApiManager.get_characters_from_api(api_id, api_key).result + except evelink.api.APIError as e: + if int(e.code) in [221, 222]: + raise e + raise EveApiManager.ApiInvalidError(api_id) + except Exception: + raise EveApiManager.ApiInvalidError(api_id) + auth, c = AuthServicesInfo.objects.get_or_create(user=user) + states = [auth.state] + from authentication.tasks import determine_membership_by_character # circular import issue + 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'] + states.append(determine_membership_by_character(evechar)) + if MEMBER_STATE not in states and BLUE_STATE not in states: + # default to requiring member keys for applications + states.append(MEMBER_STATE) + logger.debug('Checking API %s for states %s' % (api_id, states)) + for state in states: + if (state == MEMBER_STATE and settings.MEMBER_API_ACCOUNT) or ( + state == BLUE_STATE and settings.BLUE_API_ACCOUNT): + if info['type'] != 'account': + raise EveApiManager.ApiAccountValidationError(api_id) + if state == MEMBER_STATE: + if int(info['access_mask']) & int(settings.MEMBER_API_MASK) != int(settings.MEMBER_API_MASK): + raise EveApiManager.ApiMaskValidationError(settings.MEMBER_API_MASK, info['access_mask'], api_id) + elif state == BLUE_STATE: + if int(info['access_mask']) & int(settings.BLUE_API_MASK) != int(settings.BLUE_API_MASK): + raise EveApiManager.ApiMaskValidationError(settings.BLUE_API_MASK, info['access_mask'], api_id) + return True diff --git a/services/managers/evewho_manager.py b/services/managers/evewho_manager.py index 257b47d8..ee7407e2 100644 --- a/services/managers/evewho_manager.py +++ b/services/managers/evewho_manager.py @@ -1,13 +1,9 @@ -from django.conf import settings - -import logging +from __future__ import unicode_literals import requests -#import requests_cache import json -#requests_cache.install_cache("{}/evewho".format(settings.EVEWHO_CACHE_DIR), backend="sqlite", expire_after=3600) -class EveWhoManager(): +class EveWhoManager: def __init__(self): pass @@ -18,11 +14,11 @@ class EveWhoManager(): data = json.loads(jsondata.decode()) members = {} - page_count=0 + page_count = 0 while len(data["characters"]): for row in data["characters"]: - members[int(row["character_id"])] = {"name":row["name"], "id":int(row["character_id"])} - page_count=page_count+1 + members[int(row["character_id"])] = {"name": row["name"], "id": int(row["character_id"])} + page_count += 1 jsondata = requests.get(url + "&page=%i" % page_count).content data = json.loads(jsondata.decode()) diff --git a/services/managers/fleetup_manager.py b/services/managers/fleetup_manager.py index 9209c916..be6f5cb0 100644 --- a/services/managers/fleetup_manager.py +++ b/services/managers/fleetup_manager.py @@ -1,5 +1,5 @@ +from __future__ import unicode_literals from django.conf import settings -from django.http import HttpResponse from datetime import datetime import logging @@ -13,43 +13,45 @@ userid = settings.FLEETUP_USER_ID apiid = settings.FLEETUP_API_ID groupid = settings.FLEETUP_GROUP_ID -class FleetUpManager(): + +class FleetUpManager: def __init__(self): pass @staticmethod def get_fleetup_members(): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/GroupCharacters/" + str(groupid) + "" + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/GroupCharacters/" + str(groupid) + "" try: jsondata = requests.get(url).content - fmembers=json.loads(jsondata.decode()) - return {row["UserId"]:{"user_id":row["UserId"], - "char_name":row["EveCharName"], - "char_id":row["EveCharId"], - "corporation":row["Corporation"]} for row in fmembers["Data"]} + fmembers = json.loads(jsondata.decode()) + return {row["UserId"]: {"user_id": row["UserId"], + "char_name": row["EveCharName"], + "char_id": row["EveCharId"], + "corporation": row["Corporation"]} for row in fmembers["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): logger.debug("No fleetup members retrieved.") return {} - @staticmethod def get_fleetup_operations(): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Operations/" + str(groupid) + "" + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Operations/" + str(groupid) + "" try: jsondata = requests.get(url).content - foperations=json.loads(jsondata.decode()) - return {row["StartString"]:{"subject":row["Subject"], - "start": (datetime.strptime(row["StartString"], "%Y-%m-%d %H:%M:%S")), - "end": (datetime.strptime(row["EndString"], "%Y-%m-%d %H:%M:%S")), - "operation_id":row["OperationId"], - "location":row["Location"], - "location_info":row["LocationInfo"], - "details":row["Details"], - "url":row["Url"], - "doctrine":row["Doctrines"], - "organizer":row["Organizer"]} for row in foperations["Data"]} + foperations = json.loads(jsondata.decode()) + return {row["StartString"]: {"subject": row["Subject"], + "start": (datetime.strptime(row["StartString"], "%Y-%m-%d %H:%M:%S")), + "end": (datetime.strptime(row["EndString"], "%Y-%m-%d %H:%M:%S")), + "operation_id": row["OperationId"], + "location": row["Location"], + "location_info": row["LocationInfo"], + "details": row["Details"], + "url": row["Url"], + "doctrine": row["Doctrines"], + "organizer": row["Organizer"]} for row in foperations["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): @@ -58,18 +60,19 @@ class FleetUpManager(): @staticmethod def get_fleetup_timers(): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Timers/" + str(groupid) + "" + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Timers/" + str(groupid) + "" try: jsondata = requests.get(url).content - ftimers=json.loads(jsondata.decode()) - return {row["ExpiresString"]:{"solarsystem":row["SolarSystem"], - "planet":row["Planet"], - "moon":row["Moon"], - "owner":row["Owner"], - "type":row["Type"], - "timer_type":row["TimerType"], - "expires": (datetime.strptime(row["ExpiresString"], "%Y-%m-%d %H:%M:%S")), - "notes":row["Notes"]} for row in ftimers["Data"]} + ftimers = json.loads(jsondata.decode()) + return {row["ExpiresString"]: {"solarsystem": row["SolarSystem"], + "planet": row["Planet"], + "moon": row["Moon"], + "owner": row["Owner"], + "type": row["Type"], + "timer_type": row["TimerType"], + "expires": (datetime.strptime(row["ExpiresString"], "%Y-%m-%d %H:%M:%S")), + "notes": row["Notes"]} for row in ftimers["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): @@ -78,45 +81,50 @@ class FleetUpManager(): @staticmethod def get_fleetup_doctrines(): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Doctrines/" + str(groupid) + "" + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Doctrines/" + str(groupid) + "" try: jsondata = requests.get(url).content - fdoctrines=json.loads(jsondata.decode()) - return {"fleetup_doctrines":fdoctrines["Data"]} + fdoctrines = json.loads(jsondata.decode()) + return {"fleetup_doctrines": fdoctrines["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): logger.debug("No fleetup doctrines retrieved.") - return {"fleetup_doctrines":[]} + return {"fleetup_doctrines": []} @staticmethod def get_fleetup_doctrine(doctrinenumber): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/DoctrineFittings/%s" % doctrinenumber + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/DoctrineFittings/%s" % doctrinenumber try: jsondata = requests.get(url).content - fdoctrine=json.loads(jsondata.decode()) - return {"fitting_doctrine":fdoctrine} + fdoctrine = json.loads(jsondata.decode()) + return {"fitting_doctrine": fdoctrine} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): logger.warn("Fleetup doctrine number %s not found" % doctrinenumber) - return {"fitting_doctrine":{}} + return {"fitting_doctrine": {}} @staticmethod def get_fleetup_fittings(): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Fittings/" + str(groupid) + "" + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Fittings/" + str(groupid) + "" try: jsondata = requests.get(url).content - ffittings=json.loads(jsondata.decode()) - return {row["FittingId"]:{"fitting_id":row["FittingId"], - "name":row["Name"], - "icon_id":row["EveTypeId"], - "hull":row["HullType"], - "shiptype":row["ShipType"], - "estimated":row["EstPrice"], - "faction":row["Faction"], - "categories":row["Categories"], - "last_update":(datetime.strptime(row["LastUpdatedString"], "%Y-%m-%d %H:%M:%S"))} for row in ffittings["Data"]} + ffittings = json.loads(jsondata.decode()) + return {row["FittingId"]: {"fitting_id": row["FittingId"], + "name": row["Name"], + "icon_id": row["EveTypeId"], + "hull": row["HullType"], + "shiptype": row["ShipType"], + "estimated": row["EstPrice"], + "faction": row["Faction"], + "categories": row["Categories"], + "last_update": ( + datetime.strptime(row["LastUpdatedString"], "%Y-%m-%d %H:%M:%S"))} for row in + ffittings["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): @@ -125,25 +133,27 @@ class FleetUpManager(): @staticmethod def get_fleetup_fitting(fittingnumber): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Fitting/%s" % fittingnumber + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Fitting/%s" % fittingnumber try: jsondata = requests.get(url).content - ffitting=json.loads(jsondata.decode()) - return {"fitting_data":ffitting["Data"]} + ffitting = json.loads(jsondata.decode()) + return {"fitting_data": ffitting["Data"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): logger.warn("Fleetup fitting number %s not found" % fittingnumber) except KeyError: logger.warn("Failed to retrieve fleetup fitting number %s" % fittingnumber) - return {"fitting_data":{}} + return {"fitting_data": {}} @staticmethod def get_fleetup_doctrineid(fittingnumber): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Fitting/%s" % fittingnumber + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Fitting/%s" % fittingnumber try: jsondata = requests.get(url).content - fdoctrineid=json.loads(jsondata.decode()) + fdoctrineid = json.loads(jsondata.decode()) return fdoctrineid['Data']['Doctrines'][0]['DoctrineId'] except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") @@ -155,13 +165,14 @@ class FleetUpManager(): @staticmethod def get_fleetup_fitting_eft(fittingnumber): - url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str(apiid) + "/Fitting/%s/eft" % fittingnumber + url = "http://api.fleet-up.com/Api.svc/" + str(appkey) + "/" + str(userid) + "/" + str( + apiid) + "/Fitting/%s/eft" % fittingnumber try: jsondata = requests.get(url).content - ffittingeft=json.loads(jsondata.decode()) - return {"fitting_eft":ffittingeft["Data"]["FittingData"]} + ffittingeft = json.loads(jsondata.decode()) + return {"fitting_eft": ffittingeft["Data"]["FittingData"]} except requests.exceptions.ConnectionError: logger.warn("Can't connect to Fleet-Up API, is it offline?!") except (ValueError, UnicodeDecodeError): logger.warn("Fleetup fitting eft not found for fitting number %s" % fittingnumber) - return {"fitting_eft":{}} + return {"fitting_eft": {}} diff --git a/services/managers/ipboard_manager.py b/services/managers/ipboard_manager.py index f966d0f5..4f6e5124 100755 --- a/services/managers/ipboard_manager.py +++ b/services/managers/ipboard_manager.py @@ -1,6 +1,13 @@ +from __future__ import unicode_literals import os -import xmlrpclib +import re from hashlib import md5 +try: + from xmlrpclib import Server +except ImportError: + # python 3 + from xmlrpc import server as Server + from django.conf import settings @@ -8,6 +15,7 @@ import logging logger = logging.getLogger(__name__) + class IPBoardManager: def __init__(self): pass @@ -21,17 +29,21 @@ class IPBoardManager: def __generate_random_pass(): return os.urandom(8).encode('hex') + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w.-]', '', name) + @staticmethod def exec_xmlrpc(func, **kwargs): """ Send a XMLRPC request """ try: - server = xmlrpclib.Server(settings.IPBOARD_ENDPOINT, verbose=False) + server = Server(settings.IPBOARD_ENDPOINT, verbose=False) params = {} for i in kwargs: params[i] = kwargs[i] params['api_key'] = settings.IPBOARD_APIKEY params['api_module'] = settings.IPBOARD_APIMODULE - print params return getattr(server, func)(params) except: @@ -44,22 +56,22 @@ class IPBoardManager: logger.debug("Adding user to IPBoard with username %s" % sanatized) plain_password = IPBoardManager.__generate_random_pass() password = md5(plain_password).hexdigest() - ret = IPBoardManager.exec_xmlrpc('createUser', username=sanatized, email=str(email), display_name=sanatized, - md5_passwordHash=password) + IPBoardManager.exec_xmlrpc('createUser', username=sanatized, email=str(email), display_name=sanatized, + md5_passwordHash=password) logger.info("Added IPBoard user with username %s" % sanatized) return sanatized, plain_password @staticmethod def delete_user(username): """ Delete user """ - ret = IPBoardManager.exec_xmlrpc('deleteUser', username=username) + IPBoardManager.exec_xmlrpc('deleteUser', username=username) logger.info("Deleted IPBoard user with username %s" % username) return username @staticmethod def disable_user(username): """ Disable user """ - ret = IPBoardManager.exec_xmlrpc('disableUser', username=username) + IPBoardManager.exec_xmlrpc('disableUser', username=username) logger.info("Disabled IPBoard user with username %s" % username) return username @@ -67,8 +79,9 @@ class IPBoardManager: def update_user(username, email, password): """ Add user to service """ password = md5(password).hexdigest() - logger.debug("Updating IPBoard username %s with email %s and password hash starting with %s" % (username, email, password[0:5])) - ret = IPBoardManager.exec_xmlrpc('updateUser', username=username, email=email, md5_passwordHash=password) + logger.debug("Updating IPBoard username %s with email %s and password hash starting with %s" % ( + username, email, password[0:5])) + IPBoardManager.exec_xmlrpc('updateUser', username=username, email=email, md5_passwordHash=password) logger.info("Updated IPBoard user with username %s" % username) return username @@ -111,7 +124,6 @@ class IPBoardManager: @staticmethod def help_me(): - "Random help me" ret = IPBoardManager.exec_xmlrpc('helpMe') return ret @@ -120,13 +132,13 @@ class IPBoardManager: logger.debug("Updating IPBoard user %s with groups %s" % (username, groups)) forum_groups = IPBoardManager.get_all_groups() user_groups = set(IPBoardManager.get_user_groups(username)) - act_groups = set([g.replace(' ', '-') for g in groups]) + act_groups = set([IPBoardManager._sanitize_groupname(g) for g in groups]) addgroups = act_groups - user_groups remgroups = user_groups - act_groups logger.info("Updating IPBoard groups for user %s - adding %s, removing %s" % (username, addgroups, remgroups)) for g in addgroups: - if not g in forum_groups: + if g not in forum_groups: IPBoardManager.add_group(g) logger.debug("Adding user %s to IPBoard group %s" % (username, g)) IPBoardManager.add_user_to_group(username, g) diff --git a/services/managers/ips4_manager.py b/services/managers/ips4_manager.py index ad0e9eed..1fd59b5c 100644 --- a/services/managers/ips4_manager.py +++ b/services/managers/ips4_manager.py @@ -1,27 +1,21 @@ +from __future__ import unicode_literals import logging -from django.conf import settings -import requests import os from django.db import connections from passlib.hash import bcrypt -from django.utils import timezone - logger = logging.getLogger(__name__) -class Ips4Manager: +class Ips4Manager: SQL_ADD_USER = r"INSERT INTO core_members (name, email, members_pass_hash, members_pass_salt, " \ r"member_group_id) VALUES (%s, %s, %s, %s, %s)" SQL_GET_ID = r"SELECT member_id FROM core_members WHERE name = %s" SQL_UPDATE_PASSWORD = r"UPDATE core_members SET members_pass_hash = %s, members_pass_salt = %s WHERE name = %s" SQL_DEL_USER = r"DELETE FROM core_members WHERE member_id = %s" - - MEMBER_GROUP_ID = 3 - @staticmethod def add_user(username, email): logger.debug("Adding new IPS4 user %s" % username) @@ -30,7 +24,6 @@ class Ips4Manager: hash_result = hash rounds_striped = hash_result.strip('$2a$13$') salt = rounds_striped[:22] - joined_date = timezone.now group = Ips4Manager.MEMBER_GROUP_ID cursor = connections['ips4'].cursor() cursor.execute(Ips4Manager.SQL_ADD_USER, [username, email, hash, salt, group]) @@ -53,7 +46,6 @@ class Ips4Manager: def __generate_random_pass(): return os.urandom(8).encode('hex') - @staticmethod def delete_user(id): logger.debug("Deleting IPS4 user id %s" % id) @@ -107,4 +99,4 @@ class Ips4Manager: return plain_password else: logger.error("Unable to update ips4 user %s password" % username) - return "" \ No newline at end of file + return "" diff --git a/services/managers/market_manager.py b/services/managers/market_manager.py index c397c336..c1958fbb 100644 --- a/services/managers/market_manager.py +++ b/services/managers/market_manager.py @@ -1,18 +1,21 @@ +from __future__ import unicode_literals import logging -from django.conf import settings -import requests import os from django.db import connections from passlib.hash import bcrypt -## requires yum install libffi-devel and pip install bcrypt + +# requires yum install libffi-devel and pip install bcrypt logger = logging.getLogger(__name__) -class marketManager: - SQL_ADD_USER = r"INSERT INTO fos_user (username, username_canonical, email, email_canonical, enabled, salt, password," \ - r"locked, expired, roles, credentials_expired, characterid, characterName)" \ +class marketManager: + def __init__(self): + pass + + SQL_ADD_USER = r"INSERT INTO fos_user (username, username_canonical, email, email_canonical, enabled, salt," \ + r"password, locked, expired, roles, credentials_expired, characterid, characterName)" \ r"VALUES (%s, %s, %s, %s, 1,%s, %s, 0, 0, 'a:0:{}', 0, %s, %s) " SQL_GET_USER_ID = r"SELECT id FROM fos_user WHERE username = %s" SQL_DISABLE_USER = r"UPDATE fos_user SET enabled = '0' WHERE username = %s" @@ -22,7 +25,6 @@ class marketManager: SQL_CHECK_USERNAME = r"SELECT username FROM fos_user WHERE username = %s" SQL_UPDATE_USER = r"UPDATE fos_user SET password = %s, salt = %s, enabled = '1' WHERE username = %s" - @staticmethod def __santatize_username(username): sanatized = username.replace(" ", "_") @@ -56,7 +58,6 @@ class marketManager: logger.debug("User %s email address not found on alliance market" % username) return False - @staticmethod def add_user(username, email, characterid, charactername): logger.debug("Adding new market user %s" % username) @@ -66,8 +67,8 @@ class marketManager: rounds_striped = hash_result.strip('$2a$13$') salt = rounds_striped[:22] username_clean = marketManager.__santatize_username(username) - if marketManager.check_username(username)== False: - if marketManager.check_user_email(username, email) == False: + if not marketManager.check_username(username): + if not marketManager.check_user_email(username, email): try: logger.debug("Adding user %s to alliance market" % username) cursor = connections['market'].cursor() diff --git a/services/managers/mumble_manager.py b/services/managers/mumble_manager.py index a1ef9b5f..b3e12ff4 100755 --- a/services/managers/mumble_manager.py +++ b/services/managers/mumble_manager.py @@ -1,10 +1,6 @@ +from __future__ import unicode_literals import os import hashlib -import sys - -import django -from django.db import connections -from django.conf import settings from services.models import MumbleUser @@ -12,7 +8,10 @@ import logging logger = logging.getLogger(__name__) + class MumbleManager: + def __init__(self): + pass @staticmethod def __santatize_username(username): @@ -41,10 +40,11 @@ class MumbleManager: username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username(username, corp_ticker)) password = MumbleManager.__generate_random_pass() pwhash = MumbleManager._gen_pwhash(password) - logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (username_clean, pwhash[0:5])) + logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % ( + username_clean, pwhash[0:5])) if MumbleUser.objects.filter(username=username_clean).exists() is False: logger.info("Creating mumble user %s" % username_clean) - model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash) + MumbleUser.objects.create(username=username_clean, pwhash=pwhash) return username_clean, password else: logger.warn("Mumble user %s already exists. Updating password") @@ -57,13 +57,15 @@ class MumbleManager: @staticmethod def create_blue_user(corp_ticker, username): logger.debug("Creating mumble blue user with username %s and ticker %s" % (username, corp_ticker)) - username_clean = MumbleManager.__santatize_username(MumbleManager.__generate_username_blue(username, corp_ticker)) + username_clean = MumbleManager.__santatize_username( + MumbleManager.__generate_username_blue(username, corp_ticker)) password = MumbleManager.__generate_random_pass() pwhash = MumbleManager._gen_pwhash(password) - logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % (username_clean, pwhash[0:5])) + logger.debug("Proceeding with mumble user creation: clean username %s, pwhash starts with %s" % ( + username_clean, pwhash[0:5])) if MumbleUser.objects.filter(username=username_clean).exists() is False: logger.info("Creating mumble user %s" % username_clean) - model = MumbleUser.objects.create(username=username_clean, pwhash=pwhash) + MumbleUser.objects.create(username=username_clean, pwhash=pwhash) return username_clean, password else: logger.warn("Mumble user %s already exists. Updating password") @@ -102,7 +104,7 @@ class MumbleManager: def update_groups(username, groups): logger.debug("Updating mumble user %s groups %s" % (username, groups)) safe_groups = list(set([g.replace(' ', '-') for g in groups])) - groups ='' + groups = '' for g in safe_groups: groups = groups + g + ',' groups = groups.strip(',') diff --git a/services/managers/openfire_manager.py b/services/managers/openfire_manager.py index 5d8c88db..4cdb054a 100755 --- a/services/managers/openfire_manager.py +++ b/services/managers/openfire_manager.py @@ -1,9 +1,14 @@ +from __future__ import unicode_literals +from django.utils import six +import re import os -from urlparse import urlparse +try: + from urlparse import urlparse +except ImportError: + # python 3 + from urllib.parse import urlparse -import xmpp -from django.contrib.auth.models import User -from django.contrib.auth.models import Group +import sleekxmpp from django.conf import settings import threading from ofrestapi.users import Users as ofUsers @@ -13,6 +18,7 @@ import logging logger = logging.getLogger(__name__) + class OpenfireManager: def __init__(self): pass @@ -38,6 +44,11 @@ class OpenfireManager: def __generate_random_pass(): return os.urandom(8).encode('hex') + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w.-]', '', name) + @staticmethod def add_user(username): logger.debug("Adding username %s to openfire." % username) @@ -95,30 +106,33 @@ class OpenfireManager: return "" @staticmethod - def update_user_groups(username, password, groups): + def update_user_groups(username, groups): logger.debug("Updating openfire user %s groups %s" % (username, groups)) api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY) response = api.get_user_groups(username) remote_groups = [] if response: remote_groups = response['groupname'] - if isinstance(remote_groups, basestring): + if isinstance(remote_groups, six.string_types): remote_groups = [remote_groups] logger.debug("Openfire user %s has groups %s" % (username, remote_groups)) add_groups = [] del_groups = [] for g in groups: - if not g in remote_groups: + g = OpenfireManager._sanitize_groupname(g) + if g not in remote_groups: add_groups.append(g) for g in remote_groups: - if not g in groups: + g = OpenfireManager._sanitize_groupname(g) + if g not in groups: del_groups.append(g) - logger.info("Updating openfire groups for user %s - adding %s, removing %s" % (username, add_groups, del_groups)) + logger.info( + "Updating openfire groups for user %s - adding %s, removing %s" % (username, add_groups, del_groups)) if add_groups: api.add_user_groups(username, add_groups) if del_groups: api.delete_user_groups(username, del_groups) - + @staticmethod def delete_user_groups(username, groups): logger.debug("Deleting openfire groups %s from user %s" % (groups, username)) @@ -129,30 +143,58 @@ class OpenfireManager: @staticmethod def send_broadcast_message(group_name, broadcast_message): logger.debug("Sending jabber ping to group %s with message %s" % (group_name, broadcast_message)) - # create to address - client = xmpp.Client(settings.JABBER_URL) - client.connect(server=(settings.JABBER_SERVER, settings.JABBER_PORT)) - client.auth(settings.BROADCAST_USER, settings.BROADCAST_USER_PASSWORD, 'broadcast') - to_address = group_name + '@' + settings.BROADCAST_SERVICE_NAME + '.' + settings.JABBER_URL - logger.debug("Determined ping to address: %s" % to_address) - message = xmpp.Message(to_address, broadcast_message) - message.setAttr('type', 'chat') - client.send(message) - client.Process(1) + xmpp = PingBot(settings.BROADCAST_USER, settings.BROADCAST_USER_PASSWORD, to_address, broadcast_message) + xmpp.register_plugin('xep_0030') # Service Discovery + xmpp.register_plugin('xep_0199') # XMPP Ping + if xmpp.connect(): + xmpp.process(block=True) + logger.info("Sent jabber ping to group %s" % group_name) + else: + raise ValueError("Unable to connect to jabber server.") - client.disconnect() - logger.info("Sent jabber ping to group %s" % group_name) -class XmppThread (threading.Thread): - def __init__(self, threadID, name, counter, group, message,): +class PingBot(sleekxmpp.ClientXMPP): + """ + A copy-paste of the example client bot from + http://sleekxmpp.com/getting_started/sendlogout.html + """ + def __init__(self, jid, password, recipient, message): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + + # The message we wish to send, and the JID that + # will receive it. + self.recipient = recipient + self.msg = message + + # The session_start event will be triggered when + # the bot establishes its connection with the server + # and the XML streams are ready for use. We want to + # listen for this event so that we we can initialize + # our roster. + self.add_event_handler("session_start", self.start) + + def start(self, event): + self.send_presence() + self.get_roster() + + self.send_message(mto=self.recipient, + mbody=self.msg, + mtype='chat') + + # Using wait=True ensures that the send queue will be + # emptied before ending the session. + self.disconnect(wait=True) + + +class XmppThread(threading.Thread): + def __init__(self, thread_id, name, counter, group, message, ): threading.Thread.__init__(self) - self.threadID = threadID + self.threadID = thread_id self.name = name self.counter = counter self.group = group self.message = message + def run(self): - print "Starting " + self.name OpenfireManager.send_broadcast_message(self.group, self.message) - print "Exiting " + self.name diff --git a/services/managers/pathfinder_manager.py b/services/managers/pathfinder_manager.py deleted file mode 100644 index a06d9353..00000000 --- a/services/managers/pathfinder_manager.py +++ /dev/null @@ -1,196 +0,0 @@ -import logging -from django.conf import settings -import requests -import os -from django.db import connections -from passlib.hash import bcrypt -from eveonline.managers import EveManager -from authentication.managers import AuthServicesInfo -from eveonline.models import EveCharacter -from eveonline.models import EveApiKeyPair - -logger = logging.getLogger(__name__) - -class pathfinderManager: - - SQL_ADD_USER = r"INSERT INTO user (name, email, password, active) VALUES (%s, %s, %s, %s)" - SQL_ADD_API = r"INSERT INTO user_api (userid, keyid, vCode, active) VALUES (%s, %s, %s, %s)" - SQL_ADD_CHARACTER = r"INSERT INTO user_character (userid, apiId, characterId, isMain) VALUES (%s, %s, %s, %s)" - SQL_GET_APIID = r"SELECT id, keyId FROM user_api WHERE userId = %s" - SQL_GET_USERID = r"SELECT id FROM user WHERE name = %s" - SQL_DISABLE_USER = r"UPDATE user SET active = '0' WHERE name = %s" - SQL_UPDATE_USER = r"UPDATE user SET active = '1', password = %s WHERE name = %s" - SQL_CHECK_USER = r"SELECT name FROM user WHERE name = %s" - SQL_CHECK_EMAIL = r"SELECT email from user WHERE email = %s" - SQL_SET_MAIN = r"UPDATE user_character SET isMain = 1 WHERE characterId = %s" - - - @staticmethod - def __santatize_username(username): - sanatized = username.replace(" ", "_") - return sanatized.lower() - - @staticmethod - def __generate_random_pass(): - return os.urandom(8).encode('hex') - - @staticmethod - def check_username(username): - logger.debug("Checking for pathfinder username %s" % username) - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_CHECK_USER, [pathfinderManager.__santatize_username(username)]) - row = cursor.fetchone() - if row: - logger.debug("Found user %s on pathfinder" % username) - return True - logger.debug("User %s not found on pathfinder" % username) - return False - - @staticmethod - def update_user_info(username): - logger.debug("Updating pathfinder user %s" % username) - try: - username_clean = pathfinderManager.__santatize_username(username) - plain_password = pathfinderManager.__generate_random_pass() - passwd = bcrypt.encrypt(plain_password, rounds=10) - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_UPDATE_USER, [passwd, username_clean]) - return username_clean, plain_password - except: - logger.debug("Pathfinder update user failed for %s" % username) - return "", "" - - @staticmethod - def update_custom_password(username, plain_password): - logger.debug("Updating pathfinder user id %s password" % username) - if pathfinderManager.check_username(username): - username_clean = pathfinderManager.__santatize_username(username) - passwd = bcrypt.encrypt(plain_password, rounds=10) - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_UPDATE_USER, [passwd, username_clean]) - return plain_password - else: - logger.error("Unable to update ips4 user %s password" % username) - return "" - - @staticmethod - def disable_user(username): - logger.debug("Disabling user %s" % username) - if pathfinderManager.check_username(username) == True: - try: - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_DISABLE_USER, [pathfinderManager.__santatize_username(username)]) - return True - except: - logger.debug("User %s not found cannot disable" % username) - - - - @staticmethod - def add_user(username, email, charactername): - logger.debug("Adding new pathfinder user %s" % username) - plain_password = pathfinderManager.__generate_random_pass() - passwd = bcrypt.encrypt(plain_password, rounds=10) - username_clean = pathfinderManager.__santatize_username(username) - auth_id = pathfinderManager.get_authid_by_username(charactername) - - if pathfinderManager.check_username(username)== False: - if pathfinderManager.check_email(username, email) == False: - try: - logger.debug("Adding user %s to pathfinder" % username) - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_ADD_USER, [username_clean,email, passwd, '1']) - path_id = pathfinderManager.get_pathfinder_user_id(username_clean) - api_keys = pathfinderManager.get_api_key_pairs(auth_id) - main_character = AuthServicesInfo.objects.get(user=auth_id).main_char_id - - for keyId, key in api_keys.items(): - cursor.execute(pathfinderManager.SQL_ADD_API, [path_id, keyId, key, '1']) - - char_apis = pathfinderManager.get_char_id(auth_id) - - for c,a in char_apis.items(): - cursor.execute(pathfinderManager.SQL_ADD_CHARACTER, [path_id, (pathfinderManager.get_pathfinder_api_id(username, path_id)), c, '0']) - - pathfinderManager.set_main_char(username, main_character) - return username_clean, plain_password - - except: - logger.exception("Unsuccessful attempt at adding user %s to pathfinder on add_user" % username) - return "","" - else: - logger.debug("pathfinder username %s already exists Updating instead" % username) - username_clean, password = pathfinderManager.update_user_info(username) - return username_clean, password - else: - logger.debug("pathfinder username %s already exists Updating instead" % username) - username_clean, password = pathfinderManager.update_user_info(username) - return username_clean, password - - @staticmethod - def set_main_char (username, main_character): - try: - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_SET_MAIN, [main_character]) - except: - logger.debug("Failed setting main character for user %s"% username) - return "" - - @staticmethod - def get_api_key_pairs(user_id): - char = EveCharacter.objects.all().filter(user_id=user_id) - api_list = dict() - for c in char: - api_pair = EveApiKeyPair.objects.get(api_id=c.api_id) - api_list[api_pair.api_id] = api_pair.api_key - return api_list - - @staticmethod - def get_char_id(auth_id): - char = EveCharacter.objects.all().filter(user_id=auth_id) - char_list = dict() - for c in char: - char_list[c.character_id] = c.api_id - logger.debug("printing char list %s" % char_list) - return char_list - - @staticmethod - def get_authid_by_username(username): - authid = EveCharacter.objects.get(character_name=username).user_id - return authid - - @staticmethod - def get_pathfinder_user_id(username): - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_GET_USERID, [username]) - row = cursor.fetchone() - if row: - logger.debug("Pathfinder ID for user %s is %s" % (username, row[0])) - return int(row[0]) - else: - logger.debug("failed to get pathfinder ID for user %s" % username) - return "" - - @staticmethod - def get_pathfinder_api_id(username, path_id): - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_GET_APIID, [path_id]) - row = cursor.fetchone() - if row: - logger.debug("Pathfinder API ID for user %s is %s" % (username, row[0])) - return int(row[0]) - else: - logger.debug("failed to get pathfinder API ID for user %s" % username) - return "" - - @staticmethod - def check_email(username, email): - logger.debug("Checking if email %s exists for username %s" % (email,username)) - cursor = connections['pathfinder'].cursor() - cursor.execute(pathfinderManager.SQL_CHECK_EMAIL, [email]) - row = cursor.fetchone() - if row: - logger.debug("Found user %s email on pathfinder" % username) - return True - logger.debug("User %s email not found on pathfinder" % username) - return False diff --git a/services/managers/phpbb3_manager.py b/services/managers/phpbb3_manager.py index 92384328..55f2e883 100755 --- a/services/managers/phpbb3_manager.py +++ b/services/managers/phpbb3_manager.py @@ -1,5 +1,7 @@ +from __future__ import unicode_literals import os import calendar +import re from datetime import datetime from passlib.apps import phpbb3_context @@ -11,6 +13,7 @@ from django.conf import settings logger = logging.getLogger(__name__) + class Phpbb3Manager: SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, " \ r"user_password, user_email, group_id, user_regdate, user_permissions, " \ @@ -37,8 +40,9 @@ class Phpbb3Manager: SQL_GET_USER_GROUPS = r"SELECT phpbb_groups.group_name FROM phpbb_groups , phpbb_user_group WHERE " \ r"phpbb_user_group.group_id = phpbb_groups.group_id AND user_id=%s" - SQL_ADD_USER_AVATAR = r"UPDATE phpbb_users SET user_avatar_type=2, user_avatar_width=64, user_avatar_height=64, user_avatar=%s WHERE user_id = %s" - + SQL_ADD_USER_AVATAR = r"UPDATE phpbb_users SET user_avatar_type=2, user_avatar_width=64, user_avatar_height=64, " \ + "user_avatar=%s WHERE user_id = %s" + SQL_CLEAR_USER_PERMISSIONS = r"UPDATE phpbb_users SET user_permissions = '' WHERE user_Id = %s" SQL_DEL_SESSION = r"DELETE FROM phpbb_sessions where session_user_id = %s" @@ -70,6 +74,11 @@ class Phpbb3Manager: sanatized = sanatized.replace("'", "_") return sanatized.lower() + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w.-]', '', name) + @staticmethod def __get_group_id(groupname): logger.debug("Getting phpbb3 group id for groupname %s" % groupname) @@ -153,7 +162,8 @@ class Phpbb3Manager: @staticmethod def add_user(username, email, groups, characterid): - logger.debug("Adding phpbb user with username %s, email %s, groups %s, characterid %s" % (username, email, groups, characterid)) + logger.debug("Adding phpbb user with username %s, email %s, groups %s, characterid %s" % ( + username, email, groups, characterid)) cursor = connections['phpbb3'].cursor() username_clean = Phpbb3Manager.__santatize_username(username) @@ -195,7 +205,7 @@ class Phpbb3Manager: Phpbb3Manager.update_groups(username, []) logger.info("Disabled phpbb user %s" % username) return True - except TypeError as e: + except TypeError: logger.exception("TypeError occured while disabling user %s - failed to disable." % username) return False @@ -218,7 +228,7 @@ class Phpbb3Manager: if userid is not None: forum_groups = Phpbb3Manager.__get_all_groups() user_groups = set(Phpbb3Manager.__get_user_groups(userid)) - act_groups = set([g.replace(' ', '-') for g in groups]) + act_groups = set([Phpbb3Manager._sanitize_groupname(g) for g in groups]) addgroups = act_groups - user_groups remgroups = user_groups - act_groups logger.info("Updating phpbb user %s groups - adding %s, removing %s" % (username, addgroups, remgroups)) @@ -244,7 +254,9 @@ class Phpbb3Manager: cursor.execute(Phpbb3Manager.SQL_REMOVE_USER_GROUP, [userid, groupid]) logger.info("Removed phpbb user %s from group %s" % (username, group)) except: - logger.exception("Exception prevented removal of phpbb user %s with id %s from group %s with id %s" % (username, userid, group, groupid)) + logger.exception( + "Exception prevented removal of phpbb user %s with id %s from group %s with id %s" % ( + username, userid, group, groupid)) pass @staticmethod @@ -267,7 +279,8 @@ class Phpbb3Manager: password = Phpbb3Manager.__generate_random_pass() if Phpbb3Manager.check_user(username): pwhash = Phpbb3Manager.__gen_hash(password) - logger.debug("Proceeding to update phpbb user %s password with pwhash starting with %s" % (username, pwhash[0:5])) + logger.debug( + "Proceeding to update phpbb user %s password with pwhash starting with %s" % (username, pwhash[0:5])) cursor.execute(Phpbb3Manager.SQL_UPDATE_USER_PASSWORD, [pwhash, username]) Phpbb3Manager.__add_avatar(username, characterid) logger.info("Updated phpbb user %s password." % username) @@ -277,7 +290,8 @@ class Phpbb3Manager: @staticmethod def __update_user_info(username, email, password): - logger.debug("Updating phpbb user %s info: username %s password of length %s" % (username, email, len(password))) + logger.debug( + "Updating phpbb user %s info: username %s password of length %s" % (username, email, len(password))) cursor = connections['phpbb3'].cursor() try: cursor.execute(Phpbb3Manager.SQL_DIS_USER, [email, password, username]) diff --git a/services/managers/smf_manager.py b/services/managers/smf_manager.py index 701f63c5..a8352c7b 100644 --- a/services/managers/smf_manager.py +++ b/services/managers/smf_manager.py @@ -1,15 +1,21 @@ +from __future__ import unicode_literals import os import calendar from datetime import datetime import hashlib import logging +import re from django.db import connections from django.conf import settings logger = logging.getLogger(__name__) + class smfManager: + def __init__(self): + pass + SQL_ADD_USER = r"INSERT INTO smf_members (member_name, passwd, email_address, date_registered, real_name," \ r" buddy_list, message_labels, openid_uri, signature, ignore_boards) " \ r"VALUES (%s, %s, %s, %s, %s, 0, 0, 0, 0, 0)" @@ -36,7 +42,10 @@ class smfManager: SQL_ADD_USER_AVATAR = r"UPDATE smf_members SET avatar = %s WHERE id_member = %s" - + @staticmethod + def _sanitize_groupname(name): + name = name.strip(' _') + return re.sub('[^\w.-]', '', name) @staticmethod def generate_random_pass(): @@ -44,7 +53,7 @@ class smfManager: @staticmethod def gen_hash(username_clean, passwd): - return hashlib.sha1((username_clean) + passwd).hexdigest() + return hashlib.sha1(username_clean + passwd).hexdigest() @staticmethod def santatize_username(username): @@ -66,7 +75,6 @@ class smfManager: logger.info("Created smf group %s" % groupname) return smfManager.get_group_id(groupname) - @staticmethod def get_group_id(groupname): logger.debug("Getting smf group id for groupname %s" % groupname) @@ -88,7 +96,6 @@ class smfManager: logger.debug("User %s not found on smf" % username) return False - @staticmethod def add_avatar(member_name, characterid): logger.debug("Adding EVE character id %s portrait as smf avatar for user %s" % (characterid, member_name)) @@ -133,7 +140,8 @@ class smfManager: @staticmethod def add_user(username, email_address, groups, characterid): - logger.debug("Adding smf user with member_name %s, email_address %s, characterid %s" % (username, email_address, characterid)) + logger.debug("Adding smf user with member_name %s, email_address %s, characterid %s" % ( + username, email_address, characterid)) cursor = connections['smf'].cursor() username_clean = smfManager.santatize_username(username) passwd = smfManager.generate_random_pass() @@ -141,12 +149,13 @@ class smfManager: logger.debug("Proceeding to add smf user %s and pwhash starting with %s" % (username, pwhash[0:5])) register_date = smfManager.get_current_utc_date() # check if the username was simply revoked - if smfManager.check_user(username)is True : + if smfManager.check_user(username) is True: logger.warn("Unable to add smf user with username %s - already exists. Updating user instead." % username) smfManager.__update_user_info(username_clean, email_address, pwhash) else: try: - cursor.execute(smfManager.SQL_ADD_USER, [username_clean, passwd, email_address, register_date, username_clean]) + cursor.execute(smfManager.SQL_ADD_USER, + [username_clean, passwd, email_address, register_date, username_clean]) smfManager.add_avatar(username_clean, characterid) logger.info("Added smf member_name %s" % username_clean) smfManager.update_groups(username_clean, groups) @@ -157,7 +166,8 @@ class smfManager: @staticmethod def __update_user_info(username, email_address, passwd): - logger.debug("Updating smf user %s info: username %s password of length %s" % (username, email_address, len(passwd))) + logger.debug( + "Updating smf user %s info: username %s password of length %s" % (username, email_address, len(passwd))) cursor = connections['smf'].cursor() try: cursor.execute(smfManager.SQL_DIS_USER, [email_address, passwd, username]) @@ -185,19 +195,18 @@ class smfManager: if userid is not None: forum_groups = smfManager.get_all_groups() user_groups = set(smfManager.get_user_groups(userid)) - act_groups = set([g.replace(' ', '-') for g in groups]) + act_groups = set([smfManager._sanitize_groupname(g) for g in groups]) addgroups = act_groups - user_groups remgroups = user_groups - act_groups logger.info("Updating smf user %s groups - adding %s, removing %s" % (username, addgroups, remgroups)) act_group_id = set() for g in addgroups: - if not g in forum_groups: + if g not in forum_groups: forum_groups[g] = smfManager.create_group(g) act_group_id.add(str(smfManager.get_group_id(g))) string_groups = ','.join(act_group_id) smfManager.add_user_to_group(userid, string_groups) - @staticmethod def add_user_to_group(userid, groupid): logger.debug("Adding smf user id %s to group id %s" % (userid, groupid)) @@ -230,11 +239,11 @@ class smfManager: try: pwhash = smfManager.gen_hash(username, password) cursor.execute(smfManager.SQL_DIS_USER, [revoke_email, pwhash, username]) - userid = smfManager.get_user_id(username) + smfManager.get_user_id(username) smfManager.update_groups(username, []) logger.info("Disabled smf user %s" % username) return True - except TypeError as e: + except TypeError: logger.exception("TypeError occured while disabling user %s - failed to disable." % username) return False @@ -247,14 +256,11 @@ class smfManager: if smfManager.check_user(username): username_clean = smfManager.santatize_username(username) pwhash = smfManager.gen_hash(username_clean, password) - logger.debug("Proceeding to update smf user %s password with pwhash starting with %s" % (username, pwhash[0:5])) + logger.debug( + "Proceeding to update smf user %s password with pwhash starting with %s" % (username, pwhash[0:5])) cursor.execute(smfManager.SQL_UPDATE_USER_PASSWORD, [pwhash, username]) smfManager.add_avatar(username, characterid) logger.info("Updated smf user %s password." % username) return password logger.error("Unable to update smf user %s password - user not found on smf." % username) return "" - - - - diff --git a/services/managers/srp_manager.py b/services/managers/srp_manager.py index 6bd2f8b9..007a044e 100644 --- a/services/managers/srp_manager.py +++ b/services/managers/srp_manager.py @@ -1,46 +1,49 @@ +from __future__ import unicode_literals from django.conf import settings - -import json -import urllib2 +import requests import logging - logger = logging.getLogger(__name__) -class srpManager(): + +class srpManager: + def __init__(self): + pass + @staticmethod - def get_kill_id (killboard_link): - str = (killboard_link) - set = '0123456789' - kill_id = ''.join([c for c in str if c in set]) + def get_kill_id(killboard_link): + num_set = '0123456789' + kill_id = ''.join([c for c in killboard_link if c in num_set]) return kill_id @staticmethod - def get_kill_data (kill_id): + def get_kill_data(kill_id): url = ("https://www.zkillboard.com/api/killID/%s" % kill_id) - request = urllib2.Request(url) - request.add_header('User-Agent',"%s Alliance Auth" % settings.DOMAIN) - request.add_header('Content-Type','application/json') - response = urllib2.urlopen(request) - result = json.load(response)[0] + headers = { + 'User-Agent': "%s Alliance Auth" % settings.DOMAIN, + 'Content-Type': 'application/json', + } + r = requests.get(url, headers=headers) + result = r.json()[0] if result: ship_type = result['victim']['shipTypeID'] logger.debug("Ship type for kill ID %s is determined to be %s" % (kill_id, ship_type)) ship_value = result['zkb']['totalValue'] - logger.debug("total loss value for kill id %s is %s" %(kill_id, ship_value)) - return (ship_type, ship_value) + logger.debug("total loss value for kill id %s is %s" % (kill_id, ship_value)) + return ship_type, ship_value else: raise ValueError("Invalid Kill ID") @staticmethod - def get_ship_name (ship_type): + def get_ship_name(ship_type): url = ("https://jetbalsa.com/api/json.php/invTypes/%s" % ship_type) - request = urllib2.Request(url) - request.add_header('User-Agent',"%s Alliance Auth" % settings.DOMAIN) - request.add_header('Content-Type','application/json') - response = urllib2.urlopen(request) - result = json.load(response) + headers = { + 'User-Agent': "%s Alliance Auth" % settings.DOMAIN, + 'Content-Type': 'application/json', + } + r = requests.get(url, headers=headers) + result = r.json() if result: ship_name = result['typeName'] logger.debug("ship type %s determined to be %s" % (ship_type, ship_name)) @@ -48,13 +51,3 @@ class srpManager(): else: logger.debug("ship type %s is invalid" % ship_type) raise ValueError("Cannot get ship name") - - - - - - - - - - diff --git a/services/managers/teamspeak3_manager.py b/services/managers/teamspeak3_manager.py index 82f54a8c..e2c060bb 100755 --- a/services/managers/teamspeak3_manager.py +++ b/services/managers/teamspeak3_manager.py @@ -1,11 +1,13 @@ +from __future__ import unicode_literals from django.conf import settings -from services.managers.util.ts3 import TS3Server +from services.managers.util.ts3 import TS3Server, TeamspeakError from services.models import TSgroup import logging logger = logging.getLogger(__name__) + class Teamspeak3Manager: def __init__(self): pass @@ -117,10 +119,9 @@ class Teamspeak3Manager: def _add_user_to_group(uid, groupid): logger.debug("Adding group id %s to TS3 user id %s" % (groupid, uid)) server = Teamspeak3Manager.__get_created_server() - server_groups = Teamspeak3Manager._group_list() user_groups = Teamspeak3Manager._user_group_list(uid) - - if not groupid in user_groups.values(): + + if groupid not in user_groups.values(): logger.debug("User does not have group already. Issuing command to add.") server.send_command('servergroupaddclient', {'sgid': str(groupid), 'cldbid': uid}) @@ -130,7 +131,6 @@ class Teamspeak3Manager: def _remove_user_from_group(uid, groupid): logger.debug("Removing group id %s from TS3 user id %s" % (groupid, uid)) server = Teamspeak3Manager.__get_created_server() - server_groups = Teamspeak3Manager._group_list() user_groups = Teamspeak3Manager._user_group_list(uid) if str(groupid) in user_groups.values(): @@ -149,39 +149,45 @@ class Teamspeak3Manager: for key in remote_groups: logger.debug("Typecasting remote_group value at position %s to int: %s" % (key, remote_groups[key])) remote_groups[key] = int(remote_groups[key]) - + for group in local_groups: logger.debug("Checking local group %s" % group) if group.ts_group_id not in remote_groups.values(): - logger.debug("Local group id %s not found on server. Deleting model %s" % (group.ts_group_id, group)) + logger.debug( + "Local group id %s not found on server. Deleting model %s" % (group.ts_group_id, group)) TSgroup.objects.filter(ts_group_id=group.ts_group_id).delete() for key in remote_groups: - g = TSgroup(ts_group_id=remote_groups[key],ts_group_name=key) + g = TSgroup(ts_group_id=remote_groups[key], ts_group_name=key) q = TSgroup.objects.filter(ts_group_id=g.ts_group_id) if not q: - logger.debug("Local group does not exist for TS group %s. Creating TSgroup model %s" % (remote_groups[key], g)) + logger.debug("Local group does not exist for TS group %s. Creating TSgroup model %s" % ( + remote_groups[key], g)) g.save() + except TeamspeakError as e: + logger.error("Error occured while syncing TS group db: %s" % str(e)) except: logger.exception("An unhandled exception has occured while syncing TS groups.") - pass @staticmethod def add_user(username, corp_ticker): username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username(username, - corp_ticker)) + corp_ticker)) server = Teamspeak3Manager.__get_created_server() - token = "" logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean) server_groups = Teamspeak3Manager._group_list() - if not settings.DEFAULT_AUTH_GROUP in server_groups: + if settings.DEFAULT_AUTH_GROUP not in server_groups: Teamspeak3Manager._create_group(settings.DEFAULT_AUTH_GROUP) alliance_group_id = Teamspeak3Manager._group_id_by_name(settings.DEFAULT_AUTH_GROUP) - ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': alliance_group_id, 'tokenid2': 0, - 'tokendescription': username_clean, - 'tokencustomset': "ident=sso_uid value=%s" % username_clean}) + try: + ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': alliance_group_id, 'tokenid2': 0, + 'tokendescription': username_clean, + 'tokencustomset': "ident=sso_uid value=%s" % username_clean}) + except TeamspeakError as e: + logger.error("Failed to add teamspeak user %s: %s" % (username, str(e))) + return "","" try: token = ret['keys']['token'] @@ -189,24 +195,27 @@ class Teamspeak3Manager: return username_clean, token except: logger.exception("Failed to add teamspeak user %s - received response: %s" % (username_clean, ret)) - return "","" + return "", "" @staticmethod def add_blue_user(username, corp_ticker): username_clean = Teamspeak3Manager.__santatize_username(Teamspeak3Manager.__generate_username_blue(username, - corp_ticker)) + corp_ticker)) server = Teamspeak3Manager.__get_created_server() - token = "" logger.debug("Adding user to TS3 server with cleaned username %s" % username_clean) server_groups = Teamspeak3Manager._group_list() - if not settings.DEFAULT_BLUE_GROUP in server_groups: + if settings.DEFAULT_BLUE_GROUP not in server_groups: Teamspeak3Manager._create_group(settings.DEFAULT_BLUE_GROUP) blue_group_id = Teamspeak3Manager._group_id_by_name(settings.DEFAULT_BLUE_GROUP) - ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': blue_group_id, 'tokenid2': 0, - 'tokendescription': username_clean, - 'tokencustomset': "ident=sso_uid value=%s" % username_clean}) + try: + ret = server.send_command('tokenadd', {'tokentype': 0, 'tokenid1': blue_group_id, 'tokenid2': 0, + 'tokendescription': username_clean, + 'tokencustomset': "ident=sso_uid value=%s" % username_clean}) + except TeamspeakError as e: + logger.error("Failed to add blue teamspeak user %s: %s" % (username, str(e))) + return "","" try: token = ret['keys']['token'] @@ -214,10 +223,7 @@ class Teamspeak3Manager: return username_clean, token except: logger.exception("Failed to add blue teamspeak user %s - received response: %s" % (username_clean, ret)) - return "","" - - - + return "", "" @staticmethod def delete_user(uid): @@ -235,7 +241,12 @@ class Teamspeak3Manager: logger.exception("Failed to delete user id %s from TS3 - received response %s" % (uid, client)) return False - ret = server.send_command('clientdbdelete', {'cldbid': user}) + try: + ret = server.send_command('clientdbdelete', {'cldbid': user}) + except TeamspeakError as e: + logger.error("Failed to delete teamspeak user %s: %s" % (uid, str(e))) + return False + if ret == '0': logger.info("Deleted user with id %s from TS3 server." % uid) return True @@ -291,4 +302,3 @@ class Teamspeak3Manager: for g in remgroups: logger.info("Removing Teamspeak user %s from group %s" % (userid, g)) Teamspeak3Manager._remove_user_from_group(userid, g) - diff --git a/services/managers/util/__init__.py b/services/managers/util/__init__.py index 8fdaf87a..81a621a7 100755 --- a/services/managers/util/__init__.py +++ b/services/managers/util/__init__.py @@ -1 +1,2 @@ +from __future__ import unicode_literals __author__ = 'r4stl1n' diff --git a/services/managers/util/ts3.py b/services/managers/util/ts3.py index 1122737b..f61c304b 100755 --- a/services/managers/util/ts3.py +++ b/services/managers/util/ts3.py @@ -1,8 +1,9 @@ +from __future__ import unicode_literals import socket import logging -class ConnectionError(): +class ConnectionError: def __init__(self, ip, port): self.ip = ip self.port = port @@ -22,8 +23,7 @@ ts3_escape = {'/': r"\/", "\t": r'\t', "\v": r'\v'} - -class TS3Proto(): +class TS3Proto: bytesin = 0 bytesout = 0 @@ -66,7 +66,7 @@ class TS3Proto(): while True: resp = self._sockfile.readline() resp = self.parse_command(resp) - if not 'command' in resp: + if 'command' not in resp: data.append(resp) else: break @@ -78,7 +78,7 @@ class TS3Proto(): else: return data[0] else: - return resp['keys']['id'] + raise TeamspeakError(resp['keys']['id']) def construct_command(self, command, keys=None, opts=None): """ @@ -139,7 +139,7 @@ class TS3Proto(): v = [v[0], '='.join(v[1:])] key, value = v keys[key] = self._unescape_str(value) - elif (not v == ['']): + elif not v == ['']: if v[0][0] and v[0][0] == '-': # Option opts.append(v[0][1:]) @@ -159,9 +159,10 @@ class TS3Proto(): @type value: string/int """ - if isinstance(value, int): return "%d" % value + if isinstance(value, int): + return "%d" % value value = value.replace("\\", r'\\') - for i, j in ts3_escape.iteritems(): + for i, j in ts3_escape: value = value.replace(i, j) return value @@ -173,13 +174,13 @@ class TS3Proto(): @type value: string/int """ - if isinstance(value, int): return "%d" % value + if isinstance(value, int): + return "%d" % value value = value.replace(r"\\", "\\") - for i, j in ts3_escape.iteritems(): + for i, j in ts3_escape: value = value.replace(j, i) return value - def send(self, payload): if self._connected: self._log.debug('Sent: %s' % payload) @@ -230,7 +231,7 @@ class TS3Server(TS3Proto): """ Send a global message to the current Virtual Server @param msg: Message - @type ip: str + @type msg: str """ if self._connected: return self.send_command('gm', keys={'msg': msg}) @@ -243,3 +244,213 @@ class TS3Server(TS3Proto): """ if self._connected and id > 0: self.send_command('use', keys={'sid': id}) + + +class TeamspeakError: + def __init__(self, code, msg=None): + self.code = str(code) + if not msg: + msg = ts3_errors[self.code] + self.msg = msg + + def __str__(self): + return self.code + ' ' + self.msg + +ts3_errors = { + '0': 'unknown error code', + '1': 'undefined error', + '2': 'not implemented', + '3': '', + '4': '', + '5': 'library time limit reached', + '256': 'command not found', + '257': 'unable to bind network port', + '258': 'no network port available', + '512': 'invalid clientID', + '513': 'nickname is already in use', + '514': 'invalid error code', + '515': 'max clients protocol limit reached', + '516': 'invalid client type', + '517': 'already subscribed', + '518': 'not logged in', + '519': 'could not validate client identity', + '520': 'invalid loginname or password', + '521': 'too many clones already connected', + '522': 'client version outdated, please update', + '523': 'client is online', + '524': 'client is flooding', + '525': 'client is modified', + '526': 'can not verify client at this moment', + '527': 'client is not permitted to log in', + '528': 'client is not subscribed to the channel', + '768': 'invalid channelID', + '769': 'max channels protocol limit reached', + '770': 'already member of channel', + '771': 'channel name is already in use', + '772': 'channel not empty', + '773': 'can not delete default channel', + '774': 'default channel requires permanent', + '775': 'invalid channel flags', + '776': 'permanent channel can not be child of non permanent channel', + '777': 'channel maxclient reached', + '778': 'channel maxfamily reached', + '779': 'invalid channel order', + '780': 'channel does not support filetransfers', + '781': 'invalid channel password', + '782': 'channel is private channel', + '783': 'invalid security hash supplied by client', + '1024': 'invalid serverID', + '1025': 'server is running', + '1026': 'server is shutting down', + '1027': 'server maxclient reached', + '1028': 'invalid server password', + '1029': 'deployment active', + '1030': 'unable to stop own server in your connection class', + '1031': 'server is virtual', + '1032': 'server wrong machineID', + '1033': 'server is not running', + '1034': 'server is booting up', + '1035': 'server got an invalid status for this operation', + '1036': 'server modal quit', + '1037': 'server version is too old for command', + '1280': 'database error', + '1281': 'database empty result set', + '1282': 'database duplicate entry', + '1283': 'database no modifications', + '1284': 'database invalid constraint', + '1285': 'database reinvoke command', + '1536': 'invalid quote', + '1537': 'invalid parameter count', + '1538': 'invalid parameter', + '1539': 'parameter not found', + '1540': 'convert error', + '1541': 'invalid parameter size', + '1542': 'missing required parameter', + '1543': 'invalid checksum', + '1792': 'virtual server got a critical error', + '1793': 'Connection lost', + '1794': 'not connected', + '1795': 'no cached connection info', + '1796': 'currently not possible', + '1797': 'failed connection initialization', + '1798': 'could not resolve hostname', + '1799': 'invalid server connection handler ID', + '1800': 'could not initialize Input Manager', + '1801': 'client library not initialized', + '1802': 'server library not initialized', + '1803': 'too many whisper targets', + '1804': 'no whisper targets found', + '2048': 'invalid file name', + '2049': 'invalid file permissions', + '2050': 'file already exists', + '2051': 'file not found', + '2052': 'file input/output error', + '2053': 'invalid file transfer ID', + '2054': 'invalid file path', + '2055': 'no files available', + '2056': 'overwrite excludes resume', + '2057': 'invalid file size', + '2058': 'file already in use', + '2059': 'could not open file transfer connection', + '2060': 'no space left on device (disk full?)', + '2061': "file exceeds file system's maximum file size", + '2062': 'file transfer connection timeout', + '2063': 'lost file transfer connection', + '2064': 'file exceeds supplied file size', + '2065': 'file transfer complete', + '2066': 'file transfer canceled', + '2067': 'file transfer interrupted', + '2068': 'file transfer server quota exceeded', + '2069': 'file transfer client quota exceeded', + '2070': 'file transfer reset', + '2071': 'file transfer limit reached', + '2304': 'preprocessor disabled', + '2305': 'internal preprocessor', + '2306': 'internal encoder', + '2307': 'internal playback', + '2308': 'no capture device available', + '2309': 'no playback device available', + '2310': 'could not open capture device', + '2311': 'could not open playback device', + '2312': 'ServerConnectionHandler has a device registered', + '2313': 'invalid capture device', + '2314': 'invalid clayback device', + '2315': 'invalid wave file', + '2316': 'wave file type not supported', + '2317': 'could not open wave file', + '2318': 'internal capture', + '2319': 'device still in use', + '2320': 'device already registerred', + '2321': 'device not registered/known', + '2322': 'unsupported frequency', + '2323': 'invalid channel count', + '2324': 'read error in wave', + '2325': 'sound need more data', + '2326': 'sound device was busy', + '2327': 'there is no sound data for this period', + '2328': 'Channelmask set bits count (speakers) is not the same as channel (count)', + '2560': 'invalid group ID', + '2561': 'duplicate entry', + '2562': 'invalid permission ID', + '2563': 'empty result set', + '2564': 'access to default group is forbidden', + '2565': 'invalid size', + '2566': 'invalid value', + '2567': 'group is not empty', + '2568': 'insufficient client permissions', + '2569': 'insufficient group modify power', + '2570': 'insufficient permission modify power', + '2571': 'template group is currently used', + '2572': 'permission error', + '2816': 'virtualserver limit reached', + '2817': 'max slot limit reached', + '2818': 'license file not found', + '2819': 'license date not ok', + '2820': 'unable to connect to accounting server', + '2821': 'unknown accounting error', + '2822': 'accounting server error', + '2823': 'instance limit reached', + '2824': 'instance check error', + '2825': 'license file invalid', + '2826': 'virtualserver is running elsewhere', + '2827': 'virtualserver running in same instance already', + '2828': 'virtualserver already started', + '2829': 'virtualserver not started', + '2830': '', + '3072': 'invalid message id', + '3328': 'invalid ban id', + '3329': 'connection failed, you are banned', + '3330': 'rename failed, new name is banned', + '3331': 'flood ban', + '3584': 'unable to initialize tts', + '3840': 'invalid privilege key', + '4096': '', + '4097': '', + '4098': '', + '4099': '', + '4100': '', + '4101': '', + '4102': '', + '4103': '', + '4352': 'invalid password', + '4353': 'invalid request', + '4354': 'no (more) slots available', + '4355': 'pool missing', + '4356': 'pool unknown', + '4357': 'unknown ip location (perhaps LAN ip?)', + '4358': 'internal error (tried exceeded)', + '4359': 'too many slots requested', + '4360': 'too many reserved', + '4361': 'could not connect to provisioning server', + '4368': 'authentication server not connected', + '4369': 'authentication data too large', + '4370': 'already initialized', + '4371': 'not initialized', + '4372': 'already connecting', + '4373': 'already connected', + '4374': '', + '4375': 'io_error', + '4376': '', + '4377': '', + '4378': '', +} diff --git a/services/managers/xenforo_manager.py b/services/managers/xenforo_manager.py index 18050201..aaa4ca3f 100644 --- a/services/managers/xenforo_manager.py +++ b/services/managers/xenforo_manager.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import os import requests import json @@ -8,130 +9,131 @@ import logging logger = logging.getLogger(__name__) + class XenForoManager: - def __init__(self): - if not settings.XENFORO_ENDPOINT: - logger.debug("Could not find XenForo endpoint") - if not settings.XENFORO_APIKEY: - logger.debug("XenForo API Key not found") - pass + def __init__(self): + if not settings.XENFORO_ENDPOINT: + logger.debug("Could not find XenForo endpoint") + if not settings.XENFORO_APIKEY: + logger.debug("XenForo API Key not found") + pass - @staticmethod - def __sanitize_username(username): - sanitized = username.replace(" ", "_") - return sanitized + @staticmethod + def __sanitize_username(username): + sanitized = username.replace(" ", "_") + return sanitized - @staticmethod - def __generate_password(): - return os.urandom(8).encode('hex') + @staticmethod + def __generate_password(): + return os.urandom(8).encode('hex') - @staticmethod - def exec_http_request(http_params): - default_params = { - 'hash': settings.XENFORO_APIKEY - } - http_params.update(default_params) - r = requests.get(settings.XENFORO_ENDPOINT, params=http_params) - return r + @staticmethod + def exec_http_request(http_params): + default_params = { + 'hash': settings.XENFORO_APIKEY + } + http_params.update(default_params) + r = requests.get(settings.XENFORO_ENDPOINT, params=http_params) + return r - @staticmethod - def add_user(username, email): + @staticmethod + def add_user(username, email): - sanitized = XenForoManager.__sanitize_username(username) - password = XenForoManager.__generate_password(); + sanitized = XenForoManager.__sanitize_username(username) + password = XenForoManager.__generate_password() - data = { - 'action': 'register', - 'username': sanitized, - 'password': password, - 'email': email, - 'group': settings.XENFORO_DEFAULT_GROUP, - 'visible': '1', - 'user_state': 'valid' - } + data = { + 'action': 'register', + 'username': sanitized, + 'password': password, + 'email': email, + 'group': settings.XENFORO_DEFAULT_GROUP, + 'visible': '1', + 'user_state': 'valid' + } - r = XenForoManager.exec_http_request(data) - - # check if the user already exist but was disabled - if r.status_code != 200: - if json.loads(r.text)['error'] == 7: - data = XenForoManager.reactivate_user(sanitized) - return data + r = XenForoManager.exec_http_request(data) - response = { - 'response': { - 'message': r.text, - 'status_code': r.status_code - } - } - data.update(response) - return data + # check if the user already exist but was disabled + if r.status_code != 200: + if json.loads(r.text)['error'] == 7: + data = XenForoManager.reactivate_user(sanitized) + return data - @staticmethod - def reset_password(username): + response = { + 'response': { + 'message': r.text, + 'status_code': r.status_code + } + } + data.update(response) + return data - password = XenForoManager.__generate_password(); + @staticmethod + def reset_password(username): - data = { - 'action': 'editUser', - 'user': username, - 'password': password - } + password = XenForoManager.__generate_password() - r = XenForoManager.exec_http_request(data) + data = { + 'action': 'editUser', + 'user': username, + 'password': password + } - response = { - 'response': { - 'message': r.text, - 'status_code': r.status_code - } - } - data.update(response) - return data + r = XenForoManager.exec_http_request(data) - @staticmethod - def disable_user(username): - data = { - 'action': 'editUser', - 'user': username, - 'remove_groups': settings.XENFORO_DEFAULT_GROUP - } - r = XenForoManager.exec_http_request(data) - return r + response = { + 'response': { + 'message': r.text, + 'status_code': r.status_code + } + } + data.update(response) + return data - @staticmethod - def reactivate_user(username): - data = { - 'action': 'editUser', - 'user': username, - 'add_groups': settings.XENFORO_DEFAULT_GROUP, - 'password': XenForoManager.__generate_password() - } - r = XenForoManager.exec_http_request(data) - response = { - 'response': { - 'message': r.text, - 'status_code': r.status_code - }, - 'username': username - } - data.update(response) - return data + @staticmethod + def disable_user(username): + data = { + 'action': 'editUser', + 'user': username, + 'remove_groups': settings.XENFORO_DEFAULT_GROUP + } + r = XenForoManager.exec_http_request(data) + return r - @staticmethod - def update_user_password(username, raw_password): - data = { - 'action': 'editUser', - 'user': username, - 'password': raw_password - } - r = XenForoManager.exec_http_request(data) - response = { - 'response': { - 'message': r.text, - 'status_code': r.status_code - }, - 'username': username - } - data.update(response) - return data \ No newline at end of file + @staticmethod + def reactivate_user(username): + data = { + 'action': 'editUser', + 'user': username, + 'add_groups': settings.XENFORO_DEFAULT_GROUP, + 'password': XenForoManager.__generate_password() + } + r = XenForoManager.exec_http_request(data) + response = { + 'response': { + 'message': r.text, + 'status_code': r.status_code + }, + 'username': username + } + data.update(response) + return data + + @staticmethod + def update_user_password(username, raw_password): + data = { + 'action': 'editUser', + 'user': username, + 'password': raw_password + } + r = XenForoManager.exec_http_request(data) + response = { + 'response': { + 'message': r.text, + 'status_code': r.status_code + }, + 'username': username + } + data.update(response) + return data diff --git a/services/migrations/0001_initial.py b/services/migrations/0001_initial.py new file mode 100644 index 00000000..5787cfb8 --- /dev/null +++ b/services/migrations/0001_initial.py @@ -0,0 +1,83 @@ +# -*- 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 = [ + ('auth', '0008_alter_user_username_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='AuthTS', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('auth_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group')), + ], + options={ + 'verbose_name': 'Auth / TS Group', + }, + ), + migrations.CreateModel( + name='DiscordAuthToken', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.CharField(max_length=254, unique=True)), + ('token', models.CharField(max_length=254)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='GroupCache', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('groups', models.TextField(default={})), + ('service', models.CharField(choices=[(b'discourse', b'discourse'), (b'discord', b'discord')], max_length=254, unique=True)), + ], + ), + migrations.CreateModel( + name='MumbleUser', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('username', models.CharField(max_length=254, unique=True)), + ('pwhash', models.CharField(max_length=40)), + ('groups', models.TextField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='TSgroup', + fields=[ + ('ts_group_id', models.IntegerField(primary_key=True, serialize=False)), + ('ts_group_name', models.CharField(max_length=30)), + ], + options={ + 'verbose_name': 'TS Group', + }, + ), + migrations.CreateModel( + name='UserTSgroup', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ts_group', models.ManyToManyField(to='services.TSgroup')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'User TS Group', + }, + ), + migrations.AddField( + model_name='authts', + name='ts_group', + field=models.ManyToManyField(to='services.TSgroup'), + ), + ] diff --git a/services/migrations/0002_auto_20161016_0135.py b/services/migrations/0002_auto_20161016_0135.py new file mode 100644 index 00000000..68749395 --- /dev/null +++ b/services/migrations/0002_auto_20161016_0135.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-10-16 01:35 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('services', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='discordauthtoken', + name='user', + ), + migrations.DeleteModel( + name='DiscordAuthToken', + ), + ] diff --git a/services/migrations/__init__.py b/services/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/services/models.py b/services/models.py index 3ff5c786..80b62c08 100644 --- a/services/models.py +++ b/services/models.py @@ -1,44 +1,45 @@ +from __future__ import unicode_literals +from django.utils.encoding import python_2_unicode_compatible from django.db import models -from django.contrib.auth.models import Group, User + +@python_2_unicode_compatible class TSgroup(models.Model): ts_group_id = models.IntegerField(primary_key=True) ts_group_name = models.CharField(max_length=30) class Meta: - verbose_name='TS Group' + verbose_name = 'TS Group' def __str__(self): return self.ts_group_name - + + +@python_2_unicode_compatible class AuthTS(models.Model): auth_group = models.ForeignKey('auth.Group') ts_group = models.ManyToManyField(TSgroup) class Meta: - verbose_name='Auth / TS Group' + verbose_name = 'Auth / TS Group' def __str__(self): return self.auth_group.name + +@python_2_unicode_compatible class UserTSgroup(models.Model): user = models.ForeignKey('auth.User') ts_group = models.ManyToManyField(TSgroup) class Meta: - verbose_name='User TS Group' + verbose_name = 'User TS Group' def __str__(self): return self.user.name -class DiscordAuthToken(models.Model): - email = models.CharField(max_length=254, unique=True) - token = models.CharField(max_length=254) - user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) - def __str__(self): - output = "Discord Token for email %s user %s" % (self.email, self.user) - return output.encode('utf-8') +@python_2_unicode_compatible class MumbleUser(models.Model): username = models.CharField(max_length=254, unique=True) pwhash = models.CharField(max_length=40) @@ -47,6 +48,8 @@ class MumbleUser(models.Model): def __str__(self): return self.username + +@python_2_unicode_compatible class GroupCache(models.Model): SERVICE_CHOICES = ( ("discourse", "discourse"), diff --git a/celerytask/signals.py b/services/signals.py similarity index 81% rename from celerytask/signals.py rename to services/signals.py index 0ca303f8..acc1102d 100644 --- a/celerytask/signals.py +++ b/services/signals.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from django.db.models.signals import m2m_changed from django.db.models.signals import post_save from django.db.models.signals import pre_save @@ -6,25 +7,26 @@ from django.db.models.signals import pre_delete from django.dispatch import receiver from django.contrib.auth.models import User import logging -from .tasks import update_jabber_groups -from .tasks import update_mumble_groups -from .tasks import update_forum_groups -from .tasks import update_ipboard_groups -from .tasks import update_discord_groups -from .tasks import update_teamspeak3_groups -from .tasks import update_discourse_groups -from .tasks import update_smf_groups -from .tasks import set_state -from .tasks import disable_member +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_discord_groups +from services.tasks import update_teamspeak3_groups +from services.tasks import update_discourse_groups +from services.tasks import update_smf_groups +from authentication.tasks import set_state +from authentication.tasks import disable_member from authentication.models import AuthServicesInfo from services.models import AuthTS logger = logging.getLogger(__name__) + @receiver(m2m_changed, sender=User.groups.through) def m2m_changed_user_groups(sender, instance, action, *args, **kwargs): logger.debug("Received m2m_changed from %s groups with action %s" % (instance, action)) - if action=="post_add" or action=="post_remove" or action=="post_clear": + if action == "post_add" or action == "post_remove" or action == "post_clear": logger.debug("Triggering service group update for %s" % instance) auth, c = AuthServicesInfo.objects.get_or_create(user=instance) if auth.jabber_username: @@ -43,32 +45,40 @@ def m2m_changed_user_groups(sender, instance, action, *args, **kwargs): update_mumble_groups.delay(instance.pk) if auth.discourse_username: update_discourse_groups.delay(instance.pk) + if auth.smf_username: + update_smf_groups.delay(instance.pk) + def trigger_all_ts_update(): for auth in AuthServicesInfo.objects.filter(teamspeak3_uid__isnull=False): update_teamspeak3_groups.delay(auth.user.pk) + @receiver(m2m_changed, sender=AuthTS.ts_group.through) def m2m_changed_authts_group(sender, instance, action, *args, **kwargs): logger.debug("Received m2m_changed from %s ts_group with action %s" % (instance, action)) - if action=="post_add" or action=="post_remove": + if action == "post_add" or action == "post_remove": trigger_all_ts_update() + @receiver(post_save, sender=AuthTS) def post_save_authts(sender, instance, *args, **kwargs): logger.debug("Received post_save from %s" % instance) trigger_all_ts_update() + @receiver(post_delete, sender=AuthTS) def post_delete_authts(sender, instance, *args, **kwargs): logger.debug("Received post_delete signal from %s" % instance) trigger_all_ts_update() + @receiver(pre_delete, sender=User) def pre_delete_user(sender, instance, *args, **kwargs): logger.debug("Received pre_delete from %s" % instance) disable_member(instance) + @receiver(pre_save, sender=User) def pre_save_user(sender, instance, *args, **kwargs): logger.debug("Received pre_save from %s" % instance) diff --git a/services/tasks.py b/services/tasks.py index e3a45694..e754de13 100644 --- a/services/tasks.py +++ b/services/tasks.py @@ -1,20 +1,47 @@ -from authentication.models import AuthServicesInfo -from celerytask.models import SyncGroupCache +from __future__ import unicode_literals from django.conf import settings import logging +from django.contrib.auth.models import User +from celery import task from services.models import UserTSgroup from services.models import AuthTS from services.models import TSgroup -from services.models import DiscordAuthToken from services.models import MumbleUser +from authentication.managers import AuthServicesInfoManager +from authentication.models import AuthServicesInfo +from services.managers.openfire_manager import OpenfireManager +from services.managers.phpbb3_manager import Phpbb3Manager +from services.managers.mumble_manager import MumbleManager +from services.managers.ipboard_manager import IPBoardManager +from services.managers.teamspeak3_manager import Teamspeak3Manager +from services.managers.discord_manager import DiscordOAuthManager +from services.managers.xenforo_manager import XenForoManager +from services.managers.market_manager import marketManager +from services.managers.discourse_manager import DiscourseManager +from services.managers.smf_manager import smfManager +from services.managers.util.ts3 import TeamspeakError +from authentication.states import MEMBER_STATE, BLUE_STATE +from notifications import notify +from celery.task import periodic_task +from celery.task.schedules import crontab logger = logging.getLogger(__name__) + +@periodic_task(run_every=crontab(minute="*/30")) +def run_ts3_group_update(): + if settings.ENABLE_AUTH_TEAMSPEAK3 or settings.ENABLE_BLUE_TEAMSPEAK3: + logger.debug("TS3 installed. Syncing local group objects.") + Teamspeak3Manager._sync_ts_group_db() + + def disable_teamspeak(): if settings.ENABLE_AUTH_TEAMSPEAK3: - logger.warn("ENABLE_AUTH_TEAMSPEAK3 still True, after disabling users will still be able to create teamspeak accounts") + logger.warn( + "ENABLE_AUTH_TEAMSPEAK3 still True, after disabling users will still be able to create teamspeak accounts") if settings.ENABLE_BLUE_TEAMSPEAK3: - logger.warn("ENABLE_BLUE_TEAMSPEAK3 still True, after disabling blues will still be able to create teamspeak accounts") + logger.warn( + "ENABLE_BLUE_TEAMSPEAK3 still True, after disabling blues will still be able to create teamspeak accounts") for auth in AuthServicesInfo.objects.all(): if auth.teamspeak3_uid: logger.info("Clearing %s Teamspeak3 UID" % auth.user) @@ -32,6 +59,7 @@ def disable_teamspeak(): TSgroup.objects.all().delete() logger.info("Teamspeak3 disabled") + def disable_forum(): if settings.ENABLE_AUTH_FORUM: logger.warn("ENABLE_AUTH_FORUM still True, after disabling users will still be able to create forum accounts") @@ -46,8 +74,7 @@ def disable_forum(): logger.info("Clearing %s forum password" % auth.user) auth.forum_password = '' auth.save() - logger.info("Deleting all SyncGroupCache models for forum") - SyncGroupCache.objects.filter(servicename="forum").delete() + def disable_jabber(): if settings.ENABLE_AUTH_JABBER: @@ -63,8 +90,7 @@ def disable_jabber(): logger.info("Clearing %s jabber password" % auth.user) auth.jabber_password = '' auth.save() - logger.info("Deleting all SyncGroupCache models for jabber") - SyncGroupCache.objects.filter(servicename="jabber").delete() + def disable_mumble(): if settings.ENABLE_AUTH_MUMBLE: @@ -80,16 +106,17 @@ def disable_mumble(): logger.info("Clearing %s mumble password" % auth.user) auth.mumble_password = '' auth.save() - logger.info("Deleting all SyncGroupCache models for mumble") - SyncGroupCache.objects.filter(servicename="mumble").delete() logger.info("Deleting all MumbleUser models") MumbleUser.objects.all().delete() + def disable_ipboard(): if settings.ENABLE_AUTH_IPBOARD: - logger.warn("ENABLE_AUTH_IPBOARD still True, after disabling users will still be able to create IPBoard accounts") + logger.warn( + "ENABLE_AUTH_IPBOARD still True, after disabling users will still be able to create IPBoard accounts") if settings.ENABLE_BLUE_IPBOARD: - logger.warn("ENABLE_BLUE_IPBOARD still True, after disabling blues will still be able to create IPBoard accounts") + logger.warn( + "ENABLE_BLUE_IPBOARD still True, after disabling blues will still be able to create IPBoard accounts") for auth in AuthServicesInfo.objects.all(): if auth.ipboard_username: logger.info("Clearing %s ipboard username" % auth.user) @@ -99,8 +126,6 @@ def disable_ipboard(): logger.info("Clearing %s ipboard password" % auth.user) auth.ipboard_password = '' auth.save() - logger.info("Deleting all SyncGroupCache models for ipboard") - SyncGroupCache.objects.filter(servicename="ipboard").delete() def disable_discord(): @@ -113,5 +138,349 @@ def disable_discord(): logger.info("Clearing %s Discord UID" % auth.user) auth.discord_uid = '' auth.save() - logger.info("Deleting all DiscordAuthToken models") - DiscordAuthToken.objects.all().delete() + + +def deactivate_services(user): + change = False + logger.debug("Deactivating services for user %s" % user) + authinfo = AuthServicesInfo.objects.get_or_create(user=user)[0] + if authinfo.mumble_username and authinfo.mumble_username != "": + logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.mumble_username)) + MumbleManager.delete_user(authinfo.mumble_username) + AuthServicesInfoManager.update_user_mumble_info("", user) + change = True + if authinfo.jabber_username and authinfo.jabber_username != "": + logger.debug("User %s has jabber account %s. Deleting." % (user, authinfo.jabber_username)) + OpenfireManager.delete_user(authinfo.jabber_username) + AuthServicesInfoManager.update_user_jabber_info("", user) + change = True + if authinfo.forum_username and authinfo.forum_username != "": + logger.debug("User %s has forum account %s. Deleting." % (user, authinfo.forum_username)) + Phpbb3Manager.disable_user(authinfo.forum_username) + AuthServicesInfoManager.update_user_forum_info("", user) + change = True + if authinfo.ipboard_username and authinfo.ipboard_username != "": + logger.debug("User %s has ipboard account %s. Deleting." % (user, authinfo.ipboard_username)) + IPBoardManager.disable_user(authinfo.ipboard_username) + AuthServicesInfoManager.update_user_ipboard_info("", user) + change = True + if authinfo.teamspeak3_uid and authinfo.teamspeak3_uid != "": + logger.debug("User %s has mumble account %s. Deleting." % (user, authinfo.teamspeak3_uid)) + Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) + AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) + change = True + if authinfo.discord_uid and authinfo.discord_uid != "": + logger.debug("User %s has discord account %s. Deleting." % (user, authinfo.discord_uid)) + DiscordOAuthManager.delete_user(authinfo.discord_uid) + AuthServicesInfoManager.update_user_discord_info("", user) + change = True + if authinfo.xenforo_username and authinfo.xenforo_password != "": + logger.debug("User %s has a XenForo account %s. Deleting." % (user, authinfo.xenforo_username)) + XenForoManager.disable_user(authinfo.xenforo_username) + AuthServicesInfoManager.update_user_xenforo_info("", user) + change = True + if authinfo.market_username and authinfo.market_username != "": + logger.debug("User %s has a Market account %s. Deleting." % (user, authinfo.market_username)) + marketManager.disable_user(authinfo.market_username) + AuthServicesInfoManager.update_user_market_info("", user) + change = True + if authinfo.discourse_username and authinfo.discourse_username != "": + logger.debug("User %s has a Discourse account %s. Deleting." % (user, authinfo.discourse_username)) + DiscourseManager.delete_user(authinfo.discourse_username) + AuthServicesInfoManager.update_user_discourse_info("", user) + change = True + if authinfo.smf_username and authinfo.smf_username != "": + logger.debug("User %s has a SMF account %s. Deleting." % (user, authinfo.smf_username)) + smfManager.disable_user(authinfo.smf_username) + AuthServicesInfoManager.update_user_smf_info("", user) + change = True + if change: + notify(user, "Services Disabled", message="Your services accounts have been disabled.", level="danger") + + +@task +def validate_services(user, state): + if state == MEMBER_STATE: + setting_string = 'AUTH' + elif state == BLUE_STATE: + setting_string = 'BLUE' + else: + deactivate_services(user) + return + logger.debug('Ensuring user %s services are available to state %s' % (user, state)) + auth = AuthServicesInfo.objects.get_or_create(user=user)[0] + if auth.mumble_username and not getattr(settings, 'ENABLE_%s_MUMBLE' % setting_string, False): + MumbleManager.delete_user(auth.mumble_username) + AuthServicesInfoManager.update_user_mumble_info("", user) + notify(user, 'Mumble Account Disabled', level='danger') + if auth.jabber_username and not getattr(settings, 'ENABLE_%s_JABBER' % setting_string, False): + OpenfireManager.delete_user(auth.jabber_username) + AuthServicesInfoManager.update_user_jabber_info("", user) + notify(user, 'Jabber Account Disabled', level='danger') + if auth.forum_username and not getattr(settings, 'ENABLE_%s_FORUM' % setting_string, False): + Phpbb3Manager.disable_user(auth.forum_username) + AuthServicesInfoManager.update_user_forum_info("", user) + notify(user, 'Forum Account Disabled', level='danger') + if auth.ipboard_username and not getattr(settings, 'ENABLE_%s_IPBOARD' % setting_string, False): + IPBoardManager.disable_user(auth.ipboard_username) + AuthServicesInfoManager.update_user_ipboard_info("", user) + notify(user, 'IPBoard Account Disabled', level='danger') + if auth.teamspeak3_uid and not getattr(settings, 'ENABLE_%s_TEAMSPEAK' % setting_string, False): + Teamspeak3Manager.delete_user(auth.teamspeak3_uid) + AuthServicesInfoManager.update_user_teamspeak3_info("", "", user) + notify(user, 'TeamSpeak3 Account Disabled', level='danger') + if auth.discord_uid and not getattr(settings, 'ENABLE_%s_DISCORD' % setting_string, False): + DiscordOAuthManager.delete_user(auth.discord_uid) + AuthServicesInfoManager.update_user_discord_info("", user) + notify(user, 'Discord Account Disabled', level='danger') + if auth.xenforo_username and not getattr(settings, 'ENABLE_%s_XENFORO' % setting_string, False): + XenForoManager.disable_user(auth.xenforo_username) + AuthServicesInfoManager.update_user_xenforo_info("", user) + notify(user, 'XenForo Account Disabled', level='danger') + if auth.market_username and not getattr(settings, 'ENABLE_%s_MARKET' % setting_string, False): + marketManager.disable_user(auth.market_username) + AuthServicesInfoManager.update_user_market_info("", user) + notify(user, 'Alliance Market Account Disabled', level='danger') + if auth.discourse_username and not getattr(settings, 'ENABLE_%s_DISCOURSE' % setting_string, False): + DiscourseManager.delete_user(auth.discourse_username) + AuthServicesInfoManager.update_user_discourse_info("", user) + notify(user, 'Discourse Account Disabled', level='danger') + if auth.smf_username and not getattr(settings, 'ENABLE_%s_SMF' % setting_string, False): + smfManager.disable_user(auth.smf_username) + AuthServicesInfoManager.update_user_smf_info(auth.smf_username, user) + notify(user, "SMF Account Disabled", level='danger') + + +@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, 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)) + try: + Teamspeak3Manager.update_groups(authserviceinfo.teamspeak3_uid, groups) + logger.debug("Updated user %s teamspeak3 groups." % user) + except TeamspeakError as e: + logger.error("Error occured while syncing TS groups for %s: %s" % (user, str(e))) + raise self.retry(countdown=60*10) + + +@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) diff --git a/services/views.py b/services/views.py index f931ab8f..79ba8cf4 100755 --- a/services/views.py +++ b/services/views.py @@ -1,52 +1,50 @@ -from django.template import RequestContext -from django.shortcuts import HttpResponseRedirect -from django.shortcuts import render_to_response +from __future__ import unicode_literals +from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.models import Group from django.conf import settings - +from django.contrib import messages from eveonline.models import EveCharacter from eveonline.models import EveAllianceInfo from authentication.models import AuthServicesInfo -from managers.openfire_manager import OpenfireManager -from managers.phpbb3_manager import Phpbb3Manager -from managers.mumble_manager import MumbleManager -from managers.ipboard_manager import IPBoardManager -from managers.xenforo_manager import XenForoManager -from managers.teamspeak3_manager import Teamspeak3Manager -from managers.discord_manager import DiscordOAuthManager -from managers.discourse_manager import DiscourseManager -from managers.ips4_manager import Ips4Manager -from managers.smf_manager import smfManager -from managers.market_manager import marketManager -from managers.pathfinder_manager import pathfinderManager +from services.managers.openfire_manager import OpenfireManager +from services.managers.phpbb3_manager import Phpbb3Manager +from services.managers.mumble_manager import MumbleManager +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.ips4_manager import Ips4Manager +from services.managers.smf_manager import smfManager +from services.managers.market_manager import marketManager from authentication.managers import AuthServicesInfoManager from eveonline.managers import EveManager -from celerytask.tasks import update_jabber_groups -from celerytask.tasks import update_mumble_groups -from celerytask.tasks import update_forum_groups -from celerytask.tasks import update_ipboard_groups -from celerytask.tasks import update_smf_groups -from celerytask.tasks import update_teamspeak3_groups -from celerytask.tasks import update_discord_groups -from celerytask.tasks import update_discord_nickname -from celerytask.tasks import update_discourse_groups -from forms import JabberBroadcastForm -from forms import FleetFormatterForm -from forms import DiscordForm -from forms import ServicePasswordForm -from forms import TeamspeakJoinForm -from util import check_if_user_has_permission +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 +from services.forms import JabberBroadcastForm +from services.forms import FleetFormatterForm +from services.forms import ServicePasswordForm +from services.forms import TeamspeakJoinForm +from authentication.decorators import members_and_blues +from authentication.states import MEMBER_STATE, BLUE_STATE -import threading -import datetime +import datetime import logging logger = logging.getLogger(__name__) + @login_required def fleet_formatter_view(request): logger.debug("fleet_formatter_view called by user %s" % request.user) @@ -74,15 +72,15 @@ def fleet_formatter_view(request): context = {'form': form, 'generated': generated} - return render_to_response('registered/fleetformattertool.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/fleetformattertool.html', context=context) + @login_required @permission_required('auth.jabber_broadcast') def jabber_broadcast_view(request): logger.debug("jabber_broadcast_view called by user %s" % request.user) - success = False allchoices = [] - if check_if_user_has_permission(request.user, 'jabber_broadcast_all'): + if request.user.has_perm('auth.jabber_broadcast_all'): allchoices.append(('all', 'all')) for g in Group.objects.all(): allchoices.append((str(g.name), str(g.name))) @@ -98,140 +96,204 @@ def jabber_broadcast_view(request): main_char = EveCharacter.objects.get(character_id=user_info.main_char_id) logger.debug("Processing jabber broadcast for user %s with main character %s" % (user_info, main_char)) if user_info.main_char_id != "": - message_to_send = form.cleaned_data['message'] + "\n##### SENT BY: " + "[" + main_char.corporation_ticker + "]" + main_char.character_name + " TO: " + form.cleaned_data['group'] + " WHEN: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + " #####\n##### Replies are NOT monitored #####\n" + message_to_send = form.cleaned_data[ + 'message'] + "\n##### SENT BY: " + "[" + main_char.corporation_ticker + "]" + \ + main_char.character_name + " TO: " + \ + form.cleaned_data['group'] + " WHEN: " + datetime.datetime.utcnow().strftime( + "%Y-%m-%d %H:%M:%S") + " #####\n##### Replies are NOT monitored #####\n" group_to_send = form.cleaned_data['group'] - OpenfireManager.send_broadcast_threaded(group_to_send, message_to_send,) + OpenfireManager.send_broadcast_threaded(group_to_send, message_to_send, ) else: - message_to_send = form.cleaned_data['message'] + "\n##### SENT BY: " + "No character but can send pings?" + " TO: " + form.cleaned_data['group'] + " WHEN: " + datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + " #####\n##### Replies are NOT monitored #####\n" + message_to_send = form.cleaned_data[ + 'message'] + "\n##### SENT BY: " + "No character but can send pings?" + " TO: " + \ + form.cleaned_data['group'] + " WHEN: " + datetime.datetime.utcnow().strftime( + "%Y-%m-%d %H:%M:%S") + " #####\n##### Replies are NOT monitored #####\n" group_to_send = form.cleaned_data['group'] - OpenfireManager.send_broadcast_threaded(group_to_send, message_to_send,) + OpenfireManager.send_broadcast_threaded(group_to_send, message_to_send, ) - success = True + messages.success(request, 'Sent jabber broadcast to %s' % group_to_send) logger.info("Sent jabber broadcast on behalf of user %s" % request.user) else: form = JabberBroadcastForm() form.fields['group'].choices = allchoices - logger.debug("Generated broadcast form for user %s containing %s groups" % (request.user, len(form.fields['group'].choices))) + logger.debug("Generated broadcast form for user %s containing %s groups" % ( + request.user, len(form.fields['group'].choices))) - context = {'form': form, 'success': success} - return render_to_response('registered/jabberbroadcast.html', context, context_instance=RequestContext(request)) + context = {'form': form} + return render(request, 'registered/jabberbroadcast.html', context=context) @login_required +@members_and_blues() def services_view(request): logger.debug("services_view called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + auth = AuthServicesInfo.objects.get_or_create(user=request.user)[0] - return render_to_response('registered/services.html', {'authinfo': authinfo}, - context_instance=RequestContext(request)) + services = [ + 'FORUM', + 'JABBER', + 'MUMBLE', + 'IPBOARD', + 'TEAMSPEAK3', + 'DISCORD', + 'DISCOURSE', + 'IPS4', + 'SMF', + 'MARKET', + 'XENFORO', + ] + context = {'authinfo': auth} + + for s in services: + context['SHOW_' + s] = (getattr(settings, 'ENABLE_AUTH_' + s) and ( + auth.state == MEMBER_STATE or request.user.is_superuser)) or (getattr(settings, 'ENABLE_BLUE_' + s) and ( + auth.state == BLUE_STATE or request.user.is_superuser)) + + return render(request, 'registered/services.html', context=context) -def service_blue_alliance_test(user): - return check_if_user_has_permission(user, 'member') or check_if_user_has_permission(user, 'blue_member') def superuser_test(user): return user.is_superuser + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_forum(request): logger.debug("activate_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] # Valid now we get the main characters character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding phpbb user for user %s with main character %s" % (request.user, character)) result = Phpbb3Manager.add_user(character.character_name, request.user.email, ['REGISTERED'], authinfo.main_char_id) # if empty we failed if result[0] != "": - AuthServicesInfoManager.update_user_forum_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_forum_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with forum credentials. Updating groups." % request.user) update_forum_groups.delay(request.user.pk) - logger.info("Succesfully activated forum for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate forum for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated forum for user %s" % request.user) + messages.success(request, 'Activated forum account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Forum'}) + else: + logger.error("Unsuccessful attempt to activate forum for user %s" % request.user) + messages.error(request, 'An error occurred while processing your forum account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_forum(request): logger.debug("deactivate_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Phpbb3Manager.disable_user(authinfo.forum_username) # false we failed if result: - AuthServicesInfoManager.update_user_forum_info("", "", request.user) - logger.info("Succesfully deactivated forum for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate forum for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_forum_info("", request.user) + logger.info("Successfully deactivated forum for user %s" % request.user) + messages.success(request, 'Deactivated forum account.') + else: + logger.error("Unsuccessful attempt to activate forum for user %s" % request.user) + messages.error(request, 'An error occurred while processing your forum account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_forum_password(request): logger.debug("reset_forum_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Phpbb3Manager.update_user_password(authinfo.forum_username, authinfo.main_char_id) # false we failed if result != "": - AuthServicesInfoManager.update_user_forum_info(authinfo.forum_username, result, request.user) - logger.info("Succesfully reset forum password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset forum password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset forum password for user %s" % request.user) + messages.success(request, 'Reset forum password.') + credentials = { + 'username': authinfo.forum_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Forum'}) + else: + logger.error("Unsuccessful attempt to reset forum password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your forum account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_xenforo_forum(request): logger.debug("activate_xenforo_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding XenForo user for user %s with main character %s" % (request.user, character)) result = XenForoManager.add_user(character.character_name, request.user.email) # Based on XenAPI's response codes if result['response']['status_code'] == 200: logger.info("Updated authserviceinfo for user %s with XenForo credentials. Updating groups." % request.user) - AuthServicesInfoManager.update_user_xenforo_info(result['username'], result['password'], request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate xenforo for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_xenforo_info(result['username'], request.user) + messages.success(request, 'Activated XenForo account.') + credentials = { + 'username': result['username'], + 'password': result['password'], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'XenForo'}) + + else: + logger.error("UnSuccessful attempt to activate xenforo for user %s" % request.user) + messages.error(request, 'An error occurred while processing your XenForo account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_xenforo_forum(request): logger.debug("deactivate_xenforo_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = XenForoManager.disable_user(authinfo.xenforo_username) if result.status_code == 200: - AuthServicesInfoManager.update_user_xenforo_info("", "", request.user) - logger.info("Succesfully deactivated XenForo for user %s" % request.user) - return HttpResponseRedirect("/services/") - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_xenforo_info("", request.user) + logger.info("Successfully deactivated XenForo for user %s" % request.user) + messages.success(request, 'Deactivated XenForo account.') + else: + messages.error(request, 'An error occurred while processing your XenForo account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_xenforo_password(request): logger.debug("reset_xenforo_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - character = EveManager.get_character_by_id(authinfo.main_char_id) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = XenForoManager.reset_password(authinfo.xenforo_username) # Based on XenAPI's response codes if result['response']['status_code'] == 200: - AuthServicesInfoManager.update_user_xenforo_info(authinfo.xenforo_username, result['password'], request.user) - logger.info("Succesfully reset XenForo password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset XenForo password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset XenForo password for user %s" % request.user) + messages.success(request, 'Reset XenForo account password.') + credentials = { + 'username': authinfo.xenforo_username, + 'password': result['password'], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'XenForo'}) + else: + logger.error("Unsuccessful attempt to reset XenForo password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your XenForo account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_xenforo_password(request): logger.debug("set_xenforo_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -239,131 +301,165 @@ def set_xenforo_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = XenForoManager.update_user_password(authinfo.xenforo_username, password) if result['response']['status_code'] == 200: - AuthServicesInfoManager.update_user_xenforo_info(authinfo.xenforo_username, result['password'], request.user) - logger.info("Succesfully reset XenForo password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully reset XenForo password for user %s" % request.user) + messages.success(request, 'Changed XenForo password.') else: logger.error("Failed to install custom XenForo password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your XenForo account.') + return redirect('auth_services') else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'Forum'} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_ipboard_forum(request): logger.debug("activate_ipboard_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] # Valid now we get the main characters character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding ipboard user for user %s with main character %s" % (request.user, character)) result = IPBoardManager.add_user(character.character_name, request.user.email) if result[0] != "": - AuthServicesInfoManager.update_user_ipboard_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_ipboard_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with ipboard credentials. Updating groups." % request.user) update_ipboard_groups.delay(request.user.pk) - logger.info("Succesfully activated ipboard for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate ipboard for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated ipboard for user %s" % request.user) + messages.success(request, 'Activated IPBoard account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'IPBoard'}) + else: + logger.error("UnSuccessful attempt to activate ipboard for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPBoard account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_ipboard_forum(request): logger.debug("deactivate_ipboard_forum called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = IPBoardManager.disable_user(authinfo.ipboard_username) # false we failed if result: - AuthServicesInfoManager.update_user_ipboard_info("", "", request.user) - logger.info("Succesfully deactivated ipboard for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to deactviate ipboard for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_ipboard_info("", request.user) + logger.info("Successfully deactivated ipboard for user %s" % request.user) + messages.success(request, 'Deactivated IPBoard account.') + else: + logger.error("Unsuccessful attempt to deactviate ipboard for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPBoard account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_ipboard_password(request): logger.debug("reset_ipboard_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = IPBoardManager.update_user_password(authinfo.ipboard_username, request.user.email) if result != "": - AuthServicesInfoManager.update_user_ipboard_info(authinfo.ipboard_username, result, request.user) - logger.info("Succesfully reset ipboard password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to reset ipboard password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset ipboard password for user %s" % request.user) + messages.success(request, 'Reset IPBoard password.') + credentials = { + 'username': authinfo.ipboard_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'IPBoard'}) + else: + logger.error("UnSuccessful attempt to reset ipboard password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPBoard account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_jabber(request): logger.debug("activate_jabber called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding jabber user for user %s with main character %s" % (request.user, character)) info = OpenfireManager.add_user(character.character_name) # If our username is blank means we already had a user if info[0] is not "": - AuthServicesInfoManager.update_user_jabber_info(info[0], info[1], request.user) + AuthServicesInfoManager.update_user_jabber_info(info[0], request.user) logger.debug("Updated authserviceinfo for user %s with jabber credentials. Updating groups." % request.user) update_jabber_groups.delay(request.user.pk) - logger.info("Succesfully activated jabber for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate jabber for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated jabber for user %s" % request.user) + messages.success(request, 'Activated jabber account.') + credentials = { + 'username': info[0], + 'password': info[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Jabber'}) + else: + logger.error("UnSuccessful attempt to activate jabber for user %s" % request.user) + messages.error(request, 'An error occurred while processing your jabber account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_jabber(request): logger.debug("deactivate_jabber called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = OpenfireManager.delete_user(authinfo.jabber_username) # If our username is blank means we failed if result: - AuthServicesInfoManager.update_user_jabber_info("", "", request.user) - logger.info("Succesfully deactivated jabber for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to deactivate jabber for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_jabber_info("", request.user) + logger.info("Successfully deactivated jabber for user %s" % request.user) + messages.success(request, 'Deactivated jabber account.') + else: + logger.error("UnSuccessful attempt to deactivate jabber for user %s" % request.user) + messages.error(request, 'An error occurred while processing your jabber account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_jabber_password(request): logger.debug("reset_jabber_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = OpenfireManager.update_user_pass(authinfo.jabber_username) # If our username is blank means we failed if result != "": - AuthServicesInfoManager.update_user_jabber_info(authinfo.jabber_username, result, request.user) - logger.info("Succesfully reset jabber password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset jabber for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_jabber_info(authinfo.jabber_username, request.user) + logger.info("Successfully reset jabber password for user %s" % request.user) + messages.success(request, 'Reset jabber password.') + credentials = { + 'username': authinfo.jabber_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Jabber'}) + else: + logger.error("Unsuccessful attempt to reset jabber for user %s" % request.user) + messages.error(request, 'An error occurred while processing your jabber account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_mumble(request): logger.debug("activate_mumble called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) ticker = character.corporation_ticker - if check_if_user_has_permission(request.user, "blue_member"): + if authinfo.state == BLUE_STATE: logger.debug("Adding mumble user for blue user %s with main character %s" % (request.user, character)) # Blue members should have alliance ticker (if in alliance) if EveAllianceInfo.objects.filter(alliance_id=character.alliance_id).exists(): @@ -375,55 +471,72 @@ def activate_mumble(request): result = MumbleManager.create_user(ticker, character.character_name) # if its empty we failed if result[0] is not "": - AuthServicesInfoManager.update_user_mumble_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_mumble_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with mumble credentials. Updating groups." % request.user) update_mumble_groups.delay(request.user.pk) - logger.info("Succesfully activated mumble for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to activate mumble for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated mumble for user %s" % request.user) + messages.success(request, 'Activated Mumble account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Mumble'}) + else: + logger.error("Unsuccessful attempt to activate mumble for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Mumble account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_mumble(request): logger.debug("deactivate_mumble called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = MumbleManager.delete_user(authinfo.mumble_username) # if false we failed if result: - AuthServicesInfoManager.update_user_mumble_info("", "", request.user) - logger.info("Succesfully deactivated mumble for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to deactivate mumble for user %s" % request.user) - return HttpResponseRedirect("/") + AuthServicesInfoManager.update_user_mumble_info("", request.user) + logger.info("Successfully deactivated mumble for user %s" % request.user) + messages.success(request, 'Deactivated Mumble account.') + else: + logger.error("Unsuccessful attempt to deactivate mumble for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Mumble account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_mumble_password(request): logger.debug("reset_mumble_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = MumbleManager.update_user_password(authinfo.mumble_username) # if blank we failed if result != "": - AuthServicesInfoManager.update_user_mumble_info(authinfo.mumble_username, result, request.user) - logger.info("Succesfully reset mumble password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to reset mumble password for user %s" % request.user) - return HttpResponseRedirect("/") + logger.info("Successfully reset mumble password for user %s" % request.user) + messages.success(request, 'Reset Mumble password.') + credentials = { + 'username': authinfo.mumble_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Mumble'}) + else: + logger.error("UnSuccessful attempt to reset mumble password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Mumble account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_teamspeak3(request): logger.debug("activate_teamspeak3 called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) ticker = character.corporation_ticker - if check_if_user_has_permission(request.user, "blue_member"): + if authinfo.state == BLUE_STATE: logger.debug("Adding TS3 user for blue user %s with main character %s" % (request.user, character)) # Blue members should have alliance ticker (if in alliance) if EveAllianceInfo.objects.filter(alliance_id=character.alliance_id).exists(): @@ -438,60 +551,67 @@ def activate_teamspeak3(request): if result[0] is not "": AuthServicesInfoManager.update_user_teamspeak3_info(result[0], result[1], request.user) logger.debug("Updated authserviceinfo for user %s with TS3 credentials. Updating groups." % request.user) - logger.info("Succesfully activated TS3 for user %s" % request.user) - return HttpResponseRedirect("/verify_teamspeak3/") + logger.info("Successfully activated TS3 for user %s" % request.user) + messages.success(request, 'Activated TeamSpeak3 account.') + return redirect("auth_verify_teamspeak3") logger.error("Unsuccessful attempt to activate TS3 for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + messages.error(request, 'An error occurred while processing your TeamSpeak3 account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def verify_teamspeak3(request): logger.debug("verify_teamspeak3 called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] if not authinfo.teamspeak3_uid: logger.warn("Unable to validate user %s teamspeak: no teamspeak data" % request.user) - return HttpResponseRedirect("/services") + return redirect("auth_services") if request.method == "POST": form = TeamspeakJoinForm(request.POST) if form.is_valid(): update_teamspeak3_groups.delay(request.user.pk) logger.debug("Validated user %s joined TS server" % request.user) - return HttpResponseRedirect("/services/") + return redirect("auth_services") else: - form = TeamspeakJoinForm({'username':authinfo.teamspeak3_uid}) + form = TeamspeakJoinForm({'username': authinfo.teamspeak3_uid}) context = { 'form': form, 'authinfo': authinfo, } - return render_to_response('registered/teamspeakjoin.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/teamspeakjoin.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_teamspeak3(request): logger.debug("deactivate_teamspeak3 called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) # if false we failed if result: AuthServicesInfoManager.update_user_teamspeak3_info("", "", request.user) - logger.info("Succesfully deactivated TS3 for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to deactivate TS3 for user %s" % request.user) - return HttpResponseRedirect("/") + logger.info("Successfully deactivated TS3 for user %s" % request.user) + messages.success(request, 'Deactivated TeamSpeak3 account.') + else: + logger.error("Unsuccessful attempt to deactivate TS3 for user %s" % request.user) + messages.error(request, 'An error occurred while processing your TeamSpeak3 account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_teamspeak3_perm(request): logger.debug("reset_teamspeak3_perm called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Deleting TS3 user for user %s" % request.user) Teamspeak3Manager.delete_user(authinfo.teamspeak3_uid) - if check_if_user_has_permission(request.user, "blue_member"): - logger.debug("Generating new permission key for blue user %s with main character %s" % (request.user, character)) + if authinfo.state == BLUE_STATE: + logger.debug( + "Generating new permission key for blue user %s with main character %s" % (request.user, character)) result = Teamspeak3Manager.generate_new_blue_permissionkey(authinfo.teamspeak3_uid, character.character_name, character.corporation_ticker) else: @@ -505,78 +625,83 @@ def reset_teamspeak3_perm(request): logger.debug("Updated authserviceinfo for user %s with TS3 credentials. Updating groups." % request.user) update_teamspeak3_groups.delay(request.user) logger.info("Successfully reset TS3 permission key for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user) - return HttpResponseRedirect("/") + messages.success(request, 'Reset TeamSpeak3 permission key.') + else: + logger.error("Unsuccessful attempt to reset TS3 permission key for user %s" % request.user) + messages.error(request, 'An error occurred while processing your TeamSpeak3 account.') + return redirect("auth_services") + @login_required -def fleet_fits(request): - logger.debug("fleet_fits called by user %s" % request.user) - context = {} - return render_to_response('registered/fleetfits.html', context, -context_instance=RequestContext(request)) - -@login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_discord(request): logger.debug("deactivate_discord called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = DiscordOAuthManager.delete_user(authinfo.discord_uid) if result: AuthServicesInfoManager.update_user_discord_info("", request.user) - logger.info("Succesfully deactivated discord for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to deactivate discord for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully deactivated discord for user %s" % request.user) + messages.success(request, 'Deactivated Discord account.') + else: + logger.error("UnSuccessful attempt to deactivate discord for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Discord account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_discord(request): logger.debug("reset_discord called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = DiscordOAuthManager.delete_user(authinfo.discord_uid) if result: - AuthServicesInfoManager.update_user_discord_info("",request.user) - logger.info("Succesfully deleted discord user for user %s - forwarding to discord activation." % request.user) - return HttpResponseRedirect("/activate_discord/") + AuthServicesInfoManager.update_user_discord_info("", request.user) + logger.info("Successfully deleted discord user for user %s - forwarding to discord activation." % request.user) + return redirect("auth_activate_discord") logger.error("Unsuccessful attempt to reset discord for user %s" % request.user) - return HttpResponseRedirect("/services/") + messages.error(request, 'An error occurred while processing your Discord account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_discord(request): logger.debug("activate_discord called by user %s" % request.user) - return HttpResponseRedirect(DiscordOAuthManager.generate_oauth_redirect_url()) + return redirect(DiscordOAuthManager.generate_oauth_redirect_url()) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def discord_callback(request): logger.debug("Received Discord callback for activation of user %s" % request.user) code = request.GET.get('code', None) if not code: logger.warn("Did not receive OAuth code from callback of user %s" % request.user) - return HttpResponseRedirect("/services/") + return redirect("auth_services") user_id = DiscordOAuthManager.add_user(code) if user_id: AuthServicesInfoManager.update_user_discord_info(user_id, request.user) - if (settings.DISCORD_SYNC_NAMES): + if settings.DISCORD_SYNC_NAMES: update_discord_nickname.delay(request.user.pk) update_discord_groups.delay(request.user.pk) - logger.info("Succesfully activated Discord for user %s" % request.user) + logger.info("Successfully activated Discord for user %s" % request.user) + messages.success(request, 'Activated Discord account.') else: logger.error("Failed to activate Discord for user %s" % request.user) - return HttpResponseRedirect("/services/") + messages.error(request, 'An error occurred while processing your Discord account.') + return redirect("auth_services") + @login_required @user_passes_test(superuser_test) def discord_add_bot(request): - return HttpResponseRedirect(DiscordOAuthManager.generate_bot_add_url()) + return redirect(DiscordOAuthManager.generate_bot_add_url()) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_forum_password(request): logger.debug("set_forum_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -584,30 +709,29 @@ def set_forum_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = Phpbb3Manager.update_user_password(authinfo.forum_username, authinfo.main_char_id, password=password) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] + result = Phpbb3Manager.update_user_password(authinfo.forum_username, authinfo.main_char_id, + password=password) if result != "": - AuthServicesInfoManager.update_user_forum_info(authinfo.forum_username, result, request.user) - logger.info("Succesfully reset forum password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully set forum password for user %s" % request.user) + messages.success('Set forum password.') else: logger.error("Failed to install custom forum password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your forum account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'Forum'} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_mumble_password(request): logger.debug("set_mumble_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -615,30 +739,28 @@ def set_mumble_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = MumbleManager.update_user_password(authinfo.mumble_username, password=password) if result != "": - AuthServicesInfoManager.update_user_mumble_info(authinfo.mumble_username, result, request.user) - logger.info("Succesfully reset forum password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully reset forum password for user %s" % request.user) + messages.success(request, 'Set Mumble password.') else: logger.error("Failed to install custom mumble password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your Mumble account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) - context = {'form': form, 'service': 'Mumble', 'error': error} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + context = {'form': form, 'service': 'Mumble'} + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_jabber_password(request): logger.debug("set_jabber_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -646,27 +768,26 @@ def set_jabber_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = OpenfireManager.update_user_pass(authinfo.jabber_username, password=password) if result != "": - AuthServicesInfoManager.update_user_jabber_info(authinfo.jabber_username, result, request.user) - logger.info("Succesfully reset forum password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully set jabber password for user %s" % request.user) + messages.success(request, 'Set jabber password.') else: logger.error("Failed to install custom jabber password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your jabber account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) - context = {'form': form, 'service': 'Jabber', 'error': error} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + context = {'form': form, 'service': 'Jabber'} + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_ipboard_password(request): logger.debug("set_ipboard_password called by user %s" % request.user) error = None @@ -677,95 +798,122 @@ def set_ipboard_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = IPBoardManager.update_user_password(authinfo.ipboard_username, request.user.email, plain_password=password) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] + result = IPBoardManager.update_user_password(authinfo.ipboard_username, request.user.email, + plain_password=password) if result != "": - AuthServicesInfoManager.update_user_ipboard_info(authinfo.ipboard_username, result, request.user) - logger.info("Succesfully reset forum password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully set IPBoard password for user %s" % request.user) + messages.success(request, 'Set IPBoard password.') else: logger.error("Failed to install custom ipboard password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your IPBoard account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'IPBoard', 'error': error} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) - + return render(request, 'registered/service_password.html', context=context) + + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_discourse(request): logger.debug("activate_discourse called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding discourse user for user %s with main character %s" % (request.user, character)) result = DiscourseManager.add_user(character.character_name, request.user.email) if result[0] != "": - AuthServicesInfoManager.update_user_discourse_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_discourse_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with discourse credentials. Updating groups." % request.user) update_discourse_groups.delay(request.user.pk) logger.info("Successfully activated discourse for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to activate forum for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + messages.success('Activated Discourse account.') + messages.warning('Do not lose your Discourse password. It cannot be reset through auth.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Discourse'}) + else: + logger.error("Unsuccessful attempt to activate forum for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Discourse account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_discourse(request): logger.debug("deactivate_discourse called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = DiscourseManager.delete_user(authinfo.discourse_username) if result: - AuthServicesInfoManager.update_user_discourse_info("", "", request.user) + AuthServicesInfoManager.update_user_discourse_info("", request.user) logger.info("Successfully deactivated discourse for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to activate discourse for user %s" % request.user) - return HttpResponseRedirect("/dashboard") - + messages.success('Deactivated Discourse account.') + else: + logger.error("Unsuccessful attempt to activate discourse for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Discourse account.') + return redirect("auth_services") + + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_ips4(request): logger.debug("activate_ips4 called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] # Valid now we get the main characters character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding IPS4 user for user %s with main character %s" % (request.user, character)) result = Ips4Manager.add_user(character.character_name, request.user.email) # if empty we failed if result[0] != "": - AuthServicesInfoManager.update_user_ips4_info(result[0], result[1], result[2], request.user) + AuthServicesInfoManager.update_user_ips4_info(result[0], result[2], request.user) logger.debug("Updated authserviceinfo for user %s with IPS4 credentials." % request.user) - #update_ips4_groups.delay(request.user.pk) - logger.info("Succesfully activated IPS4 for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate IPS4 for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + # update_ips4_groups.delay(request.user.pk) + logger.info("Successfully activated IPS4 for user %s" % request.user) + messages.success(request, 'Activated IPSuite4 account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'IPSuite4'}) + else: + logger.error("UnSuccessful attempt to activate IPS4 for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPSuite4 account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_ips4_password(request): logger.debug("reset_ips4_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Ips4Manager.update_user_password(authinfo.ips4_username) - member_id = Ips4Manager.get_user_id(authinfo.ips4_username) # false we failed if result != "": - AuthServicesInfoManager.update_user_ips4_info(authinfo.ips4_username, result, member_id, request.user) - logger.info("Succesfully reset IPS4 password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset IPS4 password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset IPS4 password for user %s" % request.user) + messages.success(request, 'Reset IPSuite4 password.') + credentials = { + 'username': authinfo.ips4_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'IPSuite4'}) + else: + logger.error("Unsuccessful attempt to reset IPS4 password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPSuite4 account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_ips4_password(request): logger.debug("set_ips4_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -773,93 +921,111 @@ def set_ips4_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Ips4Manager.update_custom_password(authinfo.ips4_username, plain_password=password) - member_id = Ips4Manager.get_user_id(authinfo.ips4_username) if result != "": - AuthServicesInfoManager.update_user_ips4_info(authinfo.ips4_username, result, member_id, request.user) - logger.info("Succesfully reset IPS4 password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully set IPS4 password for user %s" % request.user) + messages.success(request, 'Set IPSuite4 password.') else: logger.error("Failed to install custom IPS4 password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your IPSuite4 account.') + return redirect('auth_services') else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) - context = {'form': form, 'service': 'IPS4', 'error': error} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + context = {'form': form, 'service': 'IPS4'} + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_ips4(request): logger.debug("deactivate_ips4 called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = Ips4Manager.delete_user(authinfo.ips4_id) if result != "": - AuthServicesInfoManager.update_user_ips4_info("", "", "", request.user) - logger.info("Succesfully deactivated IPS4 for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to deactivate IPS4 for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_ips4_info("", "", request.user) + logger.info("Successfully deactivated IPS4 for user %s" % request.user) + messages.success(request, 'Deactivated IPSuite4 account.') + else: + logger.error("UnSuccessful attempt to deactivate IPS4 for user %s" % request.user) + messages.error(request, 'An error occurred while processing your IPSuite4 account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_smf(request): logger.debug("activate_smf called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] # Valid now we get the main characters character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding smf user for user %s with main character %s" % (request.user, character)) result = smfManager.add_user(character.character_name, request.user.email, ['Member'], authinfo.main_char_id) # if empty we failed if result[0] != "": - AuthServicesInfoManager.update_user_smf_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_smf_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with smf credentials. Updating groups." % request.user) update_smf_groups.delay(request.user.pk) - logger.info("Succesfully activated smf for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate smf for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated smf for user %s" % request.user) + messages.success(request, 'Activated SMF account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'SMF'}) + else: + logger.error("UnSuccessful attempt to activate smf for user %s" % request.user) + messages.error(request, 'An error occurred while processing your SMF account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_smf(request): logger.debug("deactivate_smf called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = smfManager.disable_user(authinfo.smf_username) # false we failed if result: - AuthServicesInfoManager.update_user_smf_info("", "", request.user) - logger.info("Succesfully deactivated smf for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate smf for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_smf_info("", request.user) + logger.info("Successfully deactivated smf for user %s" % request.user) + messages.success(request, 'Deactivated SMF account.') + else: + logger.error("UnSuccessful attempt to activate smf for user %s" % request.user) + messages.error(request, 'An error occurred while processing your SMF account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_smf_password(request): logger.debug("reset_smf_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = smfManager.update_user_password(authinfo.smf_username, authinfo.main_char_id) # false we failed if result != "": - AuthServicesInfoManager.update_user_smf_info(authinfo.smf_username, result, request.user) - logger.info("Succesfully reset smf password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset smf password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset smf password for user %s" % request.user) + messages.success(request, 'Reset SMF password.') + credentials = { + 'username': authinfo.smf_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'SMF'}) + else: + logger.error("Unsuccessful attempt to reset smf password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your SMF account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_smf_password(request): logger.debug("set_smf_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -867,78 +1033,95 @@ def set_smf_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = smfManager.update_user_password(authinfo.smf_username, authinfo.main_char_id, password=password) if result != "": - AuthServicesInfoManager.update_user_smf_info(authinfo.smf_username, result, request.user) - logger.info("Succesfully reset smf password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully set smf password for user %s" % request.user) + messages.success(request, 'Set SMF password.') else: logger.error("Failed to install custom smf password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your SMF account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'SMF'} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/service_password.html', context=context) + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def activate_market(request): logger.debug("activate_market called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] # Valid now we get the main characters character = EveManager.get_character_by_id(authinfo.main_char_id) logger.debug("Adding market user for user %s with main character %s" % (request.user, character)) - result = marketManager.add_user(character.character_name, request.user.email, authinfo.main_char_id, character.character_name) + result = marketManager.add_user(character.character_name, request.user.email, authinfo.main_char_id, + character.character_name) # if empty we failed if result[0] != "": - AuthServicesInfoManager.update_user_market_info(result[0], result[1], request.user) + AuthServicesInfoManager.update_user_market_info(result[0], request.user) logger.debug("Updated authserviceinfo for user %s with market credentials." % request.user) - logger.info("Succesfully activated market for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate market for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully activated market for user %s" % request.user) + messages.success(request, 'Activated Alliance Market account.') + credentials = { + 'username': result[0], + 'password': result[1], + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Alliance Market'}) + else: + logger.error("UnSuccessful attempt to activate market for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Alliance Market account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def deactivate_market(request): logger.debug("deactivate_market called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = marketManager.disable_user(authinfo.market_username) # false we failed if result: - AuthServicesInfoManager.update_user_market_info("", "", request.user) - logger.info("Succesfully deactivated market for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate market for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + AuthServicesInfoManager.update_user_market_info("", request.user) + logger.info("Successfully deactivated market for user %s" % request.user) + messages.success(request, 'Deactivated Alliance Market account.') + else: + logger.error("UnSuccessful attempt to activate market for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Alliance Market account.') + return redirect("auth_services") @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def reset_market_password(request): logger.debug("reset_market_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = marketManager.update_user_password(authinfo.market_username) # false we failed if result != "": - AuthServicesInfoManager.update_user_market_info(authinfo.market_username, result, request.user) - logger.info("Succesfully reset market password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset market password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") + logger.info("Successfully reset market password for user %s" % request.user) + messages.success(request, 'Reset Alliance Market password.') + credentials = { + 'username': authinfo.market_username, + 'password': result, + } + return render(request, 'registered/service_credentials.html', + context={'credentials': credentials, 'service': 'Alliance Market'}) + else: + logger.error("Unsuccessful attempt to reset market password for user %s" % request.user) + messages.error(request, 'An error occurred while processing your Alliance Market account.') + return redirect("auth_services") + @login_required -@user_passes_test(service_blue_alliance_test) +@members_and_blues() def set_market_password(request): logger.debug("set_market_password called by user %s" % request.user) - error = None if request.method == 'POST': logger.debug("Received POST request with form.") form = ServicePasswordForm(request.POST) @@ -946,100 +1129,19 @@ def set_market_password(request): if form.is_valid(): password = form.cleaned_data['password'] logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] result = marketManager.update_custom_password(authinfo.market_username, password) if result != "": - AuthServicesInfoManager.update_user_market_info(authinfo.market_username, result, request.user) - logger.info("Succesfully reset market password for user %s" % request.user) - return HttpResponseRedirect("/services/") + logger.info("Successfully reset market password for user %s" % request.user) + messages.success(request, 'Set Alliance Market password.') else: logger.error("Failed to install custom market password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" + messages.error(request, 'An error occurred while processing your Alliance Market account.') + return redirect("auth_services") else: logger.debug("Request is not type POST - providing empty form.") form = ServicePasswordForm() logger.debug("Rendering form for user %s" % request.user) context = {'form': form, 'service': 'Market'} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) - -@login_required -@user_passes_test(service_blue_alliance_test) -def activate_pathfinder(request): - logger.debug("activate_pathfinder called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - # Valid now we get the main characters - character = EveManager.get_character_by_id(authinfo.main_char_id) - logger.debug("Adding pathfinder for user %s with main character %s" % (request.user, character)) - result = pathfinderManager.add_user(character.character_name, request.user.email, character.character_name) - # if empty we failed - if result[0] != "": - AuthServicesInfoManager.update_user_pathfinder_info(result[0], result[1], request.user) - logger.debug("Updated authserviceinfo for user %s with pathfinder credentials." % request.user) - logger.info("Succesfully activated pathfinder for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate pathfinder for user %s" % request.user) - return HttpResponseRedirect("/dashboard") - - -@login_required -@user_passes_test(service_blue_alliance_test) -def deactivate_pathfinder(request): - logger.debug("deactivate_pathfinder called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = pathfinderManager.disable_user(authinfo.pathfinder_username) - # false we failed - if result: - AuthServicesInfoManager.update_user_pathfinder_info("", "", request.user) - logger.info("Succesfully deactivated pathfinder for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccesful attempt to activate pathfinder for user %s" % request.user) - return HttpResponseRedirect("/dashboard") - - -@login_required -@user_passes_test(service_blue_alliance_test) -def reset_pathfinder_password(request): - logger.debug("reset_pathfinder_password called by user %s" % request.user) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = pathfinderManager.update_user_info(authinfo.pathfinder_username) - # false we failed - if result != "": - AuthServicesInfoManager.update_user_pathfinder_info(authinfo.pathfinder_username, result[1], request.user) - logger.info("Succesfully reset pathfinder password for user %s" % request.user) - return HttpResponseRedirect("/services/") - logger.error("Unsuccessful attempt to reset pathfinder password for user %s" % request.user) - return HttpResponseRedirect("/dashboard") - -@login_required -@user_passes_test(service_blue_alliance_test) -def set_pathfinder_password(request): - logger.debug("set_pathfinder_password called by user %s" % request.user) - error = None - if request.method == 'POST': - logger.debug("Received POST request with form.") - form = ServicePasswordForm(request.POST) - logger.debug("Form is valid: %s" % form.is_valid()) - if form.is_valid(): - password = form.cleaned_data['password'] - logger.debug("Form contains password of length %s" % len(password)) - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) - result = pathfinderManager.update_custom_password(authinfo.pathfinder_username, password) - if result != "": - AuthServicesInfoManager.update_user_pathfinder_info(authinfo.pathfinder_username, result, request.user) - logger.info("Succesfully reset pathfinder password for user %s" % request.user) - return HttpResponseRedirect("/services/") - else: - logger.error("Failed to install custom pathfinder password for user %s" % request.user) - error = "Failed to install custom password." - else: - error = "Invalid password provided" - else: - logger.debug("Request is not type POST - providing empty form.") - form = ServicePasswordForm() - - logger.debug("Rendering form for user %s" % request.user) - context = {'form': form, 'service': 'Pathfinder'} - return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/service_password.html', context=context) diff --git a/sigtracker/admin.py b/sigtracker/admin.py deleted file mode 100644 index 00541e4f..00000000 --- a/sigtracker/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.contrib import admin - -from models import sigtracker - -admin.site.register(sigtracker) -# Register your models here. diff --git a/sigtracker/form.py b/sigtracker/form.py deleted file mode 100644 index 7817a581..00000000 --- a/sigtracker/form.py +++ /dev/null @@ -1,26 +0,0 @@ -from django import forms -from django.core.validators import MaxValueValidator, MinValueValidator -from django.utils.translation import ugettext_lazy as _ - - -class SignatureForm(forms.Form): - mass_status = [(_('More Than 50%'), _('More Than 50%')), (_('Less Than 50%'), _('Less Than 50%')), (_('Less Than 10%'), _('Less Than 10%'))] - lifetime_status = [(_('More Than 24 Hours'), _('More Than 24 Hours')), (_('Less Than 24 Hours'), _('Less Than 24 Hours')), (_('Less Than 4 Hours'), _('Less Than 4 Hours'))] - ships_size = [(_('Only Smallest'), _('Only Smallest')), (_('Up to Medium'), _('Up to Medium')), (_('Larger'), _('Larger')), (_('Very Large'), _('Very Large'))] - - - system = forms.CharField(max_length=254, required=True, label=_('System')) - ident = forms.CharField(max_length=254, required=True, label=_("ID")) - lifetime_status = forms.ChoiceField(choices=lifetime_status, required=True, label=_("Lifetime Status")) - mass_status = forms.ChoiceField(choices=mass_status, required=True, label=_("Mass Status")) - ships_size = forms.ChoiceField(choices=ships_size, required=True, label=_("Ship Size")) - destination = forms.CharField(max_length=254, label=_("End Destination"), required=True, initial="") - through_dest = forms.CharField(max_length=254, label=_("Goes Through"), required=True, initial="") - notes = forms.CharField(max_length=254, label=_("Notes"), required=False, initial="") - - - - - - - diff --git a/sigtracker/models.py b/sigtracker/models.py deleted file mode 100644 index 03c3c344..00000000 --- a/sigtracker/models.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.db import models -from django.contrib.auth.models import User -from django.utils import timezone -from eveonline.models import EveCharacter -from eveonline.models import EveCorporationInfo - - -class sigtracker(models.Model): - class Meta: - ordering = ['post_time'] - ident = models.CharField(max_length=254, default="") - system = models.CharField(max_length=254, default="") - destination = models.CharField(max_length=254, default="") - lifetime_status = models.CharField(max_length=254, default="") - mass_status = models.CharField(max_length=254, default="") - ships_size = models.CharField(max_length=254, default="") - notes = models.CharField(max_length=254, default="") - through_dest = models.CharField(max_length=254, default="") - post_time = models.DateTimeField(default=timezone.now) - eve_character = models.ForeignKey(EveCharacter) - - diff --git a/sigtracker/tests.py b/sigtracker/tests.py deleted file mode 100644 index a39b155a..00000000 --- a/sigtracker/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/sigtracker/views.py b/sigtracker/views.py deleted file mode 100644 index fbe12599..00000000 --- a/sigtracker/views.py +++ /dev/null @@ -1,122 +0,0 @@ -from django.http import HttpResponseRedirect -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.contrib.auth.decorators import login_required -from django.contrib.auth.decorators import permission_required -from django.contrib.auth.decorators import user_passes_test -from django.shortcuts import get_object_or_404 -from django.utils import timezone - -from util import check_if_user_has_permission -from authentication.managers import AuthServicesInfoManager -from eveonline.managers import EveManager -from form import SignatureForm -from models import sigtracker - - -import logging - -logger = logging.getLogger(__name__) - -def sigtracker_util_test(user): - return check_if_user_has_permission(user, 'member') or check_if_user_has_permission(user, 'blue_member') - - -@login_required -@user_passes_test(sigtracker_util_test) -@permission_required('auth.signature_view') -def sigtracker_view(request): - logger.info("sigtracker_view called by user %s" % request.user) - sigtracker_list = sigtracker.objects.all() - render_items = {'sigtracker': sigtracker.objects.all(),} - - return render_to_response('registered/signaturemanagement.html', render_items, context_instance=RequestContext(request)) - - -@login_required -@permission_required('auth.signature_management') -def add_signature_view(request): - logger.info("add_signature_view called by user %s" % request.user) - if request.method == 'POST': - form = SignatureForm(request.POST) - logger.info("Request type POST contains form valid: %s" % form.is_valid()) - if form.is_valid(): - #Get Current Time - post_time = timezone.now() - # Get character - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) - character = EveManager.get_character_by_id(auth_info.main_char_id) - # handle valid form - sig = sigtracker() - sig.ident = form.cleaned_data['ident'] - sig.system = form.cleaned_data['system'] - sig.destination = form.cleaned_data['destination'] - sig.lifetime_status = form.cleaned_data['lifetime_status'] - sig.mass_status = form.cleaned_data['mass_status'] - sig.ships_size = form.cleaned_data['ships_size'] - sig.through_dest = form.cleaned_data['through_dest'] - sig.notes = form.cleaned_data['notes'] - sig.create_time = post_time - sig.eve_character = character - sig.save() - return HttpResponseRedirect("/sigtracker/") - else: - logger.info("Returning new SignatureForm") - form = SignatureForm() - - render_items = {'form': form} - - return render_to_response('registered/addsignature.html', render_items, context_instance=RequestContext(request)) - - -@login_required -@permission_required('auth.signature_management') -def remove_signature(request, sigtracker_id): - logger.info("remove_signature called by user %s for signature id %s" % (request.user, sigtracker_id)) - if sigtracker.objects.filter(id=sigtracker_id).exists(): - sig = sigtracker.objects.get(id=sigtracker_id) - sig.delete() - logger.info("Deleting sigtracker id %s by user %s" % (sigtracker_id, request.user)) - else: - logger.info("Unable to delete signature id %s for user %s - signature matching id not found." % (sigtracker_id, request.user)) - return HttpResponseRedirect("/sigtracker/") - - -@login_required -@permission_required('auth.signature_management') -def edit_signature(request, sigtracker_id): - logger.debug("edit_optimer called by user %s for optimer id %s" % (request.user, sigtracker_id)) - sig = get_object_or_404(sigtracker, id=sigtracker_id) - if request.method == 'POST': - form = SignatureForm(request.POST) - logger.debug("Received POST request containing update sigtracker form, is valid: %s" % form.is_valid()) - if form.is_valid(): - auth_info = AuthServicesInfoManager.get_auth_service_info(request.user) - character = EveManager.get_character_by_id(auth_info.main_char_id) - sig.ident = form.cleaned_data['ident'] - sig.system = form.cleaned_data['system'] - sig.destination = form.cleaned_data['destination'] - sig.lifetime_status = form.cleaned_data['lifetime_status'] - sig.mass_status = form.cleaned_data['mass_status'] - sig.ships_size = form.cleaned_data['ships_size'] - sig.through_dest = form.cleaned_data['through_dest'] - sig.notes = form.cleaned_data['notes'] - sig.eve_character = character - logger.info("User %s updating sigtracker id %s " % (request.user, sigtracker_id)) - sig.save() - - logger.debug("Detected no changes between sigtracker id %s and supplied form." % sigtracker_id) - return HttpResponseRedirect("/sigtracker/") - else: - data = { - 'ident': sig.ident, - 'system': sig.system, - 'destination': sig.destination, - 'lifetime_status': sig.lifetime_status, - 'mass_status': sig.mass_status, - 'ships_size': sig.ships_size, - 'through_dest': sig.through_dest, - 'notes': sig.notes, - } - form = SignatureForm(initial= data) - return render_to_response('registered/signatureupdate.html', {'form':form}, context_instance=RequestContext(request)) diff --git a/srp/__init__.py b/srp/__init__.py index e69de29b..baffc488 100755 --- a/srp/__init__.py +++ b/srp/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/srp/admin.py b/srp/admin.py index 5ddca89d..53eff30a 100755 --- a/srp/admin.py +++ b/srp/admin.py @@ -1,8 +1,8 @@ +from __future__ import unicode_literals from django.contrib import admin -from models import SrpFleetMain -from models import SrpUserRequest +from srp.models import SrpFleetMain +from srp.models import SrpUserRequest -# Register your models here. admin.site.register(SrpFleetMain) -admin.site.register(SrpUserRequest) \ No newline at end of file +admin.site.register(SrpUserRequest) diff --git a/srp/apps.py b/srp/apps.py new file mode 100644 index 00000000..93027128 --- /dev/null +++ b/srp/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class SRPConfig(AppConfig): + name = 'srp' diff --git a/srp/form.py b/srp/form.py index 4cc64ac3..7dfccfe6 100755 --- a/srp/form.py +++ b/srp/form.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from django import forms from django.utils.translation import ugettext_lazy as _ @@ -30,4 +31,3 @@ class SrpFleetUpdateCostForm(forms.Form): class SrpFleetMainUpdateForm(forms.Form): fleet_aar_link = forms.CharField(required=True, label=_("After Action Report Link")) - diff --git a/srp/migrations/0001_initial.py b/srp/migrations/0001_initial.py new file mode 100644 index 00000000..661199cf --- /dev/null +++ b/srp/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-05 21:40 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('eveonline', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='SrpFleetMain', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('fleet_name', models.CharField(default=b'', max_length=254)), + ('fleet_doctrine', models.CharField(default=b'', max_length=254)), + ('fleet_time', models.DateTimeField()), + ('fleet_srp_code', models.CharField(default=b'', max_length=254)), + ('fleet_srp_status', models.CharField(default=b'', max_length=254)), + ('fleet_srp_aar_link', models.CharField(default=b'', max_length=254)), + ('fleet_commander', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')), + ], + ), + migrations.CreateModel( + name='SrpUserRequest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('killboard_link', models.CharField(default=b'', max_length=254)), + ('after_action_report_link', models.CharField(default=b'', max_length=254)), + ('additional_info', models.CharField(default=b'', max_length=254)), + ('srp_status', models.CharField(default=b'', max_length=254)), + ('srp_total_amount', models.BigIntegerField(default=0)), + ('kb_total_loss', models.BigIntegerField(default=0)), + ('srp_ship_name', models.CharField(default=b'', max_length=254)), + ('post_time', models.DateTimeField(default=django.utils.timezone.now)), + ('character', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='eveonline.EveCharacter')), + ('srp_fleet_main', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='srp.SrpFleetMain')), + ], + ), + ] diff --git a/srp/migrations/__init__.py b/srp/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/srp/models.py b/srp/models.py index c8e05e41..c57fa2ce 100755 --- a/srp/models.py +++ b/srp/models.py @@ -1,8 +1,11 @@ +from __future__ import unicode_literals +from django.utils.encoding import python_2_unicode_compatible from django.db import models from django.utils import timezone from eveonline.models import EveCharacter +@python_2_unicode_compatible class SrpFleetMain(models.Model): fleet_name = models.CharField(max_length=254, default="") fleet_doctrine = models.CharField(max_length=254, default="") @@ -16,6 +19,7 @@ class SrpFleetMain(models.Model): return self.fleet_name + " - SrpFleetMain" +@python_2_unicode_compatible class SrpUserRequest(models.Model): killboard_link = models.CharField(max_length=254, default="") after_action_report_link = models.CharField(max_length=254, default="") @@ -25,7 +29,7 @@ class SrpUserRequest(models.Model): character = models.ForeignKey(EveCharacter) srp_fleet_main = models.ForeignKey(SrpFleetMain) kb_total_loss = models.BigIntegerField(default=0) - srp_ship_name = models.CharField(max_length=254, default="") + srp_ship_name = models.CharField(max_length=254, default="") post_time = models.DateTimeField(default=timezone.now) def __str__(self): diff --git a/srp/views.py b/srp/views.py index 15c3a9ed..ade0c6d6 100755 --- a/srp/views.py +++ b/srp/views.py @@ -1,34 +1,37 @@ -from django.template import RequestContext -from django.http import HttpResponseRedirect -from django.shortcuts import render_to_response +from __future__ import unicode_literals +from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import permission_required -from django.contrib.auth.decorators import user_passes_test - -from util import random_string +from django.contrib import messages from eveonline.managers import EveManager -from authentication.managers import AuthServicesInfoManager -from util import check_if_user_has_permission -from models import SrpFleetMain -from models import SrpUserRequest -from form import SrpFleetMainForm -from form import SrpFleetUserRequestForm -from form import SrpFleetUpdateCostForm -from form import SrpFleetMainUpdateForm +from authentication.models import AuthServicesInfo +from srp.models import SrpFleetMain +from srp.models import SrpUserRequest +from srp.form import SrpFleetMainForm +from srp.form import SrpFleetUserRequestForm +from srp.form import SrpFleetUpdateCostForm +from srp.form import SrpFleetMainUpdateForm from services.managers.srp_manager import srpManager from notifications import notify from django.utils import timezone +from authentication.decorators import members_and_blues +import uuid import logging logger = logging.getLogger(__name__) -def srp_util_test(user): - return check_if_user_has_permission(user, 'member') or check_if_user_has_permission(user, 'blue_member') + +def random_string(string_length=10): + """Returns a random string of length string_length.""" + random = str(uuid.uuid4()) # Convert UUID format to a Python string. + random = random.upper() # Make all characters uppercase. + random = random.replace("-", "") # Remove the UUID '-'. + return random[0:string_length] # Return the random string. @login_required -@user_passes_test(srp_util_test) +@members_and_blues() def srp_management(request): logger.debug("srp_management called by user %s" % request.user) totalcost = 0 @@ -45,11 +48,11 @@ def srp_management(request): context = {"srpfleets": SrpFleetMain.objects.filter(fleet_srp_status=""), "totalcost": totalcost, "price_pair": price_pair} - return render_to_response('registered/srpmanagement.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/srpmanagement.html', context=context) @login_required -@user_passes_test(srp_util_test) +@members_and_blues() def srp_management_all(request): logger.debug("srp_management_all called by user %s" % request.user) totalcost = 0 @@ -65,11 +68,11 @@ def srp_management_all(request): logger.debug("Determined all-time total SRP cost %s" % totalcost) context = {"srpfleets": SrpFleetMain.objects.all(), "totalcost": totalcost, "price_pair": price_pair} - return render_to_response('registered/srpmanagement.html', context, context_instance=RequestContext(request)) + return render(request, 'registered/srpmanagement.html', context=context) @login_required -@user_passes_test(srp_util_test) +@members_and_blues() def srp_fleet_view(request, fleet_id): logger.debug("srp_fleet_view called by user %s for fleet id %s" % (request.user, fleet_id)) if SrpFleetMain.objects.filter(id=fleet_id).exists(): @@ -83,11 +86,11 @@ def srp_fleet_view(request, fleet_id): "srpfleetrequests": SrpUserRequest.objects.filter(srp_fleet_main=fleet_main), "totalcost": totalcost} - return render_to_response('registered/srpfleetdata.html', context, context_instance=RequestContext(request)) - + return render(request, 'registered/srpfleetdata.html', context=context) else: - logger.error("Unable to view SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error( + "Unable to view SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) + return redirect("auth_srp_management_view") @login_required @@ -101,7 +104,7 @@ def srp_fleet_add_view(request): form = SrpFleetMainForm(request.POST) logger.debug("Request type POST contains form valid: %s" % form.is_valid()) if form.is_valid(): - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) srp_fleet_main = SrpFleetMain() @@ -116,6 +119,7 @@ def srp_fleet_add_view(request): completed = True completed_srp_code = srp_fleet_main.fleet_srp_code logger.info("Created SRP Fleet %s by user %s" % (srp_fleet_main.fleet_name, request.user)) + messages.success(request, 'Created SRP fleet %s.' % srp_fleet_main.fleet_name) else: logger.debug("Returning blank SrpFleetMainForm") @@ -123,7 +127,7 @@ def srp_fleet_add_view(request): render_items = {'form': form, "completed": completed, "completed_srp_code": completed_srp_code} - return render_to_response('registered/srpfleetadd.html', render_items, context_instance=RequestContext(request)) + return render(request, 'registered/srpfleetadd.html', context=render_items) @login_required @@ -134,9 +138,13 @@ def srp_fleet_remove(request, fleet_id): srpfleetmain = SrpFleetMain.objects.get(id=fleet_id) srpfleetmain.delete() logger.info("SRP Fleet %s deleted by user %s" % (srpfleetmain.fleet_name, request.user)) + messages.success(request, 'Removed SRP fleet %s.' % srpfleetmain.fleet_name) else: - logger.error("Unable to delete SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error( + "Unable to delete SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect("auth_srp_management_view") + @login_required @permission_required('auth.srp_management') @@ -147,9 +155,13 @@ def srp_fleet_disable(request, fleet_id): srpfleetmain.fleet_srp_code = "" srpfleetmain.save() logger.info("SRP Fleet %s disabled by user %s" % (srpfleetmain.fleet_name, request.user)) + messages.success(request, 'Disabled SRP fleet %s.' % srpfleetmain.fleet_name) else: - logger.error("Unable to disable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error( + "Unable to disable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect("auth_srp_management_view") + @login_required @permission_required('auth.srp_management') @@ -160,9 +172,13 @@ def srp_fleet_enable(request, fleet_id): srpfleetmain.fleet_srp_code = random_string(8) srpfleetmain.save() logger.info("SRP Fleet %s enable by user %s" % (srpfleetmain.fleet_name, request.user)) + messages.success(request, 'Enabled SRP fleet %s.' % srpfleetmain.fleet_name) else: - logger.error("Unable to enable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error( + "Unable to enable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect("auth_srp_management_view") + @login_required @permission_required('auth.srp_management') @@ -173,9 +189,12 @@ def srp_fleet_mark_completed(request, fleet_id): srpfleetmain.fleet_srp_status = "Completed" srpfleetmain.save() logger.info("Marked SRP Fleet %s as completed by user %s" % (srpfleetmain.fleet_name, request.user)) + messages.success(request, 'Marked SRP fleet %s as completed.' % srpfleetmain.fleet_name) else: - logger.error("Unable to mark SRP fleet with id %s as completed for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp_fleet_view/" + str(fleet_id)) + logger.error("Unable to mark SRP fleet with id %s as completed for user %s - fleet matching id not found." % ( + fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect("auth_srp_fleet_view", fleet_id) @login_required @@ -187,18 +206,21 @@ def srp_fleet_mark_uncompleted(request, fleet_id): srpfleetmain.fleet_srp_status = "" srpfleetmain.save() logger.info("Marked SRP Fleet %s as incomplete for user %s" % (fleet_id, request.user)) + messages.success(request, 'Marked SRP fleet %s as incomplete.' % srpfleetmain.fleet_name) + return redirect("auth_srp_fleet_view", fleet_id) else: - logger.error("Unable to mark SRP Fleet id %s as incomplete for user %s - fleet matching id not found." % (fleet_id, request.user)) - return HttpResponseRedirect("/srp_fleet_view/" + str(fleet_id)) + logger.error("Unable to mark SRP Fleet id %s as incomplete for user %s - fleet matching id not found." % ( + fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect('auth_srp_management_view') @login_required -@user_passes_test(srp_util_test) +@members_and_blues() def srp_request_view(request, fleet_srp): logger.debug("srp_request_view called by user %s for fleet srp code %s" % (request.user, fleet_srp)) completed = False no_srp_code = False - srp_code = "" if SrpFleetMain.objects.filter(fleet_srp_code=fleet_srp).exists() is False: no_srp_code = True @@ -209,7 +231,7 @@ def srp_request_view(request, fleet_srp): logger.debug("Request type POST contains form valid: %s" % form.is_valid()) if form.is_valid(): - authinfo = AuthServicesInfoManager.get_auth_service_info(request.user) + authinfo = AuthServicesInfo.objects.get_or_create(user=request.user)[0] character = EveManager.get_character_by_id(authinfo.main_char_id) srp_fleet_main = SrpFleetMain.objects.get(fleet_srp_code=fleet_srp) post_time = timezone.now() @@ -226,9 +248,12 @@ def srp_request_view(request, fleet_srp): srp_kill_link = srpManager.get_kill_id(srp_request.killboard_link) (srp_kill_data, ship_value) = srpManager.get_kill_data(srp_kill_link) except ValueError: - logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % (request.user, srp_request.killboard_link)) - notify(request.user, "Your SRP request Killmail Link Failed Validation", message="Your SRP request Killmail link %s is invalid. Please make sure your using zKillboard." % srp_request.killboard_link, level="danger") - return HttpResponseRedirect("/srp") + logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % ( + request.user, srp_request.killboard_link)) + # THIS SHOULD BE IN FORM VALIDATION + messages.error(request, + "Your SRP request Killmail link is invalid. Please make sure you are using zKillboard.") + return redirect("auth_srp_management_view") srp_ship_name = srpManager.get_ship_name(srp_kill_data) srp_request.srp_ship_name = srp_ship_name kb_total_loss = ship_value @@ -236,7 +261,9 @@ def srp_request_view(request, fleet_srp): srp_request.post_time = post_time srp_request.save() completed = True - logger.info("Created SRP Request on behalf of user %s for fleet name %s" % (request.user, srp_fleet_main.fleet_name)) + logger.info("Created SRP Request on behalf of user %s for fleet name %s" % ( + request.user, srp_fleet_main.fleet_name)) + messages.success(request, 'Submitted SRP request for your %s.' % srp_ship_name) else: logger.debug("Returning blank SrpFleetUserRequestForm") @@ -244,7 +271,7 @@ def srp_request_view(request, fleet_srp): render_items = {'form': form, "completed": completed, "no_srp_code": no_srp_code} - return render_to_response('registered/srpfleetrequest.html', render_items, context_instance=RequestContext(request)) + return render(request, 'registered/srpfleetrequest.html', context=render_items) @login_required @@ -258,12 +285,15 @@ def srp_request_remove(request, srp_request_id): stored_fleet_view = srpuserrequest.srp_fleet_main.id srpuserrequest.delete() logger.info("Deleted SRP request id %s for user %s" % (srp_request_id, request.user)) - + messages.success(request, 'Deleted SRP request from %s for their %s.' % ( + srpuserrequest.character, srpuserrequest.srp_ship_name)) if stored_fleet_view is None: - logger.error("Unable to delete srp request id %s for user %s - request matching id not found." % (srp_request_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error("Unable to delete srp request id %s for user %s - request matching id not found." % ( + srp_request_id, request.user)) + messages.error(request, 'Unable to locate SRP request with ID %s' % srp_request_id) + return redirect("auth_srp_management_view") else: - return HttpResponseRedirect("/srp_fleet_view/" + str(stored_fleet_view)) + return redirect("auth_srp_fleet_view", stored_fleet_view) @login_required @@ -272,8 +302,6 @@ def srp_request_approve(request, srp_request_id): logger.debug("srp_request_approve called by user %s for srp request id %s" % (request.user, srp_request_id)) stored_fleet_view = None - - if SrpUserRequest.objects.filter(id=srp_request_id).exists(): srpuserrequest = SrpUserRequest.objects.get(id=srp_request_id) stored_fleet_view = srpuserrequest.srp_fleet_main.id @@ -281,13 +309,24 @@ def srp_request_approve(request, srp_request_id): if srpuserrequest.srp_total_amount == 0: srpuserrequest.srp_total_amount = srpuserrequest.kb_total_loss srpuserrequest.save() - logger.info("Approved SRP request id %s for character %s by user %s" % (srp_request_id, srpuserrequest.character, request.user)) - + logger.info("Approved SRP request id %s for character %s by user %s" % ( + srp_request_id, srpuserrequest.character, request.user)) + messages.success(request, 'Approved SRP request from %s for their %s.' % ( + srpuserrequest.character, srpuserrequest.srp_ship_name)) + notify( + srpuserrequest.character.user, + 'SRP Request Approved', + level='success', + message='Your SRP request for a %s lost during %s has been approved for %s ISK.' % ( + srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name, srpuserrequest.srp_total_amount) + ) if stored_fleet_view is None: - logger.error("Unable to approve srp request id %s on behalf of user %s - request matching id not found." % (srp_request_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error("Unable to approve srp request id %s on behalf of user %s - request matching id not found." % ( + srp_request_id, request.user)) + messages.error(request, 'Unable to locate SRP request with ID %s' % srp_request_id) + return redirect("auth_srp_management_view") else: - return HttpResponseRedirect("/srp_fleet_view/" + str(stored_fleet_view)) + return redirect("auth_srp_fleet_view", stored_fleet_view) @login_required @@ -301,25 +340,37 @@ def srp_request_reject(request, srp_request_id): stored_fleet_view = srpuserrequest.srp_fleet_main.id srpuserrequest.srp_status = "Rejected" srpuserrequest.save() - logger.info("SRP request id %s for character %s rejected by %s" % (srp_request_id, srpuserrequest.character, request.user)) + logger.info("SRP request id %s for character %s rejected by %s" % ( + srp_request_id, srpuserrequest.character, request.user)) + messages.success(request, 'Rejected SRP request from %s for their %s.' % ( + srpuserrequest.character, srpuserrequest.srp_ship_name)) + notify( + srpuserrequest.character.user, + 'SRP Request Rejected', + level='danger', + message='Your SRP request for a %s lost during %s has been rejected.' % ( + srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name) + ) if stored_fleet_view is None: - logger.error("Unable to reject SRP request id %s on behalf of user %s - request matching id not found." % (srp_request_id, request.user)) - return HttpResponseRedirect("/srp") + logger.error("Unable to reject SRP request id %s on behalf of user %s - request matching id not found." % ( + srp_request_id, request.user)) + messages.error(request, 'Unable to locate SRP request with ID %s' % srp_request_id) + return redirect("auth_srp_management_view") else: - return HttpResponseRedirect("/srp_fleet_view/" + str(stored_fleet_view)) + return redirect("auth_srp_fleet_view", stored_fleet_view) @login_required @permission_required('auth.srp_management') def srp_request_update_amount_view(request, fleet_srp_request_id): - logger.debug("srp_request_update_amount_view called by user %s for fleet srp request id %s" % (request.user, fleet_srp_request_id)) - no_srp_code = False - srp_code = "" + logger.debug("srp_request_update_amount_view called by user %s for fleet srp request id %s" % ( + request.user, fleet_srp_request_id)) if SrpUserRequest.objects.filter(id=fleet_srp_request_id).exists() is False: logger.error("Unable to locate SRP request id %s for user %s" % (fleet_srp_request_id, request.user)) - no_srp_code = True + messages.error(request, 'Unable to locate SRP request with ID %s' % fleet_srp_request_id) + return redirect("auth_srp_management_view") if request.method == 'POST': form = SrpFleetUpdateCostForm(request.POST) @@ -328,17 +379,17 @@ def srp_request_update_amount_view(request, fleet_srp_request_id): srp_request = SrpUserRequest.objects.get(id=fleet_srp_request_id) srp_request.srp_total_amount = form.cleaned_data['srp_total_amount'] srp_request.save() - logger.info("Updated srp request id %s total to %s by user %s" % (fleet_srp_request_id, form.cleaned_data['srp_total_amount'], request.user)) - - return HttpResponseRedirect("/srp_fleet_view/" + str(srp_request.srp_fleet_main.id)) + logger.info("Updated srp request id %s total to %s by user %s" % ( + fleet_srp_request_id, form.cleaned_data['srp_total_amount'], request.user)) + messages.success(request, 'Updated SRP amount.') + return redirect("auth_srp_fleet_view", srp_request.srp_fleet_main.id) else: logger.debug("Returning blank SrpFleetUpdateCostForm") form = SrpFleetUpdateCostForm() - render_items = {'form': form, "no_srp_code": no_srp_code} + render_items = {'form': form} - return render_to_response('registered/srpfleetrequestamount.html', render_items, - context_instance=RequestContext(request)) + return render(request, 'registered/srpfleetrequestamount.html', context=render_items) @login_required @@ -346,7 +397,6 @@ def srp_request_update_amount_view(request, fleet_srp_request_id): def srp_fleet_edit_view(request, fleet_id): logger.debug("srp_fleet_edit_view called by user %s for fleet id %s" % (request.user, fleet_id)) no_fleet_id = False - form = None if SrpFleetMain.objects.filter(id=fleet_id).exists(): if request.method == 'POST': form = SrpFleetMainUpdateForm(request.POST) @@ -356,15 +406,16 @@ def srp_fleet_edit_view(request, fleet_id): srpfleetmain.fleet_srp_aar_link = form.cleaned_data['fleet_aar_link'] srpfleetmain.save() logger.info("User %s edited SRP Fleet %s" % (request.user, srpfleetmain.fleet_name)) - return HttpResponseRedirect("/srp") + messages.success(request, 'Saved changes to SRP fleet %s' % srpfleetmain.fleet_name) + return redirect("auth_srp_management_view") else: logger.debug("Returning blank SrpFleetMainUpdateForm") form = SrpFleetMainUpdateForm() + render_items = {'form': form, "no_fleet_id": no_fleet_id} + return render(request, 'registered/srpfleetupdate.html', context=render_items) + else: - logger.error("Unable to edit srp fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) - no_fleet_id = True - - render_items = {'form': form, "no_fleet_id": no_fleet_id} - - return render_to_response('registered/srpfleetupdate.html', render_items, - context_instance=RequestContext(request)) + logger.error( + "Unable to edit srp fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user)) + messages.error(request, 'Unable to locate SRP fleet with ID %s' % fleet_id) + return redirect("auth_srp_management_view") diff --git a/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_Black.png b/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_Black.png new file mode 100644 index 00000000..0540f9a3 Binary files /dev/null and b/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_Black.png differ diff --git a/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_White.png b/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_White.png new file mode 100644 index 00000000..a7268c3e Binary files /dev/null and b/stock/static/img/sso/EVE_SSO_Login_Buttons_Large_White.png differ diff --git a/stock/templates/public/base.html b/stock/templates/public/base.html index c5e4af9b..650d843a 100755 --- a/stock/templates/public/base.html +++ b/stock/templates/public/base.html @@ -1,5 +1,6 @@ {% load staticfiles %} {% load i18n %} +{% load navactive %} @@ -30,6 +31,10 @@ #f_lang_select { margin-right: 5px; } + .navbar-brand { + height: 58px; + padding: 19px 19px; + } @@ -39,22 +44,17 @@