Files
test-auth/app/api/handlers/v1.py

315 lines
12 KiB
Python

import re
from datetime import datetime
from xml.dom import minidom
from operator import itemgetter
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
from django.conf import settings
from django.utils.timezone import now
from BeautifulSoup import BeautifulSoup
from piston.handler import BaseHandler
from piston.utils import rc, throttle
from gargoyle import gargoyle
from api.models import AuthAPIKey, AuthAPILog
from eve_proxy.models import CachedDocument
from eve_proxy.exceptions import *
from eve_api.app_defines import *
from eve_api.models import EVEAccount, EVEPlayerCharacter
from sso.models import ServiceAccount, Service
from hr.app_defines import *
from hr.models import Blacklist
class UserHandler(BaseHandler):
allowed_methods = ('GET')
def read(self, request):
if 'userid' in request.GET:
try:
u = User.objects.get(id=request.GET['userid'])
except (User.DoesNotExist, ValueError):
return {'auth': 'missing', 'missing': 'userid'}
elif 'user' in request.GET:
try:
u = User.objects.get(username=request.GET['user'])
except User.DoesNotExist:
return {'auth': 'missing', 'missing': 'username'}
elif 'serviceuid' in request.GET:
try:
u = ServiceAccount.objects.get(service_uid=request.GET['serviceuid']).user
except ServiceAccount.DoesNotExist:
return {'auth': 'missing', 'missing': 'ServiceAccount'}
elif 'apiuserid' in request.GET:
try:
u = EVEAccount.objects.get(api_user_id=request.GET['apiuserid']).user
except EVEAccount.DoesNotExist:
return {'auth': 'missing', 'missing': 'apiuserid'}
chars = []
for a in u.eveaccount_set.all():
chars.extend(a.characters.all())
d = {'id': u.id, 'username': u.username, 'email': u.email,
'serviceaccounts': u.serviceaccount_set.all(), 'characters': chars,
'groups': u.groups.all(), 'staff': u.is_staff, 'superuser': u.is_superuser, 'redditaccounts': u.redditaccount_set.filter(validated=True) }
return d
class LoginHandler(BaseHandler):
allowed_methods = ('GET')
def read(self, request):
username = request.GET.get('user', None)
character = request.GET.get('character', None)
password = request.GET.get('pass', None)
if username:
u = User.objects.filter(username=username)
elif character:
u = User.objects.filter(profile__primary_character__name__iexact=character)
else:
u = User.objects.none()
if not u.count():
return {'auth': 'failed', 'error': 'none'}
elif u.count() > 1:
return {'auth': 'failed', 'error': 'multiple'}
else:
u = u[0]
if u.is_active and password and password == u.get_profile().api_service_password:
pchar = u.get_profile().primary_character
if pchar:
pchardict = {'id': pchar.id,
'name': pchar.name,
'corporation': {'name': pchar.corporation.name, 'id': pchar.corporation.id, 'ticker': pchar.corporation.ticker },
}
if pchar.corporation.alliance:
pchardict['alliance'] = {'id': pchar.corporation.alliance.id, 'name': pchar.corporation.alliance.name, 'ticker': pchar.corporation.alliance.ticker }
else:
pchardict['alliance'] = None
else:
pchardict = None
glist = []
for g in u.groups.all():
if u in g.groupinformation.admins.all():
admin = True
else:
admin = False
glist.append({'id': g.id, 'name': g.name, 'admin': admin})
return {'auth': 'ok', 'id': u.id, 'username': u.username,
'email': u.email, 'groups': glist,
'staff': u.is_staff, 'superuser': u.is_superuser, 'primarycharacter': pchardict}
else:
return {'auth': 'failed', 'error': 'password'}
return {'auth': 'missing', 'missing': 'all'}
class EveAPIHandler(BaseHandler):
allowed_methods = ('GET')
exclude = ('api_key')
def read(self, request):
s = None
if request.GET.get('id', None):
s = get_object_or_404(EVEAccount, pk=id)
elif request.GET.get('userid', None):
s = EVEAccount.objects.filter(user=request.GET['userid'])
elif request.GET.get('corpid', None):
s = EVEAccount.objects.filter(characters__corporation__id=request.GET['corpid'])
elif request.GET.get('allianceid', None):
s = EVEAccount.objects.filter(characters__corporation__alliance__id=request.GET['allianceid'])
if s:
return {'keys': s.values('api_user_id', 'user_id', 'api_status', 'api_keytype', 'api_last_updated')}
return {'keys': []}
class EveAPIProxyHandler(BaseHandler):
allowed_methods = ('GET')
def read(self, request):
url_path = request.META['PATH_INFO'].replace(reverse('api-eveapiproxy'), "/")
params = {}
for key, value in request.GET.items():
params[key.lower()] = value
if 'userid' in params or 'keyid' in params:
try:
obj = get_object_or_404(EVEAccount, pk=params['userid'])
except ValueError:
return rc.BAD_REQUEST
# "Fix" new style keys
if obj.api_keytype >= 3:
params['keyid'] = params['userid']
del params['userid']
params['vcode'] = obj.api_key
else:
params['apikey'] = obj.api_key
try:
cached_doc = CachedDocument.objects.api_query(url_path, params, service=request.api_key.name)
except DocumentRetrievalError, exc:
return rc.INTERNAL_ERROR
else:
return HttpResponse(cached_doc.body)
class OpTimerHandler(BaseHandler):
allowed_methods = ('GET')
def read(self, request, id=None):
obj = get_object_or_404(EVEAccount, pk=settings.FULL_API_USER_ID)
if gargoyle.is_active('eve-cak'):
params = {'keyid': obj.pk, 'vcode': obj.api_key, 'characterID': settings.FULL_API_CHARACTER_ID}
else:
params = {'userID': obj.pk, 'apiKey': obj.api_key, 'characterID': settings.FULL_API_CHARACTER_ID}
error_doc = {'ops': [{'startsIn': -1, 'eventID': 0, 'ownerName': '', 'eventDate': '', 'eventTitle': '<div style="text-align:center">The EVE API calendar is unavailable</div>', 'duration': 0, 'isImportant': 0, 'eventText': 'Fuck CCP tbqh imho srsly', 'endsIn':-1, 'forumLink': ''}]}
try:
cached_doc = CachedDocument.objects.api_query('/char/UpcomingCalendarEvents.xml.aspx', params, timeout=10, service="Optimer")
except DocumentRetrievalError:
return error_doc
dom = minidom.parseString(cached_doc.body.encode('utf-8'))
if dom.getElementsByTagName('error'):
error_doc['raw_xml'] = cached_doc.body
return error_doc
events = []
for node in dom.getElementsByTagName('rowset')[0].childNodes:
if node.nodeType == 1:
ownerID = node.getAttribute('ownerID')
if ownerID != '1':
dt = datetime.strptime(node.getAttribute('eventDate'), '%Y-%m-%d %H:%M:%S').replace(tzinfo=utc)
startsIn = int(dt.strftime('%s')) - int(now().strftime('%s'))
duration = int(node.getAttribute('duration'))
fid = re.search('topic=[\d]+', node.getAttribute('eventText'))
if fid:
forumlink = 'http://forum.pleaseignore.com/index.php?%s' % fid.group(0)
else:
forumlink = ''
#In case people forget to set a duration, we'll give a default of 1 hour
if duration == 0:
duration = 60
endsIn = startsIn + (duration * 60)
if startsIn < 0:
startsIn = 0
if endsIn > 0:
event = {
'startsIn': startsIn,
'eventID': int(node.getAttribute('eventID')),
'ownerName': node.getAttribute('ownerName'),
'eventDate': date,
'eventTitle': node.getAttribute('eventTitle'),
'duration': duration,
'isImportant': int(node.getAttribute('importance')),
'eventText': ' '.join(BeautifulSoup(node.getAttribute('eventText')).findAll(text=True)),
'endsIn':endsIn,
'forumLink': forumlink}
events.append(event)
if len(events) == 0:
return {'ops':[{
'startsIn': -1,
'eventID': 0,
'ownerName': '',
'eventDate': '',
'eventTitle': '<div style="text-align:center">No ops are currently scheduled</div>',
'duration': 0,
'isImportant': 0,
'eventText': 'Add ops using EVE-Gate or the in-game calendar',
'endsIn':-1,
'forumLink': ''}]}
else:
events.sort(key=itemgetter('startsIn'))
return {'ops': events, 'doc_time': cached_doc.time_retrieved, 'cache_until': cached_doc.cached_until, 'current_time': now() }
class BlacklistHandler(BaseHandler):
model = Blacklist
allowed_methods = ('GET')
fields = ('type', 'value', 'level', 'source', ('name', 'ticker'), 'created_date', 'expiry_date', 'reason')
def read(self, request):
if request.GET.get('value'):
obj = Blacklist.objects.select_related('blacklistsource').filter(level__lte=BLACKLIST_LEVEL_ADVISORY,value__icontains=request.GET.get('value'))
if obj.count() and request.GET.get('type'):
obj = obj.filter(type=request.GET.get('type'))
else:
obj = []
return obj
class CharacterHandler(BaseHandler):
allowed_methods = ('GET')
fields = ('id', 'name', ('corporation', ('id', 'name', ('alliance', ('id', 'name')))), 'corporation_date', 'balance', 'total_sp', 'security_status', 'director', 'skillset')
@classmethod
def skillset(cls, instance):
return instance.eveplayercharacterskill_set.all().values('skill__id', 'skill__name', 'level', 'skillpoints')
def read(self, request):
s = []
if request.GET.get('id', None):
s = get_object_or_404(EVEPlayerCharacter, pk=id)
elif request.GET.get('corpid', None):
s = EVEPlayerCharacter.objects.filter(corporation__id=request.GET['corpid'])
elif request.GET.get('allianceid', None):
s = EVEPlayerCharacter.objects.filter(corporation__alliance__id=request.GET['allianceid'])
return s
class AnnounceHandler(BaseHandler):
allowed_methods = ('GET')
def read(self, request):
sid = request.GET.get('sid', None)
users = request.GET.getlist('users')
groups = request.GET.getlist('groups')
servers = request.GET.getlist('servers')
message = request.GET.get('message', None)
subject = request.GET.get('subject', None)
if sid and message:
srv = get_object_or_404(Service, pk=sid)
if not srv.api == 'sso.services.jabber':
return {'result': 'invalid'}
api = srv.api_class
return {'result': api.announce(api.settings['jabber_server'], message, subject, users=users, groups=groups, servers=servers) }
return {'result': 'invalid'}
class EDKApiHandler(BaseHandler):
allowed_methods = ('GET',)
def read(self, request):
alliance = request.GET.get('alliance', None)
if not alliance:
return {'auth': 'missing', 'missing': 'alliance'}
objs = EVEAccount.objects.filter(characters__corporation__alliance=alliance, api_keytype=API_KEYTYPE_CORPORATION, api_status=API_STATUS_OK).extra(where=['(api_accessmask & 256) > 0'])
return objs.values('api_user_id', 'api_key', 'characters__id', 'characters__name', 'characters__corporation__name')