Skip to content
This repository has been archived by the owner on Apr 12, 2023. It is now read-only.

Commit

Permalink
Merge pull request #28 from matslindh/support-imbo-users
Browse files Browse the repository at this point in the history
Support imbo users

Separates the concepts of 'user' and 'public_key', so that we can make requests based on the 'user' configured in Imbo instead of only the public key.
  • Loading branch information
matslindh authored Jan 3, 2017
2 parents 612fa98 + 34ec3ad commit 267726a
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 39 deletions.
9 changes: 5 additions & 4 deletions imboclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
from urlparse import urlparse

class Client:
def __init__(self, server_urls, public_key, private_key, version=None):
def __init__(self, server_urls, public_key, private_key, version=None, user=None):
self.server_urls = self._parse_urls(server_urls)
self._public_key = public_key
self._private_key = private_key
self._version = version
self._user = user

def metadata_url(self, image_identifier):
return metadata.UrlMetadata(self.server_urls[0], self._public_key, self._private_key, image_identifier)
return metadata.UrlMetadata(self.server_urls[0], self._public_key, self._private_key, image_identifier, user=self._user)

def status_url(self):
return status.UrlStatus(self.server_urls[0], self._public_key, self._private_key)
Expand All @@ -36,10 +37,10 @@ def user_url(self):
return user.UrlUser(self.server_urls[0], self._public_key, self._private_key)

def images_url(self):
return images.UrlImages(self.server_urls[0], self._public_key, self._private_key)
return images.UrlImages(self.server_urls[0], self._public_key, self._private_key, user=self._user)

def image_url(self, image_identifier):
return image.UrlImage(self.server_urls[0], self._public_key, self._private_key, image_identifier)
return image.UrlImage(self.server_urls[0], self._public_key, self._private_key, image_identifier, user=self._user)

def add_image(self, path):
image_file_data = self._image_file_data(path)
Expand Down
59 changes: 46 additions & 13 deletions imboclient/test/unit/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,39 @@

class TestClient:
def setup(self):
self._client = imbo.Client(['http://imbo.local'], 'public', 'private');
self._client = imbo.Client(['http://imbo.local'], 'public', 'private')
self._client_with_user = imbo.Client(['http://imbo.local'], 'public', 'private', user='foo')

def teardown(self):
self._client = None
self._client_with_user = None

def test_server_urls_generic(self):
self._client = imbo.Client(['imbo.local'], 'public', 'private');
self._client = imbo.Client(['imbo.local'], 'public', 'private')
assert self._client.server_urls[0] == 'http://imbo.local'

def test_server_urls_http(self):
self._client = imbo.Client(['http://imbo.local'], 'public', 'private');
self._client = imbo.Client(['http://imbo.local'], 'public', 'private')
assert self._client.server_urls[0] == 'http://imbo.local'

def test_server_urls_https(self):
self._client = imbo.Client(['https://imbo.local'], 'public', 'private');
self._client = imbo.Client(['https://imbo.local'], 'public', 'private')
assert self._client.server_urls[0] == 'https://imbo.local'

def test_server_urls_port_normal(self):
self._client = imbo.Client(['http://imbo.local'], 'public', 'private');
self._client = imbo.Client(['http://imbo.local'], 'public', 'private')
assert self._client.server_urls[0] == 'http://imbo.local'

def test_server_urls_port_normal_explicit(self):
self._client = imbo.Client(['http://imbo.local:80'], 'public', 'private');
self._client = imbo.Client(['http://imbo.local:80'], 'public', 'private')
assert self._client.server_urls[0] == 'http://imbo.local'

def test_server_urls_port_ssl(self):
self._client = imbo.Client(['https://imbo.local:443'], 'public', 'private');
self._client = imbo.Client(['https://imbo.local:443'], 'public', 'private')
assert self._client.server_urls[0] == 'https://imbo.local'

