mirror of
https://github.com/nikdoof/test-auth.git
synced 2025-12-14 06:42:16 +00:00
Initial import
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.pyc
|
||||||
0
__init__.py
Normal file
0
__init__.py
Normal file
0
eve_api/__init__.py
Normal file
0
eve_api/__init__.py
Normal file
32
eve_api/admin.py
Normal file
32
eve_api/admin.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
Admin interface models. Automatically detected by admin.autodiscover().
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from eve_api.models import *
|
||||||
|
|
||||||
|
class EVEAccountAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('id', 'user')
|
||||||
|
search_fields = ['id']
|
||||||
|
admin.site.register(EVEAccount, EVEAccountAdmin)
|
||||||
|
|
||||||
|
class EVEPlayerCharacterAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('id', 'name', 'corporation')
|
||||||
|
search_fields = ['id', 'name']
|
||||||
|
admin.site.register(EVEPlayerCharacter, EVEPlayerCharacterAdmin)
|
||||||
|
|
||||||
|
class EVEPlayerCorporationInline(admin.TabularInline):
|
||||||
|
model = EVEPlayerCorporation
|
||||||
|
fields = ('name', 'ticker')
|
||||||
|
extra = 0
|
||||||
|
|
||||||
|
class EVEPlayerAllianceAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('id', 'name', 'ticker', 'member_count', 'date_founded')
|
||||||
|
search_fields = ['name', 'ticker']
|
||||||
|
date_hierarchy = 'date_founded'
|
||||||
|
inlines = [EVEPlayerCorporationInline]
|
||||||
|
admin.site.register(EVEPlayerAlliance, EVEPlayerAllianceAdmin)
|
||||||
|
|
||||||
|
class EVEPlayerCorporationAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('id', 'name', 'ticker', 'member_count', 'alliance')
|
||||||
|
search_fields = ['name', 'ticker']
|
||||||
|
admin.site.register(EVEPlayerCorporation, EVEPlayerCorporationAdmin)
|
||||||
16
eve_api/api_exceptions.py
Normal file
16
eve_api/api_exceptions.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
Contains exeptions used in the eve_api app.
|
||||||
|
"""
|
||||||
|
class APIAuthException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when an invalid userID and/or authKey were provided.
|
||||||
|
"""
|
||||||
|
def __str__(self):
|
||||||
|
return "An authentication was encountered while querying the EVE API."
|
||||||
|
|
||||||
|
class APINoUserIDException(Exception):
|
||||||
|
"""
|
||||||
|
Raised when a userID is required, but missing.
|
||||||
|
"""
|
||||||
|
def __str__(self):
|
||||||
|
return "This query requires a valid userID, but yours is either missing or invalid."
|
||||||
0
eve_api/api_puller/__init__.py
Normal file
0
eve_api/api_puller/__init__.py
Normal file
72
eve_api/api_puller/accounts.py
Executable file
72
eve_api/api_puller/accounts.py
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
This module abstracts the pulling of account data from the EVE API.
|
||||||
|
"""
|
||||||
|
from xml.dom import minidom
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Only mess with the environmental stuff if this is being ran directly.
|
||||||
|
from importer_path import fix_environment
|
||||||
|
fix_environment()
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
from eve_api.api_exceptions import APIAuthException, APINoUserIDException
|
||||||
|
from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation
|
||||||
|
|
||||||
|
def import_eve_account(api_key, user_id):
|
||||||
|
"""
|
||||||
|
Imports an account from the API into the EVEAccount model.
|
||||||
|
"""
|
||||||
|
print user_id, ":", api_key
|
||||||
|
auth_params = {'userID': user_id, 'apiKey': api_key}
|
||||||
|
account_doc = CachedDocument.objects.api_query('/account/Characters.xml.aspx',
|
||||||
|
params=auth_params,
|
||||||
|
no_cache=False)
|
||||||
|
#print account_doc.body
|
||||||
|
|
||||||
|
dom = minidom.parseString(account_doc.body)
|
||||||
|
characters_node_children = dom.getElementsByTagName('rowset')[0].childNodes
|
||||||
|
|
||||||
|
# Create or retrieve the account last to make sure everything
|
||||||
|
# before here is good to go.
|
||||||
|
try:
|
||||||
|
account = EVEAccount.objects.get(id=user_id)
|
||||||
|
except EVEAccount.DoesNotExist:
|
||||||
|
account = EVEAccount(id=user_id)
|
||||||
|
|
||||||
|
account.api_key = api_key
|
||||||
|
account.api_user_id = user_id
|
||||||
|
account.api_last_updated = datetime.now()
|
||||||
|
account.save()
|
||||||
|
|
||||||
|
for node in characters_node_children:
|
||||||
|
try:
|
||||||
|
# Get this first, as it's safe.
|
||||||
|
corporation_id = node.getAttribute('corporationID')
|
||||||
|
corp, created = EVEPlayerCorporation.objects.get_or_create(id=corporation_id)
|
||||||
|
# Do this last, since the things we retrieved above are used
|
||||||
|
# on the EVEPlayerCharacter object's fields.
|
||||||
|
character_id = node.getAttribute('characterID')
|
||||||
|
pchar, created = EVEPlayerCharacter.objects.get_or_create(id=character_id)
|
||||||
|
name = node.getAttribute('name')
|
||||||
|
# Save these for last to keep the save count low.
|
||||||
|
pchar.name = name
|
||||||
|
pchar.corporation = corp
|
||||||
|
pchar.save()
|
||||||
|
account.characters.add(pchar)
|
||||||
|
except AttributeError:
|
||||||
|
# This must be a Text node, ignore it.
|
||||||
|
continue
|
||||||
|
|
||||||
|
return account
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
"""
|
||||||
|
Test import.
|
||||||
|
"""
|
||||||
|
api_key = settings.EVE_API_USER_KEY
|
||||||
|
#api_key += "1"
|
||||||
|
user_id = settings.EVE_API_USER_ID
|
||||||
|
import_eve_account(api_key, user_id)
|
||||||
130
eve_api/api_puller/alliances.py
Executable file
130
eve_api/api_puller/alliances.py
Executable file
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
This module pulls the master alliance XML list from the API and dumps it in the
|
||||||
|
api_puller/xml_cache directory as needed. All alliance data must be updated
|
||||||
|
in bulk, which is done reasonably quickly.
|
||||||
|
"""
|
||||||
|
from xml.dom import minidom
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Only mess with the environmental stuff if this is being ran directly.
|
||||||
|
from importer_path import fix_environment
|
||||||
|
fix_environment()
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from eve_api.models import EVEPlayerAlliance, EVEPlayerCorporation
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
|
||||||
|
# This stores a list of all corps whose alliance attribute has been updated.
|
||||||
|
UPDATED_CORPS = []
|
||||||
|
|
||||||
|
def __update_corp_from_alliance_node(alliance_node, alliance):
|
||||||
|
"""
|
||||||
|
Updates a corp's alliance membership from an alliance <row> element.
|
||||||
|
"""
|
||||||
|
member_corp_nodelist = alliance_node.getElementsByTagName('rowset')[0].childNodes
|
||||||
|
|
||||||
|
for node in member_corp_nodelist:
|
||||||
|
corp_row_node = None
|
||||||
|
try:
|
||||||
|
# If this fails, this is a Text node and should be ignored.
|
||||||
|
corporation_id = int(node.getAttribute('corporationID'))
|
||||||
|
except AttributeError:
|
||||||
|
# This is probably a Text node, ignore it.
|
||||||
|
continue
|
||||||
|
|
||||||
|
corp, created = EVEPlayerCorporation.objects.get_or_create(id=corporation_id)
|
||||||
|
corp.id = corporation_id
|
||||||
|
corp.alliance = alliance
|
||||||
|
corp.alliance_join_date = datetime.strptime(alliance_node.getAttribute('startDate'),
|
||||||
|
'%Y-%m-%d %H:%M:%S')
|
||||||
|
corp.save()
|
||||||
|
# Store the corp in the updated corps list for later checks.
|
||||||
|
UPDATED_CORPS.append(corp.id)
|
||||||
|
|
||||||
|
def __remove_invalid_corp_alliance_memberships():
|
||||||
|
"""
|
||||||
|
Compares UPDATED_CORPS list to the full list of player corporations. If
|
||||||
|
the corporation was not updated from being found in one of the alliance
|
||||||
|
data sets, it has no alliance affiliation and needs to be set to no
|
||||||
|
alliance if it is not already a None value.
|
||||||
|
"""
|
||||||
|
all_corps = EVEPlayerCorporation.objects.all()
|
||||||
|
# This is not terribly efficient, but it will do for a background process.
|
||||||
|
for corp in all_corps:
|
||||||
|
"""
|
||||||
|
If the corp is not in the UPDATED_CORP list that was built from
|
||||||
|
alliance memberCorporations rowsets, then it does not belong to an
|
||||||
|
alliance and should be un-allianced if it currently is.
|
||||||
|
"""
|
||||||
|
if corp.id not in UPDATED_CORPS and corp.alliance != None:
|
||||||
|
corp.alliance = None
|
||||||
|
corp.save()
|
||||||
|
|
||||||
|
def __start_full_import():
|
||||||
|
"""
|
||||||
|
This method runs a full import of all known alliances. This may take a few
|
||||||
|
minutes and should be ran regularly if you are maintaining a full corp
|
||||||
|
list of all EVE corps as well.
|
||||||
|
"""
|
||||||
|
print "Querying /eve/AllianceList.xml.aspx/"
|
||||||
|
alliance_doc = CachedDocument.objects.api_query('/eve/AllianceList.xml.aspx')
|
||||||
|
print "Parsing..."
|
||||||
|
dom = minidom.parseString(alliance_doc.body)
|
||||||
|
result_node_children = dom.getElementsByTagName('result')[0].childNodes
|
||||||
|
|
||||||
|
# This will hold a reference to the <rowset name="alliances> Element.
|
||||||
|
alliances_rowset_node = None
|
||||||
|
# For some odd reason, two text nodes and an Element are children of
|
||||||
|
# the result Element. Find the alliances rowset from its children.
|
||||||
|
for node in result_node_children:
|
||||||
|
try:
|
||||||
|
# The node we want has a 'name' attribute.
|
||||||
|
if node.getAttribute('name') == 'alliances':
|
||||||
|
# Store the reference for later use.
|
||||||
|
alliances_rowset_node = node
|
||||||
|
# Look no further.
|
||||||
|
break
|
||||||
|
except AttributeError:
|
||||||
|
# This must be a Text node, ignore it.
|
||||||
|
continue
|
||||||
|
|
||||||
|
if alliances_rowset_node == None:
|
||||||
|
print "No alliance rowset node could be found. Your AllianceList.xml file may be corrupt."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# We now have a list of <row> tags representing each alliance.
|
||||||
|
print "Updating alliance and member corporation data..."
|
||||||
|
for alliance_node in alliances_rowset_node.childNodes:
|
||||||
|
try:
|
||||||
|
# If this fails, this is a Text node and should be ignored.
|
||||||
|
alliance_id = int(alliance_node.getAttribute('allianceID'))
|
||||||
|
except AttributeError:
|
||||||
|
# This is probably a Text node, ignore it.
|
||||||
|
continue
|
||||||
|
|
||||||
|
"""
|
||||||
|
Search for an existing EVEPlayerAlliance object with the given
|
||||||
|
alliance ID. Create one if it doesn't exist, retrieve the existing
|
||||||
|
object if it's already there.
|
||||||
|
"""
|
||||||
|
alliance, created = EVEPlayerAlliance.objects.get_or_create(id=alliance_id)
|
||||||
|
alliance.id = alliance_id
|
||||||
|
alliance.name = alliance_node.getAttribute('name')
|
||||||
|
alliance.ticker = alliance_node.getAttribute('shortName')
|
||||||
|
alliance.member_count = alliance_node.getAttribute('memberCount')
|
||||||
|
alliance.date_founded = datetime.strptime(alliance_node.getAttribute('startDate'),
|
||||||
|
'%Y-%m-%d %H:%M:%S')
|
||||||
|
alliance.save()
|
||||||
|
# Update member corp alliance attributes.
|
||||||
|
__update_corp_from_alliance_node(alliance_node, alliance)
|
||||||
|
|
||||||
|
print "Alliances and member corps updated."
|
||||||
|
print "Removing corps alliance memberships that are no longer valid..."
|
||||||
|
__remove_invalid_corp_alliance_memberships()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
__start_full_import()
|
||||||
55
eve_api/api_puller/corps.py
Executable file
55
eve_api/api_puller/corps.py
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Module for updating corp information. If this is ran directly, the module will
|
||||||
|
iterate through all known alliances, looking at the corps in each alliance's
|
||||||
|
member list. This can be very time-consuming and should not be done often.
|
||||||
|
|
||||||
|
Within your applications, you may call query_and_update_corp() to update
|
||||||
|
an individual corp object as need be.
|
||||||
|
|
||||||
|
NOTE: To get corp data, it must be a member of an alliance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Only mess with the environmental stuff if this is being ran directly.
|
||||||
|
from importer_path import fix_environment
|
||||||
|
fix_environment()
|
||||||
|
|
||||||
|
from eve_api.models import EVEPlayerAlliance, EVEPlayerCorporation
|
||||||
|
|
||||||
|
def start_full_import():
|
||||||
|
"""
|
||||||
|
Imports all of the corps that are in all of the known alliances.
|
||||||
|
|
||||||
|
WARNING: THIS WILL TAKE A _LONG_ TIME AND MUST BE RAN AFTER
|
||||||
|
eve_db.api_puller.alliances.__start_full_import() OR YOU WON'T GET ALL
|
||||||
|
OF THE CORPS (or any at all).
|
||||||
|
"""
|
||||||
|
alliances = EVEPlayerAlliance.objects.all()
|
||||||
|
|
||||||
|
# These two variables are used to track progress.
|
||||||
|
alliance_count = alliances.count()
|
||||||
|
# Use this as a progress indicator.
|
||||||
|
current_alliance_num = 1
|
||||||
|
|
||||||
|
for alliance in alliances:
|
||||||
|
# Keep the user informed as to the progress.
|
||||||
|
print "Alliance %d of %d..." % (current_alliance_num, alliance_count)
|
||||||
|
# A list of the alliance's member corps.
|
||||||
|
member_corps = alliance.eveplayercorporation_set.all()
|
||||||
|
# We're getting the list of corps to update from alliance memberships.
|
||||||
|
for corp in member_corps:
|
||||||
|
print "Querying", corp.id
|
||||||
|
corp.query_and_update_corp()
|
||||||
|
|
||||||
|
# Increment progress counter.
|
||||||
|
current_alliance_num += 1
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
"""
|
||||||
|
If ran directly, this will grab all of the corps from the known alliances.
|
||||||
|
|
||||||
|
WARNING: THIS WILL TAKE A VERY LONG TIME TO RUN! IT IS SUGGESTED YOU ONLY
|
||||||
|
GRAB CORPS AS YOU NEED THEM.
|
||||||
|
"""
|
||||||
|
start_full_import()
|
||||||
16
eve_api/api_puller/importer_path.py
Normal file
16
eve_api/api_puller/importer_path.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
# The path to the folder containing settings.py.
|
||||||
|
BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||||
|
APPS_PATH = os.path.join(BASE_PATH, 'apps')
|
||||||
|
|
||||||
|
def fix_environment():
|
||||||
|
"""
|
||||||
|
Callable function to set up all of the Django environmental variables and
|
||||||
|
pathing for directly executable python modules.
|
||||||
|
"""
|
||||||
|
from importer_path import BASE_PATH
|
||||||
|
# Prepare the environment
|
||||||
|
sys.path.insert(0, APPS_PATH)
|
||||||
|
sys.path.insert(0, BASE_PATH)
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||||
15
eve_api/app_defines.py
Normal file
15
eve_api/app_defines.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Standard definitions that don't change.
|
||||||
|
"""
|
||||||
|
# API status definitions for EVEAccount.
|
||||||
|
API_STATUS_PENDING = 0
|
||||||
|
API_STATUS_OK = 1
|
||||||
|
API_STATUS_AUTH_ERROR = 2
|
||||||
|
API_STATUS_OTHER_ERROR = 3
|
||||||
|
# This tuple is used to assemble the choices list for the field.
|
||||||
|
API_STATUS_CHOICES = (
|
||||||
|
(API_STATUS_PENDING, 'Unknown'),
|
||||||
|
(API_STATUS_OK, 'OK'),
|
||||||
|
(API_STATUS_AUTH_ERROR, 'Auth Error'),
|
||||||
|
(API_STATUS_OTHER_ERROR, 'Other Error'),
|
||||||
|
)
|
||||||
96
eve_api/managers.py
Normal file
96
eve_api/managers.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
from xml.dom import minidom
|
||||||
|
from django.db import models
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
|
||||||
|
class InvalidCorpID(Exception):
|
||||||
|
"""
|
||||||
|
Thrown when an invalid corp id is given in an api query.
|
||||||
|
"""
|
||||||
|
def __init__(self, id):
|
||||||
|
self.value = "ID: %s does not match any corporation." % id
|
||||||
|
|
||||||
|
def __str___(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
def _api_get_id_from_name(name):
|
||||||
|
"""
|
||||||
|
Queries the EVE API looking for the ID of the specified corporation,
|
||||||
|
alliance, or character based on its name. This is not case sensitive.
|
||||||
|
|
||||||
|
name: (str) Corporation name to search for.
|
||||||
|
"""
|
||||||
|
query_doc = CachedDocument.objects.api_query('/eve/CharacterID.xml.aspx',
|
||||||
|
params={'names': name})
|
||||||
|
query_dat = query_doc.body.decode("utf-8", "replace")
|
||||||
|
dom = minidom.parseString(query_dat)
|
||||||
|
|
||||||
|
id_node = dom.getElementsByTagName('row')[0]
|
||||||
|
object_id = id_node.getAttribute('characterID')
|
||||||
|
|
||||||
|
if object_id == '0':
|
||||||
|
raise self.model.DoesNotExist('EVE API returned no matches for the provided corp name.')
|
||||||
|
else:
|
||||||
|
return int(object_id)
|
||||||
|
|
||||||
|
class EVEPlayerCharacterManager(models.Manager):
|
||||||
|
def api_get_id_from_name(self, name):
|
||||||
|
"""
|
||||||
|
This uses a common call for corps, characters, and alliances.
|
||||||
|
"""
|
||||||
|
return _api_get_id_from_name(name)
|
||||||
|
|
||||||
|
class EVEPlayerAllianceManager(models.Manager):
|
||||||
|
def api_get_id_from_name(self, name):
|
||||||
|
"""
|
||||||
|
This uses a common call for corps, characters, and alliances.
|
||||||
|
"""
|
||||||
|
return _api_get_id_from_name(name)
|
||||||
|
|
||||||
|
class EVEPlayerCorporationManager(models.Manager):
|
||||||
|
def get_or_query_by_id(self, corp_id):
|
||||||
|
"""
|
||||||
|
Queries for a corporation. If the corp can't be founded, check the
|
||||||
|
EVE API service for information on it. If a match still can't be
|
||||||
|
found, return EVEPlayerCorporation.DoesNotExist.
|
||||||
|
|
||||||
|
corp_id: (int) Corp's ID.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self.get(id=corp_id)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
try:
|
||||||
|
self.api_corp_sheet_xml(corp_id)
|
||||||
|
new_corp = self.create(id=corp_id)
|
||||||
|
new_corp.query_and_update_corp()
|
||||||
|
return new_corp
|
||||||
|
except InvalidCorpID:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def api_get_id_from_name(self, name):
|
||||||
|
"""
|
||||||
|
This uses a common call for corps, characters, and alliances.
|
||||||
|
"""
|
||||||
|
return _api_get_id_from_name(name)
|
||||||
|
|
||||||
|
def api_corp_sheet_xml(self, id):
|
||||||
|
"""
|
||||||
|
Returns a corp's data sheet from the EVE API in the form of an XML
|
||||||
|
minidom doc.
|
||||||
|
"""
|
||||||
|
corp_doc = CachedDocument.objects.api_query('/corp/CorporationSheet.xml.aspx',
|
||||||
|
params={'corporationID': id})
|
||||||
|
corp_dat = corp_doc.body.decode("utf-8", "replace")
|
||||||
|
|
||||||
|
# Convert incoming data to UTF-8.
|
||||||
|
dom = minidom.parseString(corp_dat)
|
||||||
|
|
||||||
|
error_node = dom.getElementsByTagName('error')
|
||||||
|
|
||||||
|
# If there's an error, see if it's because the corp doesn't exist.
|
||||||
|
if error_node:
|
||||||
|
error_code = error_node[0].getAttribute('code')
|
||||||
|
if error_code == '523':
|
||||||
|
raise InvalidCorpID(id)
|
||||||
|
|
||||||
|
return dom
|
||||||
|
|
||||||
6
eve_api/models/__init__.py
Normal file
6
eve_api/models/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
"""
|
||||||
|
By importing all of these sub-modules, the models package is transparently
|
||||||
|
accessible by the rest of the project. This makes it act just as if it were
|
||||||
|
one monolithic models.py.
|
||||||
|
"""
|
||||||
|
from api_player import *
|
||||||
195
eve_api/models/api_player.py
Normal file
195
eve_api/models/api_player.py
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
"""
|
||||||
|
This module holds data from the EVE XML API.
|
||||||
|
"""
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
from eve_api.managers import EVEPlayerCorporationManager, EVEPlayerAllianceManager, EVEPlayerCharacterManager
|
||||||
|
from eve_api.app_defines import API_STATUS_CHOICES, API_STATUS_PENDING
|
||||||
|
|
||||||
|
class EVEAPIModel(models.Model):
|
||||||
|
"""
|
||||||
|
A simple abstract base class to set some consistent fields on the models
|
||||||
|
that are updated from the EVE API.
|
||||||
|
"""
|
||||||
|
api_last_updated = models.DateTimeField(blank=True, null=True,
|
||||||
|
verbose_name="Time last updated from API",
|
||||||
|
help_text="When this object was last updated from the EVE API.")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
class EVEAccount(EVEAPIModel):
|
||||||
|
"""
|
||||||
|
Use this class to store EVE user account information. Note that its use is
|
||||||
|
entirely optional and up to the developer's discretion.
|
||||||
|
"""
|
||||||
|
user = models.ForeignKey(User, blank=True, null=True,
|
||||||
|
help_text="User that owns this account")
|
||||||
|
description = models.CharField(max_length=50, blank=True,
|
||||||
|
help_text="User-provided description.")
|
||||||
|
api_key = models.CharField(max_length=64, verbose_name="API Key")
|
||||||
|
api_user_id = models.IntegerField(verbose_name="API User ID")
|
||||||
|
characters = models.ManyToManyField("EVEPlayerCharacter", blank=True,
|
||||||
|
null=True)
|
||||||
|
api_status = models.IntegerField(choices=API_STATUS_CHOICES,
|
||||||
|
default=API_STATUS_PENDING,
|
||||||
|
verbose_name="API Status",
|
||||||
|
help_text="End result of the last attempt at updating this object from the API.")
|
||||||
|
|
||||||
|
def in_corp(self, corpid):
|
||||||
|
for char in self.characters.all():
|
||||||
|
if char.corporation_id == corpid:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'eve_api'
|
||||||
|
verbose_name = 'EVE Account'
|
||||||
|
verbose_name_plural = 'EVE Accounts'
|
||||||
|
ordering = ['api_user_id']
|
||||||
|
|
||||||
|
class EVEPlayerCharacter(EVEAPIModel):
|
||||||
|
"""
|
||||||
|
Represents an individual player character within the game. Not to be
|
||||||
|
confused with an account.
|
||||||
|
"""
|
||||||
|
name = models.CharField(max_length=255, blank=True, null=False)
|
||||||
|
corporation = models.ForeignKey('EVEPlayerCorporation', blank=True, null=True)
|
||||||
|
# TODO: Choices field
|
||||||
|
race = models.IntegerField(blank=True, null=True)
|
||||||
|
# TODO: Choices field
|
||||||
|
gender = models.IntegerField(blank=True, null=True)
|
||||||
|
balance = models.FloatField("Account Balance", blank=True, null=True)
|
||||||
|
attrib_intelligence = models.IntegerField("Intelligence", blank=True,
|
||||||
|
null=True)
|
||||||
|
attrib_memory = models.IntegerField("Memory", blank=True, null=True)
|
||||||
|
attrib_charisma = models.IntegerField("Charisma", blank=True, null=True)
|
||||||
|
attrib_perception = models.IntegerField("Perception", blank=True, null=True)
|
||||||
|
attrib_willpower = models.IntegerField("Willpower", blank=True, null=True)
|
||||||
|
|
||||||
|
objects = EVEPlayerCharacterManager()
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
if self.name:
|
||||||
|
return "%s (%d)" % (self.name, self.id)
|
||||||
|
else:
|
||||||
|
return "(%d)" % self.id
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__unicode__()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'eve_api'
|
||||||
|
verbose_name = 'Player Character'
|
||||||
|
verbose_name_plural = 'Player Characters'
|
||||||
|
|
||||||
|
class EVEPlayerAlliance(EVEAPIModel):
|
||||||
|
"""
|
||||||
|
Represents a player-controlled alliance. Updated from the alliance
|
||||||
|
EVE XML API puller at intervals.
|
||||||
|
"""
|
||||||
|
name = models.CharField(max_length=255, blank=True, null=False)
|
||||||
|
ticker = models.CharField(max_length=15, blank=True, null=False)
|
||||||
|
#executor_character = models.ForeignKey(EVECharacter, blank=True, null=False)
|
||||||
|
member_count = models.IntegerField(blank=True, null=True)
|
||||||
|
date_founded = models.DateField(blank=True, null=True)
|
||||||
|
|
||||||
|
objects = EVEPlayerAllianceManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'eve_api'
|
||||||
|
ordering = ['date_founded']
|
||||||
|
verbose_name = 'Player Alliance'
|
||||||
|
verbose_name_plural = 'Player Alliances'
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
if self.name:
|
||||||
|
return "%s (%d)" % (self.name, self.id)
|
||||||
|
else:
|
||||||
|
return "(#%d)" % self.id
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__unicode__()
|
||||||
|
|
||||||
|
class EVEPlayerCorporation(EVEAPIModel):
|
||||||
|
"""
|
||||||
|
Represents a player-controlled corporation. Updated from a mixture of
|
||||||
|
the alliance and corporation API pullers.
|
||||||
|
"""
|
||||||
|
name = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
ticker = models.CharField(max_length=15, blank=True, null=True)
|
||||||
|
description = models.TextField(blank=True, null=True)
|
||||||
|
url = models.URLField(verify_exists=False, blank=True, null=True)
|
||||||
|
ceo_character = models.ForeignKey(EVEPlayerCharacter, blank=True, null=True)
|
||||||
|
#home_station = models.ForeignKey(EVEStation, blank=True, null=False)
|
||||||
|
alliance = models.ForeignKey(EVEPlayerAlliance, blank=True, null=True)
|
||||||
|
alliance_join_date = models.DateField(blank=True, null=True)
|
||||||
|
tax_rate = models.FloatField(blank=True, null=True)
|
||||||
|
member_count = models.IntegerField(blank=True, null=True)
|
||||||
|
shares = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
# Logo generation stuff
|
||||||
|
logo_graphic_id = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_shape1 = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_shape2 = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_shape3 = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_color1 = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_color2 = models.IntegerField(blank=True, null=True)
|
||||||
|
logo_color3 = models.IntegerField(blank=True, null=True)
|
||||||
|
|
||||||
|
objects = EVEPlayerCorporationManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = 'eve_api'
|
||||||
|
verbose_name = 'Player Corporation'
|
||||||
|
verbose_name_plural = 'Player Corporations'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.name:
|
||||||
|
return self.name
|
||||||
|
else:
|
||||||
|
return "Corp #%d" % self.id
|
||||||
|
|
||||||
|
def query_and_update_corp(self):
|
||||||
|
"""
|
||||||
|
Takes an EVEPlayerCorporation object and updates it from the
|
||||||
|
EVE API service.
|
||||||
|
"""
|
||||||
|
# Pull XML from the EVE API via eve_proxy.
|
||||||
|
dom = EVEPlayerCorporation.objects.api_corp_sheet_xml(self.id)
|
||||||
|
|
||||||
|
# Tuples of pairings of tag names and the attribute on the Corporation
|
||||||
|
# object to set the data to.
|
||||||
|
tag_mappings = (
|
||||||
|
('corporationName', 'name'),
|
||||||
|
('ticker', 'ticker'),
|
||||||
|
('url', 'url'),
|
||||||
|
('description', 'description'),
|
||||||
|
('memberCount', 'member_count'),
|
||||||
|
('graphicID', 'logo_graphic_id'),
|
||||||
|
('shape1', 'logo_shape1'),
|
||||||
|
('shape2', 'logo_shape2'),
|
||||||
|
('shape3', 'logo_shape3'),
|
||||||
|
('color1', 'logo_color1'),
|
||||||
|
('color2', 'logo_color2'),
|
||||||
|
('color3', 'logo_color3'),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Iterate through the tag mappings, setting the values of the tag names
|
||||||
|
# (first member of the tuple) to the attribute named in the second member
|
||||||
|
# of the tuple on the EVEPlayerCorporation object.
|
||||||
|
for tag_map in tag_mappings:
|
||||||
|
try:
|
||||||
|
setattr(self, tag_map[1],
|
||||||
|
dom.getElementsByTagName(tag_map[0])[0].firstChild.nodeValue)
|
||||||
|
except AttributeError:
|
||||||
|
# This tag has no value, skip it.
|
||||||
|
continue
|
||||||
|
except IndexError:
|
||||||
|
# Something weird has happened
|
||||||
|
print " * Index Error:", tag_map[0]
|
||||||
|
continue
|
||||||
|
|
||||||
|
print "Updating", self.id, self.name
|
||||||
|
self.save()
|
||||||
9
eve_proxy/__init__.py
Executable file
9
eve_proxy/__init__.py
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
VERSION = (0, 4)
|
||||||
|
|
||||||
|
# Dynamically calculate the version based on VERSION tuple
|
||||||
|
if len(VERSION)>2 and VERSION[2] is not None:
|
||||||
|
str_version = "%d.%d_%s" % VERSION[:3]
|
||||||
|
else:
|
||||||
|
str_version = "%d.%d" % VERSION[:2]
|
||||||
|
|
||||||
|
__version__ = str_version
|
||||||
9
eve_proxy/admin.py
Executable file
9
eve_proxy/admin.py
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
|
||||||
|
class CachedDocumentAdmin(admin.ModelAdmin):
|
||||||
|
model = CachedDocument
|
||||||
|
list_display = ('url_path', 'time_retrieved', 'cached_until')
|
||||||
|
verbose_name = 'Cached Document'
|
||||||
|
verbose_name_plural = 'Cached Documents'
|
||||||
|
admin.site.register(CachedDocument, CachedDocumentAdmin)
|
||||||
126
eve_proxy/models.py
Executable file
126
eve_proxy/models.py
Executable file
@@ -0,0 +1,126 @@
|
|||||||
|
import httplib
|
||||||
|
import urllib
|
||||||
|
import xml
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from xml.dom import minidom
|
||||||
|
from django.db import models
|
||||||
|
from eve_api.api_exceptions import APIAuthException, APINoUserIDException
|
||||||
|
|
||||||
|
# You generally never want to change this unless you have a very good reason.
|
||||||
|
API_URL = 'api.eve-online.com'
|
||||||
|
|
||||||
|
class CachedDocumentManager(models.Manager):
|
||||||
|
"""
|
||||||
|
This manager handles querying or retrieving CachedDocuments.
|
||||||
|
"""
|
||||||
|
def cache_from_eve_api(self, cached_doc, url_path, params, no_cache=False):
|
||||||
|
"""
|
||||||
|
Connect to the EVE API server, send the request, and cache it to
|
||||||
|
a CachedDocument. This is typically not something you want to call
|
||||||
|
directly. Use api_query().
|
||||||
|
"""
|
||||||
|
headers = {"Content-type": "application/x-www-form-urlencoded"}
|
||||||
|
# This is the connection to the EVE API server.
|
||||||
|
conn = httplib.HTTPConnection(API_URL)
|
||||||
|
# Combine everything into an HTTP request.
|
||||||
|
conn.request("POST", url_path, params, headers)
|
||||||
|
# Retrieve the response from the server.
|
||||||
|
response = conn.getresponse()
|
||||||
|
# Save the response (an XML document) to the CachedDocument.
|
||||||
|
cached_doc.body = response.read()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Parse the response via minidom
|
||||||
|
dom = minidom.parseString(cached_doc.body)
|
||||||
|
except xml.parsers.expat.ExpatError:
|
||||||
|
print "XML Parser Error:"
|
||||||
|
print cached_doc.body
|
||||||
|
return
|
||||||
|
|
||||||
|
# Set the CachedDocument's time_retrieved and cached_until times based
|
||||||
|
# on the values in the XML response. This will be used in future
|
||||||
|
# requests to see if the CachedDocument can be retrieved directly or
|
||||||
|
# if it needs to be re-cached.
|
||||||
|
cached_doc.time_retrieved = datetime.utcnow()
|
||||||
|
cached_doc.cached_until = dom.getElementsByTagName('cachedUntil')[0].childNodes[0].nodeValue
|
||||||
|
|
||||||
|
# Finish up and return the resulting document just in case.
|
||||||
|
if no_cache == False:
|
||||||
|
cached_doc.save()
|
||||||
|
|
||||||
|
return dom
|
||||||
|
|
||||||
|
def api_query(self, url_path, params=None, no_cache=False):
|
||||||
|
"""
|
||||||
|
Transparently handles querying EVE API or retrieving the document from
|
||||||
|
the cache.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
url_path: (string) Path to the EVE API page to query. For example:
|
||||||
|
/eve/ErrorList.xml.aspx
|
||||||
|
params: (dictionary/string) A dictionary of extra parameters to include.
|
||||||
|
May also be a string representation of
|
||||||
|
the query: userID=1&characterID=xxxxxxxx
|
||||||
|
"""
|
||||||
|
if type({}) == type(params):
|
||||||
|
# If 'params' is a dictionary, convert it to a URL string.
|
||||||
|
params = urllib.urlencode(params)
|
||||||
|
elif params == None or params.strip() == '':
|
||||||
|
# For whatever reason, EVE API freaks out if there are no parameters.
|
||||||
|
# Add a bogus parameter if none are specified. I'm sure there's a
|
||||||
|
# better fix for this.
|
||||||
|
params = 'odd_parm=1'
|
||||||
|
|
||||||
|
# Combine the URL path and the parameters to create the full query.
|
||||||
|
query_name = '%s?%s' % (url_path, params)
|
||||||
|
|
||||||
|
if no_cache:
|
||||||
|
# If no_cache is enabled, don't even attempt a lookup.
|
||||||
|
cached_doc = CachedDocument()
|
||||||
|
created = False
|
||||||
|
else:
|
||||||
|
# Retrieve or create a new CachedDocument based on the full URL
|
||||||
|
# and parameters.
|
||||||
|
cached_doc, created = self.get_or_create(url_path=query_name)
|
||||||
|
|
||||||
|
# EVE uses UTC.
|
||||||
|
current_eve_time = datetime.utcnow()
|
||||||
|
|
||||||
|
# Figure out if we need hit EVE API and re-cache, or just pull from
|
||||||
|
# the local cache (based on cached_until).
|
||||||
|
if no_cache or created or \
|
||||||
|
cached_doc.cached_until == None or \
|
||||||
|
current_eve_time > cached_doc.cached_until:
|
||||||
|
# Cache from EVE API
|
||||||
|
dom = self.cache_from_eve_api(cached_doc, url_path, params,
|
||||||
|
no_cache=no_cache)
|
||||||
|
else:
|
||||||
|
# Parse the document here since it was retrieved from the
|
||||||
|
# database cache instead of queried for.
|
||||||
|
dom = minidom.parseString(cached_doc.body)
|
||||||
|
|
||||||
|
# Check for the presence errors. Only check the bare minimum,
|
||||||
|
# generic stuff that applies to most or all queries. User-level code
|
||||||
|
# should check for the more specific errors.
|
||||||
|
error_node = dom.getElementsByTagName('error')
|
||||||
|
if error_node:
|
||||||
|
error_code = error_node[0].getAttribute('code')
|
||||||
|
# User specified an invalid userid and/or auth key.
|
||||||
|
if error_code == '203':
|
||||||
|
raise APIAuthException()
|
||||||
|
elif error_code == '106':
|
||||||
|
raise APINoUserIDException()
|
||||||
|
|
||||||
|
return cached_doc
|
||||||
|
|
||||||
|
class CachedDocument(models.Model):
|
||||||
|
"""
|
||||||
|
This is a cached XML document from the EVE API.
|
||||||
|
"""
|
||||||
|
url_path = models.CharField(max_length=255)
|
||||||
|
body = models.TextField()
|
||||||
|
time_retrieved = models.DateTimeField(blank=True, null=True)
|
||||||
|
cached_until = models.DateTimeField(blank=True, null=True)
|
||||||
|
|
||||||
|
# The custom manager handles the querying.
|
||||||
|
objects = CachedDocumentManager()
|
||||||
8
eve_proxy/urls.py
Executable file
8
eve_proxy/urls.py
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
urlpatterns = patterns('eve_proxy.views',
|
||||||
|
# This view can be used just like EVE API's http://api.eve-online.com.
|
||||||
|
# Any parameters or URL paths are sent through the cache system and
|
||||||
|
# forwarded to the EVE API site as needed.
|
||||||
|
url(r'^', 'retrieve_xml', name='eve_proxy-retrieve_xml'),
|
||||||
|
)
|
||||||
22
eve_proxy/views.py
Executable file
22
eve_proxy/views.py
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
|
from eve_proxy.models import CachedDocument
|
||||||
|
|
||||||
|
def retrieve_xml(request):
|
||||||
|
"""
|
||||||
|
A view that forwards EVE API requests through the cache system, either
|
||||||
|
retrieving a cached document or querying and caching as needed.
|
||||||
|
"""
|
||||||
|
# This is the URL path (minus the parameters).
|
||||||
|
url_path = request.META['PATH_INFO']
|
||||||
|
# The parameters attached to the end of the URL path.
|
||||||
|
params = request.META['QUERY_STRING']
|
||||||
|
|
||||||
|
if url_path == '/' or url_path == '':
|
||||||
|
# If they don't provide any kind of query, shoot a quick error message.
|
||||||
|
return HttpResponse('No API query specified.')
|
||||||
|
|
||||||
|
# The query system will retrieve a cached_doc that was either previously
|
||||||
|
# or newly cached depending on cache intervals.
|
||||||
|
cached_doc = CachedDocument.objects.api_query(url_path, params)
|
||||||
|
# Return the document's body as XML.
|
||||||
|
return HttpResponse(cached_doc.body, mimetype='text/xml')
|
||||||
11
manage.py
Executable file
11
manage.py
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
from django.core.management import execute_manager
|
||||||
|
try:
|
||||||
|
import settings # Assumed to be in the same directory.
|
||||||
|
except ImportError:
|
||||||
|
import sys
|
||||||
|
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
execute_manager(settings)
|
||||||
85
settings.py
Normal file
85
settings.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Django settings for login project.
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
TEMPLATE_DEBUG = DEBUG
|
||||||
|
|
||||||
|
ADMINS = (
|
||||||
|
# ('Your Name', 'your_email@domain.com'),
|
||||||
|
)
|
||||||
|
|
||||||
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
|
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||||
|
DATABASE_NAME = '/home/dreddit/www/login.dredd.it/login.db3' # Or path to database file if using sqlite3.
|
||||||
|
DATABASE_USER = '' # Not used with sqlite3.
|
||||||
|
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||||
|
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||||
|
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||||
|
|
||||||
|
# Local time zone for this installation. Choices can be found here:
|
||||||
|
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
||||||
|
# although not all choices may be available on all operating systems.
|
||||||
|
# If running in a Windows environment this must be set to the same as your
|
||||||
|
# system time zone.
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
# Language code for this installation. All choices can be found here:
|
||||||
|
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
SITE_ID = 1
|
||||||
|
|
||||||
|
# If you set this to False, Django will make some optimizations so as not
|
||||||
|
# to load the internationalization machinery.
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
# Absolute path to the directory that holds media.
|
||||||
|
# Example: "/home/media/media.lawrence.com/"
|
||||||
|
MEDIA_ROOT = ''
|
||||||
|
|
||||||
|
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||||
|
# trailing slash if there is a path component (optional in other cases).
|
||||||
|
# Examples: "http://media.lawrence.com", "http://example.com/media/"
|
||||||
|
MEDIA_URL = ''
|
||||||
|
|
||||||
|
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
|
||||||
|
# trailing slash.
|
||||||
|
# Examples: "http://foo.com/media/", "/media/".
|
||||||
|
ADMIN_MEDIA_PREFIX = '/media/'
|
||||||
|
|
||||||
|
# Make this unique, and don't share it with anybody.
|
||||||
|
SECRET_KEY = '8i2+dd-b2tg9g%mq$&i$-8beh4i5^2mm=e-nh^$p47^w=z1igr'
|
||||||
|
|
||||||
|
# List of callables that know how to import templates from various sources.
|
||||||
|
TEMPLATE_LOADERS = (
|
||||||
|
'django.template.loaders.filesystem.load_template_source',
|
||||||
|
'django.template.loaders.app_directories.load_template_source',
|
||||||
|
# 'django.template.loaders.eggs.load_template_source',
|
||||||
|
)
|
||||||
|
|
||||||
|
MIDDLEWARE_CLASSES = (
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
)
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'login.urls'
|
||||||
|
|
||||||
|
TEMPLATE_DIRS = (
|
||||||
|
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||||
|
# Always use forward slashes, even on Windows.
|
||||||
|
# Don't forget to use absolute paths, not relative paths.
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS = (
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.sites',
|
||||||
|
'registration',
|
||||||
|
'eve_proxy',
|
||||||
|
'eve_api',
|
||||||
|
'sso',
|
||||||
|
)
|
||||||
|
|
||||||
|
AUTH_PROFILE_MODULE = 'sso.UserProfile'
|
||||||
0
sso/__init__.py
Normal file
0
sso/__init__.py
Normal file
18
sso/models.py
Normal file
18
sso/models.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from eve_api.models.api_player import EVEAccount
|
||||||
|
|
||||||
|
class UserProfile(User):
|
||||||
|
eveaccount = models.ForeignKey(EVEAccount)
|
||||||
|
|
||||||
|
class Site(models.Model):
|
||||||
|
url = models.CharField(max_length=200)
|
||||||
|
active = models.BooleanField()
|
||||||
|
api = models.CharField(max_length=200)
|
||||||
|
|
||||||
|
class SiteAccount(models.Model):
|
||||||
|
user = models.ForeignKey(UserProfile)
|
||||||
|
site = models.ForeignKey(Site)
|
||||||
|
username = models.CharField(max_length=200)
|
||||||
|
active = models.BooleanField()
|
||||||
|
|
||||||
23
sso/tests.py
Normal file
23
sso/tests.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"""
|
||||||
|
This file demonstrates two different styles of tests (one doctest and one
|
||||||
|
unittest). These will both pass when you run "manage.py test".
|
||||||
|
|
||||||
|
Replace these with more appropriate tests for your application.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
class SimpleTest(TestCase):
|
||||||
|
def test_basic_addition(self):
|
||||||
|
"""
|
||||||
|
Tests that 1 + 1 always equals 2.
|
||||||
|
"""
|
||||||
|
self.failUnlessEqual(1 + 1, 2)
|
||||||
|
|
||||||
|
__test__ = {"doctest": """
|
||||||
|
Another way to test that 1 + 1 is equal to 2.
|
||||||
|
|
||||||
|
>>> 1 + 1 == 2
|
||||||
|
True
|
||||||
|
"""}
|
||||||
|
|
||||||
1
sso/views.py
Normal file
1
sso/views.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Create your views here.
|
||||||
11
urls.py
Normal file
11
urls.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
# Uncomment the next two lines to enable the admin:
|
||||||
|
from django.contrib import admin
|
||||||
|
admin.autodiscover()
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^login/', include('django.contrib.auth.views.login')),
|
||||||
|
|
||||||
|
(r'^admin/', include(admin.site.urls)),
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user