Setting up base classes
Base classes added for HTTPClient and Managers. Users and UserPreferences implementation. Change-Id: Ia2beb899b752a5db22a5dc12ff55852a7764ac36
This commit is contained in:
parent
9131009a77
commit
2090a8beff
@ -2,6 +2,6 @@
|
||||
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
|
||||
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
|
||||
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
|
||||
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
|
||||
${PYTHON:-python} -m subunit.run discover -t ./ ./storyboardclient/tests $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
||||
|
@ -9,5 +9,6 @@ oslo.config>=1.4.0
|
||||
oslo.i18n>=1.0.0
|
||||
oslo.serialization>=1.0.0
|
||||
oslo.utils>=1.0.0
|
||||
requests>=2.2.0,!=2.4.0
|
||||
six>=1.7.0
|
||||
stevedore>=1.1.0
|
0
storyboardclient/auth/__init__.py
Normal file
0
storyboardclient/auth/__init__.py
Normal file
33
storyboardclient/auth/oauth.py
Normal file
33
storyboardclient/auth/oauth.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from storyboardclient.openstack.common.apiclient import auth
|
||||
|
||||
|
||||
class OAuthPlugin(auth.BaseAuthPlugin):
|
||||
|
||||
def _do_authenticate(self, http_client):
|
||||
# Skipping for now as there will be a separate spec and implementation
|
||||
# for authenticating a python client with OAuth.
|
||||
pass
|
||||
|
||||
def __init__(self, api_url=None, access_token=None):
|
||||
super(OAuthPlugin, self).__init__()
|
||||
|
||||
self.api_url = api_url
|
||||
self.access_token = access_token
|
||||
|
||||
def token_and_endpoint(self, endpoint_type=None, service_type=None):
|
||||
return self.access_token, self.api_url
|
181
storyboardclient/base.py
Normal file
181
storyboardclient/base.py
Normal file
@ -0,0 +1,181 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import inspect
|
||||
|
||||
import six
|
||||
|
||||
from storyboardclient.auth import oauth
|
||||
from storyboardclient.openstack.common.apiclient import base
|
||||
from storyboardclient.openstack.common.apiclient import client
|
||||
|
||||
DEFAULT_API_URL = "https://storyboard.openstack.org/api/v1"
|
||||
|
||||
|
||||
class BaseClient(client.BaseClient):
|
||||
|
||||
def __init__(self, api_url=None, access_token=None):
|
||||
if not api_url:
|
||||
api_url = DEFAULT_API_URL
|
||||
|
||||
self.auth_plugin = oauth.OAuthPlugin(api_url, access_token)
|
||||
self.http_client = BaseHTTPClient(auth_plugin=self.auth_plugin)
|
||||
|
||||
|
||||
class BaseHTTPClient(client.HTTPClient):
|
||||
"""Base class for setting up endpoint and token.
|
||||
|
||||
This HTTP client is overriding a client_request method to add
|
||||
Authorization header if OAuth token is provided.
|
||||
|
||||
"""
|
||||
|
||||
def client_request(self, client, method, url, **kwargs):
|
||||
"""Send an http request using `client`'s endpoint and specified `url`.
|
||||
|
||||
If request was rejected as unauthorized (possibly because the token is
|
||||
expired), issue one authorization attempt and send the request once
|
||||
again.
|
||||
|
||||
:param client: instance of BaseClient descendant
|
||||
:param method: method of HTTP request
|
||||
:param url: URL of HTTP request
|
||||
:param kwargs: any other parameter that can be passed to
|
||||
`HTTPClient.request`
|
||||
"""
|
||||
|
||||
token, endpoint = (self.cached_token, client.cached_endpoint)
|
||||
if not (token and endpoint):
|
||||
token, endpoint = self.auth_plugin.token_and_endpoint()
|
||||
self.cached_token = token
|
||||
client.cached_endpoint = endpoint
|
||||
|
||||
if token:
|
||||
kwargs.setdefault("headers", {})["Authorization"] = \
|
||||
"Bearer %s" % token
|
||||
|
||||
return self.request(method, self.concat_url(endpoint, url), **kwargs)
|
||||
|
||||
|
||||
class BaseManager(base.CrudManager):
|
||||
|
||||
def build_url(self, base_url=None, **kwargs):
|
||||
# Overriding to use "url_key" instead of the "collection_key".
|
||||
# "key_id" is replaced with just "id" when querying a specific object.
|
||||
url = base_url if base_url is not None else ''
|
||||
|
||||
url += '/%s' % self.url_key
|
||||
|
||||
entity_id = kwargs.get('id')
|
||||
if entity_id is not None:
|
||||
url += '/%s' % entity_id
|
||||
|
||||
return url
|
||||
|
||||
def get(self, id):
|
||||
"""Get a resource by id.
|
||||
|
||||
Get method is accepting id as a positional argument for simplicity.
|
||||
|
||||
:param id: The id of resource.
|
||||
:return: The resource object.
|
||||
"""
|
||||
|
||||
query_kwargs = {"id": id}
|
||||
return self._get(self.build_url(**query_kwargs), self.key)
|
||||
|
||||
def create(self, **kwargs):
|
||||
"""Create a resource.
|
||||
|
||||
The default implementation is overridden so that the dictionary is
|
||||
passed 'as is' without any wrapping.
|
||||
"""
|
||||
|
||||
kwargs = self._filter_kwargs(kwargs)
|
||||
return self._post(
|
||||
self.build_url(**kwargs),
|
||||
kwargs)
|
||||
|
||||
|
||||
class BaseNestedManager(BaseManager):
|
||||
|
||||
def __init__(self, client, parent_id):
|
||||
super(BaseNestedManager, self).__init__(client)
|
||||
|
||||
self.parent_id = parent_id
|
||||
|
||||
def build_url(self, base_url=None, **kwargs):
|
||||
# Overriding to use "url_key" instead of the "collection_key".
|
||||
# "key_id" is replaced with just "id" when querying a specific object.
|
||||
url = base_url if base_url is not None else ''
|
||||
|
||||
url += '/%s/%s/%s' % (self.parent_url_key, self.parent_id,
|
||||
self.url_key)
|
||||
|
||||
entity_id = kwargs.get('id')
|
||||
if entity_id is not None:
|
||||
url += '/%s' % entity_id
|
||||
|
||||
return url
|
||||
|
||||
|
||||
class BaseObject(base.Resource):
|
||||
|
||||
id = None
|
||||
created_at = None
|
||||
updated_at = None
|
||||
|
||||
def __init__(self, manager, info, loaded=False, parent_id=None):
|
||||
super(BaseObject, self).__init__(manager, info, loaded)
|
||||
|
||||
self._parent_id = parent_id
|
||||
self._init_nested_managers()
|
||||
|
||||
def _add_details(self, info):
|
||||
for field, value in six.iteritems(info):
|
||||
|
||||
# Skip the fields which are not declared in the object
|
||||
if not hasattr(self, field):
|
||||
continue
|
||||
|
||||
setattr(self, field, value)
|
||||
|
||||
def _init_nested_managers(self):
|
||||
# If an object has nested resource managers, they will be initialized
|
||||
# here.
|
||||
|
||||
manager_instances = {}
|
||||
|
||||
for manager_name, manager_class in self._managers():
|
||||
manager_instance = manager_class(client=self.manager.client,
|
||||
parent_id=self.id)
|
||||
# Saving a manager to a dict as self.__dict__ should not be
|
||||
# changed while iterating
|
||||
manager_instances[manager_name] = manager_instance
|
||||
|
||||
for name, manager_instance in six.iteritems(manager_instances):
|
||||
# replacing managers declarations with real managers
|
||||
setattr(self, name, manager_instance)
|
||||
|
||||
def _managers(self):
|
||||
# Iterator over nested managers
|
||||
|
||||
for attr in dir(self):
|
||||
# Skip private fields
|
||||
if attr.startswith("_"):
|
||||
continue
|
||||
val = getattr(self, attr)
|
||||
if inspect.isclass(val) and issubclass(val, BaseNestedManager):
|
||||
yield attr, val
|
0
storyboardclient/tests/test_base/__init__.py
Normal file
0
storyboardclient/tests/test_base/__init__.py
Normal file
52
storyboardclient/tests/test_base/test_base_HTTPClient.py
Normal file
52
storyboardclient/tests/test_base/test_base_HTTPClient.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from storyboardclient.auth import oauth
|
||||
from storyboardclient import base
|
||||
from storyboardclient.tests import base as test_base
|
||||
|
||||
|
||||
class BaseHTTPClientTestCase(test_base.TestCase):
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseHTTPClient.request")
|
||||
def test_unauthorized_client_request(self, mock_request):
|
||||
|
||||
auth_plugin = oauth.OAuthPlugin(api_url="http://some_endpoint")
|
||||
client = base.BaseHTTPClient(auth_plugin=auth_plugin)
|
||||
|
||||
client.client_request(client=mock.MagicMock(),
|
||||
method="GET", url="/some_url")
|
||||
|
||||
mock_request.assert_called_once_with("GET",
|
||||
"http://some_endpoint/some_url")
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseHTTPClient.request")
|
||||
def test_authorized_client_request(self, mock_request):
|
||||
|
||||
auth_plugin = oauth.OAuthPlugin(api_url="http://some_endpoint",
|
||||
access_token="some_token")
|
||||
client = base.BaseHTTPClient(auth_plugin=auth_plugin)
|
||||
|
||||
client.client_request(client=mock.MagicMock(),
|
||||
method="GET", url="/some_url")
|
||||
|
||||
mock_request.assert_called_once_with(
|
||||
"GET",
|
||||
"http://some_endpoint/some_url",
|
||||
headers={
|
||||
"Authorization": "Bearer some_token"
|
||||
})
|
39
storyboardclient/tests/test_base/test_base_manager.py
Normal file
39
storyboardclient/tests/test_base/test_base_manager.py
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.tests import base as test_base
|
||||
|
||||
|
||||
class BaseManagerTestCase(test_base.TestCase):
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseManager._get")
|
||||
def test_get(self, mock_private_get):
|
||||
manager = base.BaseManager(mock.MagicMock())
|
||||
manager.url_key = "key"
|
||||
manager.get("id1")
|
||||
|
||||
mock_private_get.assert_called_once_with("/key/id1", None)
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseManager._post")
|
||||
def test_create(self, mock_private_post):
|
||||
manager = base.BaseManager(mock.MagicMock())
|
||||
manager.url_key = "key"
|
||||
manager.create(title="test_story")
|
||||
|
||||
mock_private_post.assert_called_once_with("/key",
|
||||
{"title": "test_story"})
|
45
storyboardclient/tests/test_base/test_base_nested_manager.py
Normal file
45
storyboardclient/tests/test_base/test_base_nested_manager.py
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.tests import base as test_base
|
||||
|
||||
|
||||
class BaseNestedManagerTestCase(test_base.TestCase):
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseManager._get")
|
||||
def test_get(self, mock_private_get):
|
||||
manager = base.BaseNestedManager(mock.MagicMock(),
|
||||
parent_id="parent_id")
|
||||
manager.parent_url_key = "parent_key"
|
||||
manager.url_key = "key"
|
||||
manager.get("id1")
|
||||
|
||||
mock_private_get.assert_called_once_with(
|
||||
"/parent_key/parent_id/key/id1", None)
|
||||
|
||||
@mock.patch("storyboardclient.base.BaseManager._post")
|
||||
def test_create(self, mock_private_post):
|
||||
manager = base.BaseNestedManager(mock.MagicMock(),
|
||||
parent_id="parent_id")
|
||||
manager.parent_url_key = "parent_key"
|
||||
manager.url_key = "key"
|
||||
manager.create(title="test_task")
|
||||
|
||||
mock_private_post.assert_called_once_with(
|
||||
"/parent_key/parent_id/key",
|
||||
{"title": "test_task"})
|
43
storyboardclient/tests/test_base/test_base_object.py
Normal file
43
storyboardclient/tests/test_base/test_base_object.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.tests import base as test_base
|
||||
|
||||
|
||||
class BaseObjectTestCase(test_base.TestCase):
|
||||
|
||||
def test_init_no_nested(self):
|
||||
manager_mock = mock.MagicMock()
|
||||
obj = base.BaseObject(manager=manager_mock, info={"id": "test_id"})
|
||||
|
||||
self.assertEqual("test_id", obj.id)
|
||||
self.assertEqual(manager_mock, obj.manager)
|
||||
|
||||
def test_init_with_nested(self):
|
||||
|
||||
manager_mock = mock.MagicMock()
|
||||
|
||||
class TestInheritedObject(base.BaseObject):
|
||||
manager_field = base.BaseNestedManager
|
||||
|
||||
obj = TestInheritedObject(manager=manager_mock, info={"id": "test_id"})
|
||||
|
||||
self.assertEqual(base.BaseNestedManager, type(obj.manager_field))
|
||||
|
||||
self.assertEqual("test_id", obj.id)
|
||||
self.assertEqual("test_id", obj.manager_field.parent_id)
|
@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
test_storyboard
|
||||
----------------------------------
|
||||
|
||||
Tests for `storyboard` module.
|
||||
"""
|
||||
|
||||
from storyboardclient.tests import base
|
||||
|
||||
|
||||
class TestStoryboard(base.TestCase):
|
||||
|
||||
def test_something(self):
|
||||
pass
|
0
storyboardclient/tests/v1/__init__.py
Normal file
0
storyboardclient/tests/v1/__init__.py
Normal file
47
storyboardclient/tests/v1/test_user_preferences.py
Normal file
47
storyboardclient/tests/v1/test_user_preferences.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from storyboardclient.tests import base as test_base
|
||||
from storyboardclient.v1 import user_preferences
|
||||
from storyboardclient.v1 import users
|
||||
|
||||
|
||||
class UserPreferencesTestCase(test_base.TestCase):
|
||||
|
||||
@mock.patch("storyboardclient.v1.user_preferences.UserPreferencesManager"
|
||||
"._get")
|
||||
def test_user_preferences_get(self, mock_private_get):
|
||||
mock_private_get.return_value = user_preferences.UserPreferences(
|
||||
mock.MagicMock(),
|
||||
info={"k1": "v1"})
|
||||
|
||||
user = users.User(manager=mock.MagicMock(), info={"id": "test_id"})
|
||||
|
||||
preferences = user.user_preferences.get_all()
|
||||
self.assertEqual("v1", preferences.k1)
|
||||
|
||||
p_k1 = user.user_preferences.get("k1")
|
||||
self.assertEqual("v1", p_k1)
|
||||
|
||||
@mock.patch("storyboardclient.v1.user_preferences.UserPreferencesManager"
|
||||
"._post")
|
||||
def test_user_preferences_set(self, mock_private_post):
|
||||
user = users.User(manager=mock.MagicMock(), info={"id": "test_id"})
|
||||
|
||||
user.user_preferences.set({"k1": "v1"})
|
||||
mock_private_post.assert_called_once_with("/users/test_id/preferences",
|
||||
{"k1": "v1"})
|
0
storyboardclient/v1/__init__.py
Normal file
0
storyboardclient/v1/__init__.py
Normal file
44
storyboardclient/v1/client.py
Normal file
44
storyboardclient/v1/client.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.v1 import users
|
||||
|
||||
|
||||
class Client(base.BaseClient):
|
||||
"""A client class for StoryBoard.
|
||||
|
||||
Usage example:
|
||||
@code:
|
||||
from storyboard.v1 import client
|
||||
|
||||
storyboard = client.Client("https://storyboard.openstack.org/api/v1",
|
||||
"mytoken")
|
||||
"""
|
||||
|
||||
def __init__(self, api_url=None, access_token=None):
|
||||
"""Sets up a client with endpoint managers.
|
||||
|
||||
:param api_url: (Optional) Full API url. Defaults to
|
||||
https://storyboard.openstack.org/api/v1
|
||||
:param access_token: (Optional) OAuth2 access token. If skipped only
|
||||
public read-only endpoint will be available. All other requests will
|
||||
fail with Unauthorized error.
|
||||
:return: a client instance.
|
||||
"""
|
||||
super(Client, self).__init__(api_url=api_url,
|
||||
access_token=access_token)
|
||||
|
||||
self.users = users.UsersManager(self)
|
66
storyboardclient/v1/user_preferences.py
Normal file
66
storyboardclient/v1/user_preferences.py
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import six
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.openstack.common import log
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class UserPreferences(base.BaseObject):
|
||||
|
||||
def _add_details(self, info):
|
||||
# User preferences can not be declared before the data is received.
|
||||
# Adding all properties to an object directly.
|
||||
for key, value in six.iteritems(info):
|
||||
setattr(self, key, value)
|
||||
|
||||
|
||||
class UserPreferencesManager(base.BaseNestedManager):
|
||||
parent_url_key = "users"
|
||||
url_key = "preferences"
|
||||
resource_class = UserPreferences
|
||||
|
||||
def get_all(self):
|
||||
"""Get a dictionary of User Preferences
|
||||
|
||||
User preferences are returned always as a dict, so it's better to use
|
||||
a get base method instead of a list here.
|
||||
|
||||
:return: UserPreferences object
|
||||
"""
|
||||
|
||||
return super(UserPreferencesManager, self).get(None)
|
||||
|
||||
def get(self, key):
|
||||
all_prefs = super(UserPreferencesManager, self).get(None)
|
||||
|
||||
return getattr(all_prefs, key)
|
||||
|
||||
def set(self, data):
|
||||
"""Set a dictionary of user preferences.
|
||||
|
||||
"""
|
||||
|
||||
return self.create(**data)
|
||||
|
||||
def set_one(self, key, value):
|
||||
"""Set a user preference by key.
|
||||
|
||||
"""
|
||||
|
||||
return self.set({key: value})
|
33
storyboardclient/v1/users.py
Normal file
33
storyboardclient/v1/users.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from storyboardclient import base
|
||||
from storyboardclient.v1 import user_preferences
|
||||
|
||||
|
||||
class User(base.BaseObject):
|
||||
username = None
|
||||
full_name = None
|
||||
openid = None
|
||||
is_superuser = None
|
||||
last_login = None
|
||||
enable_login = None
|
||||
|
||||
user_preferences = user_preferences.UserPreferencesManager
|
||||
|
||||
|
||||
class UsersManager(base.BaseManager):
|
||||
url_key = "users"
|
||||
resource_class = User
|
Loading…
Reference in New Issue
Block a user