def test_server_urls_port_explicit_without_protocol(self):
self._client = imbo.Client(['imbo.local:8000'], 'public', 'private');
self._client = imbo.Client(['imbo.local:8000'], 'public', 'private')
assert self._client.server_urls[0] == 'http://imbo.local:8000'

@patch('imboclient.url.status.UrlStatus')
Expand All @@ -64,21 +66,54 @@ def test_user_url(self, mocked_url_user):
@patch('imboclient.url.images.UrlImages')
def test_images_url(self, mocked_url_images):
images_url = self._client.images_url()
mocked_url_images.assert_called_once_with('http://imbo.local', 'public', 'private')
mocked_url_images.assert_called_once_with('http://imbo.local', 'public', 'private', user=None)
assert images_url == mocked_url_images()

@patch('imboclient.url.images.UrlImages')
def test_images_url_with_user(self, mocked_url_images):
images_url = self._client_with_user.images_url()
mocked_url_images.assert_called_once_with('http://imbo.local', 'public', 'private', user='foo')
assert images_url == mocked_url_images()

def test_images_url_with_user_used(self):
images_url = self._client_with_user.images_url()
assert images_url.url().startswith('http://imbo.local/users/foo/images')
assert 'publicKey=public' in images_url.url()

@patch('imboclient.url.image.UrlImage')
def test_image_url(self, mocked_url_image):
image_url = self._client.image_url('ff')
mocked_url_image.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff')
mocked_url_image.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff', user=None)
assert image_url == mocked_url_image()

@patch('imboclient.url.image.UrlImage')
def test_image_url_with_user(self, mocked_url_image):
image_url = self._client_with_user.image_url('ff')
mocked_url_image.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff', user='foo')
assert image_url == mocked_url_image()

def test_image_url_with_user_used(self):
image_url = self._client_with_user.image_url('ff')
assert image_url.url().startswith('http://imbo.local/users/foo/images/ff?')
assert 'publicKey=public' in image_url.url()

@patch('imboclient.url.metadata.UrlMetadata')
def test_metadata_url(self, mocked_url_metadata):
metadata_url = self._client.metadata_url('ff')
mocked_url_metadata.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff')
mocked_url_metadata.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff', user=None)
assert metadata_url == mocked_url_metadata()

@patch('imboclient.url.metadata.UrlMetadata')
def test_metadata_url_with_user(self, mocked_url_metadata):
metadata_url = self._client_with_user.metadata_url('ff')
mocked_url_metadata.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff', user='foo')
assert metadata_url == mocked_url_metadata()

def test_metadata_url_with_user_used(self):
metadata_url = self._client_with_user.metadata_url('ff')
assert metadata_url.url().startswith('http://imbo.local/users/foo/images/ff/metadata?')
assert 'publicKey=public' in metadata_url.url()

