Skip to content

Commit

Permalink
Make "app" optionnal in security
Browse files Browse the repository at this point in the history
This introduce a breaking change, since app is no longer required and in first position
Also increase version to 0.2.0
#20
  • Loading branch information
Kyria committed Oct 22, 2017
1 parent 2c80af5 commit d254a61
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 56 deletions.
2 changes: 1 addition & 1 deletion esipy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
# Not installed or in install (not yet installed) so ignore
pass

__version__ = '0.1.8'
__version__ = '0.2.0'
70 changes: 41 additions & 29 deletions esipy/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,63 @@ class EsiSecurity(object):

def __init__(
self,
app,
redirect_uri,
client_id,
secret_key,
app=None,
ssoUrl="https://login.eveonline.com",
esiUrl="https://esi.tech.ccp.is",
security_name="evesso"):
""" Init the ESI Security Object
:param app: the pyswagger app object
:param redirect_uri: the uri to redirect the user after login into SSO
:param client_id: the OAuth2 client ID
:param secret_key: the OAuth2 secret key
:param ssoUrl: the default sso URL used when no "app" is provided
:param esiUrl: the default esi URL used for verify endpoint
:param app: (optionnal) the pyswagger app object
:param security_name: (optionnal) the name of the object holding the
informations in the securityDefinitions.
informations in the securityDefinitions, used to check authed endpoint
"""
# check if the security_name actually exists in the securityDefinition
security = app.root.securityDefinitions.get(security_name, None)
if security is None:
raise NameError(
"%s is not defined in the securityDefinitions" % security_name
)

self.app = app
self.security_name = security_name
self.redirect_uri = redirect_uri
self.client_id = client_id
self.secret_key = secret_key

# some URL we still need to "manually" define... sadly
# we parse the authUrl so we don't care if it's TQ or SISI.
parsed_uri = urlparse(security.authorizationUrl)
self.oauth_verify = '%s://%s/oauth/verify' % (
parsed_uri.scheme,
parsed_uri.netloc
)
# we provide app object, so we don't use ssoUrl
if app is not None:
# check if the security_name exists in the securityDefinition
security = app.root.securityDefinitions.get(security_name, None)
if security is None:
raise NameError(
"%s is not defined in the securityDefinitions" %
security_name
)

# should be: security_definition.tokenUrl
# but not yet implemented by CCP in ESI so we need the full URL...
# https://github.com/ccpgames/esi-issues/issues/92
self.oauth_token = '%s://%s/oauth/token' % (
parsed_uri.scheme,
parsed_uri.netloc
)
self.oauth_authorize = security.authorizationUrl

# some URL we still need to "manually" define... sadly
# we parse the authUrl so we don't care if it's TQ or SISI.
# https://github.com/ccpgames/esi-issues/issues/92
parsed_uri = urlparse(security.authorizationUrl)
self.oauth_token = '%s://%s/oauth/token' % (
parsed_uri.scheme,
parsed_uri.netloc
)

# no app object is provided, so we use direct URLs
else:
if ssoUrl is None or ssoUrl == "":
raise AttributeError("ssoUrl cannot be None or empty "
"without app parameter")

self.oauth_authorize = '%s/oauth/authorize' % ssoUrl
self.oauth_token = '%s/oauth/token' % ssoUrl

# use ESI url for verify, since it's better for caching
if esiUrl is None or esiUrl == "":
raise AttributeError("esiUrl cannot be None or empty")
self.oauth_verify = '%s/verify/' % esiUrl