@patch('imboclient.header.authenticate.Authenticate.headers')
@patch('imboclient.url.images.UrlImages.url')
@patch('requests.post')
Expand Down Expand Up @@ -178,7 +213,6 @@ def test_image_identifier_exists_true(self, mocked_url_image, mocked_requests_he

assert self._client.image_identifier_exists('ff') is True
mocked_requests_head.assert_called_once_with('http://imbo.local/users/public/ff?accessToken=aa')
mocked_url_image.assert_called_once_with('http://imbo.local', 'public', 'private', 'ff')

@patch('requests.head')
@patch('imboclient.url.image.UrlImage')
Expand All @@ -189,7 +223,6 @@ def test_image_identifier_exists_false(self, mocked_url_image, mocked_requests_g

assert self._client.image_identifier_exists('ffa') is False
mocked_requests_get.assert_called_once_with('http://imbo.local/users/public/ffa?accessToken=aaf')
mocked_url_image.assert_called_once_with('http://imbo.local', 'public', 'private', 'ffa')

@patch('imboclient.url.image.UrlImage.url')
@patch('requests.head')
Expand Down
6 changes: 3 additions & 3 deletions imboclient/url/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@


class UrlImage (url.Url):
def __init__(self, base_url, public_key, private_key, image_identifier):
url.Url.__init__(self, base_url, public_key, private_key)
def __init__(self, base_url, public_key, private_key, image_identifier, user=None):
url.Url.__init__(self, base_url, public_key, private_key, user=user)
self._image_identifier = image_identifier

def resource_url(self):
return self._base_url + '/users/' + self._public_key + '/images/' + self._image_identifier
return self.user_url('images/' + self._image_identifier)

def border(self, color='000000', width=1, height=1):
self.add_query_param('t[]', "border:color={},width={},height={}".format(color, width, height))
Expand Down
6 changes: 3 additions & 3 deletions imboclient/url/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@


class UrlImages (url.Url):
def __init__(self, base_url, public_key, private_key):
super(UrlImages, self).__init__(base_url, public_key, private_key)
def __init__(self, base_url, public_key, private_key, user=None):
super(UrlImages, self).__init__(base_url, public_key, private_key, user=user)

def resource_url(self):
return self._base_url + '/users/' + self._public_key + '/images.json'
return self.user_url('images.json')
6 changes: 3 additions & 3 deletions imboclient/url/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@


class UrlMetadata (url.Url):
def __init__(self, base_url, public_key, private_key, image_identifier):
url.Url.__init__(self, base_url, public_key, private_key)
def __init__(self, base_url, public_key, private_key, image_identifier, user=None):
url.Url.__init__(self, base_url, public_key, private_key, user=user)
self._image_identifier = image_identifier

def resource_url(self):
return self._base_url + '/users/' + self._public_key + '/images/' + self._image_identifier + '/' + 'metadata'
return self.user_url('images/' + self._image_identifier + '/' + 'metadata')
47 changes: 34 additions & 13 deletions imboclient/url/url.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,52 @@


class Url(object):
def __init__(self, base_url, public_key, private_key):
def __init__(self, base_url, public_key, private_key, user=None):
self._base_url = base_url
self._public_key = public_key
self._private_key = private_key
self._query_params = None
self._user = user
self._query_params = []

self.access_token = accesstoken.AccessToken()

def __str__(self):
return self.url()

def user_url(self, resource):
u = self._user if self._user else self._public_key

return self._base_url + '/users/' + u + '/' + resource

def url(self):
url = self.resource_url()
query_string = self.query_string()

if self._query_params and len(self._query_params) > 0:
url = url + '?' + query_string
# create copy of list
params = list(self._query_params)

# if we have a user, we'll have to supply the public key as a GET argument
if self._user:
params.append(('publicKey', self._public_key))

query_string = self.query_stringify(params)

if query_string:
url += '?' + query_string

if self._public_key is None or self._private_key is None:
return url

self.access_token = accesstoken.AccessToken()
generated_token = self.access_token.generate_token(url, self._private_key)
sep = '?' if not query_string else '&'

if self._query_params is None:
return url + '?accessToken=' + generated_token

return url + '&accessToken=' + generated_token
return url + sep + 'accessToken=' + generated_token

def add_query_param(self, key, value):
if self._query_params is None:
self._query_params = []

self._query_params.append((key, value))

return self

def add_query(self, query):
Expand All @@ -48,19 +62,26 @@ def add_query(self, query):
self.add_query_param('limit', query.limit())
self.add_query_param('from', query.q_from())
self.add_query_param('to', query.q_to())

if query.metadata:
self.add_query_param('query', json.dumps(query.query()))

return self

def query_string(self):
if not self._query_params:
return ''
return urlencode(self._query_params)
return self.query_stringify(self._query_params)

def resource_url(self):
raise NotImplementedError("Missing implementation. You may want to use a Url implementation instead.")

def reset(self):
self._query_params = []

return self

@classmethod
def query_stringify(cls, parameters):
if not parameters:
return ''

return urlencode(parameters)

0 comments on commit 267726a

Please sign in to comment.