# session request stuff
self._session = Session()
Expand Down Expand Up @@ -121,15 +136,12 @@ def get_auth_uri(self, scopes=None, state=None, implicit=False):
:param state: The state to pass through the auth process
:return: the authorizationUrl with the correct parameters.
"""
security_definition = self.app.root.securityDefinitions.get(
self.security_name
)
s = [] if not scopes else scopes

response_type = 'code' if not implicit else 'token'

return '%s?response_type=%s&redirect_uri=%s&client_id=%s%s%s' % (
security_definition.authorizationUrl,
self.oauth_authorize,
response_type,
quote(self.redirect_uri, safe=''),
self.client_id,
Expand Down
8 changes: 4 additions & 4 deletions test/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def oauth_token(url, request):

@httmock.urlmatch(
scheme="https",
netloc=r"login\.eveonline\.com$",
path=r"^/oauth/verify$"
netloc=r"esi\.tech\.ccp\.is$",
path=r"^/verify/$"
)
def oauth_verify(url, request):
return httmock.response(
Expand All @@ -64,8 +64,8 @@ def oauth_verify(url, request):

@httmock.urlmatch(
scheme="https",
netloc=r"login\.eveonline\.com$",
path=r"^/oauth/verify$"
netloc=r"esi\.tech\.ccp\.is$",
path=r"^/verify/$"
)
def oauth_verify_fail(url, request):
return httmock.response(
Expand Down
5 changes: 1 addition & 4 deletions test/test_cache.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
# -*- encoding: utf-8 -*-
# -- Tests based on pycrest cache tests (as these are the same classes)
# -- https://github.com/pycrest/PyCrest/blob/master/tests/test_pycrest.py
from __future__ import absolute_import

import memcache
import mock
import redis
import shutil
import time
import unittest
import redis

from collections import namedtuple

Expand Down
12 changes: 6 additions & 6 deletions test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from .mock import public_incursion
from .mock import public_incursion_no_expires
from .mock import public_incursion_no_expires_second
from .mock import public_incursion_warning
from .mock import public_incursion_server_error
from .mock import public_incursion_warning
from esipy import App
from esipy import EsiClient
from esipy import EsiSecurity
Expand All @@ -19,8 +19,8 @@

import httmock
import mock
import time
import six
import time
import unittest
import warnings

Expand Down Expand Up @@ -50,10 +50,10 @@ def setUp(self, urlopen_mock):
)

self.security = EsiSecurity(
self.app,
TestEsiPy.CALLBACK_URI,
TestEsiPy.CLIENT_ID,
TestEsiPy.SECRET_KEY
app=self.app,
redirect_uri=TestEsiPy.CALLBACK_URI,
client_id=TestEsiPy.CLIENT_ID,
secret_key=TestEsiPy.SECRET_KEY,
)

self.cache = DictCache()
Expand Down
71 changes: 59 additions & 12 deletions test/test_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
class TestEsiSecurity(unittest.TestCase):
CALLBACK_URI = "https://foo.bar/baz/callback"
LOGIN_EVE = "https://login.eveonline.com"
OAUTH_VERIFY = "%s/oauth/verify" % LOGIN_EVE
OAUTH_VERIFY = "https://esi.tech.ccp.is/verify/"
OAUTH_TOKEN = "%s/oauth/token" % LOGIN_EVE
OAUTH_AUTHORIZE = "%s/oauth/authorize" % LOGIN_EVE
CLIENT_ID = 'foo'
SECRET_KEY = 'bar'
BASIC_TOKEN = six.u('Zm9vOmJhcg==')
Expand All @@ -42,20 +43,30 @@ def setUp(self, urlopen_mock):
)

self.security = EsiSecurity(
self.app,
TestEsiSecurity.CALLBACK_URI,
TestEsiSecurity.CLIENT_ID,
TestEsiSecurity.SECRET_KEY
app=self.app,
redirect_uri=TestEsiSecurity.CALLBACK_URI,
client_id=TestEsiSecurity.CLIENT_ID,
secret_key=TestEsiSecurity.SECRET_KEY,
)

def test_esisecurity_init(self):
def test_esisecurity_init_with_app(self):
""" test security init with app and URL"""
with self.assertRaises(NameError):
EsiSecurity(
self.app,
TestEsiSecurity.CALLBACK_URI,
TestEsiSecurity.CLIENT_ID,
TestEsiSecurity.SECRET_KEY,
"security_name_that_does_not_exist"
app=self.app,
redirect_uri=TestEsiSecurity.CALLBACK_URI,
client_id=TestEsiSecurity.CLIENT_ID,
secret_key=TestEsiSecurity.SECRET_KEY,
security_name="security_name_that_does_not_exist"
)

with self.assertRaises(AttributeError):
EsiSecurity(
app=self.app,
redirect_uri=TestEsiSecurity.CALLBACK_URI,
client_id=TestEsiSecurity.CLIENT_ID,
secret_key=TestEsiSecurity.SECRET_KEY,
esiUrl=""
)

self.assertEqual(
Expand All @@ -82,6 +93,41 @@ def test_esisecurity_init(self):
self.security.oauth_token,
TestEsiSecurity.OAUTH_TOKEN
)
self.assertEqual(
self.security.oauth_authorize,
TestEsiSecurity.OAUTH_AUTHORIZE
)

def test_esisecurity_other_init(self):
""" test security init without app and with urls """
with self.assertRaises(AttributeError):
EsiSecurity(
redirect_uri=TestEsiSecurity.CALLBACK_URI,
client_id=TestEsiSecurity.CLIENT_ID,
secret_key=TestEsiSecurity.SECRET_KEY,
ssoUrl=""
)

security = EsiSecurity(
redirect_uri=TestEsiSecurity.CALLBACK_URI,
client_id=TestEsiSecurity.CLIENT_ID,
secret_key=TestEsiSecurity.SECRET_KEY,
ssoUrl='foo.com',
esiUrl='bar.baz'
)

self.assertEqual(
security.oauth_verify,
"bar.baz/verify/"
)
self.assertEqual(
security.oauth_token,
"foo.com/oauth/token"
)
self.assertEqual(
security.oauth_authorize,
"foo.com/oauth/authorize"
)

def test_esisecurity_update_token(self):
self.security.update_token({
Expand All @@ -91,7 +137,7 @@ def test_esisecurity_update_token(self):
})
self.assertEqual(self.security.access_token, 'access_token')
self.assertEqual(self.security.refresh_token, 'refresh_token')
self.assertEqual(self.security.token_expiry, int(time.time()+60))
self.assertEqual(self.security.token_expiry, int(time.time() + 60))

def test_esisecurity_get_auth_uri(self):
self.assertEqual(
Expand Down Expand Up @@ -229,6 +275,7 @@ def test_esisecurity_verify(self):

def test_esisecurity_call(self):
class RequestTest(object):

def __init__(self):
self._security = []
self._p = {'header': {}}
Expand Down

0 comments on commit d254a61

Please sign in to comment.