From 1bbb6771333ae3046f77f476e2cde1809e0a1ed5 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Thu, 2 May 2013 18:51:36 +0300 Subject: [PATCH] astakos: WIP move all api calls under ``/astakos/api`` Refs: #3340 --- Changelog | 10 +- astakosclient/astakosclient/__init__.py | 20 +- astakosclient/astakosclient/tests.py | 18 +- docs/astakos-api-guide.rst | 58 +++--- docs/astakos.rst | 11 +- docs/quick-install-admin-guide.rst | 12 +- docs/scale/i-astakos.rst | 4 +- docs/scale/i-cms.rst | 4 +- docs/scale/i-cyclades.rst | 2 +- docs/scale/i-pithos.rst | 4 +- docs/upgrade/upgrade-0.14.rst | 52 ++++++ snf-astakos-app/astakos/api/__init__.py | 171 ++++++++++++++++++ snf-astakos-app/astakos/api/quotas.py | 6 +- .../astakos/{im => }/api/service.py | 45 +---- snf-astakos-app/astakos/api/urls.py | 18 ++ snf-astakos-app/astakos/{im => }/api/user.py | 35 +--- snf-astakos-app/astakos/api/util.py | 120 ++++++++++++ snf-astakos-app/astakos/im/urls.py | 6 +- snf-astakos-app/astakos/im/views.py | 3 +- .../astakos/test/settings/local.conf | 2 +- snf-astakos-app/astakos/urls.py | 13 +- .../conf/20-snf-astakos-app-cloudbar.conf | 4 +- snf-common/synnefo/lib/context_processors.py | 4 +- .../conf/20-snf-cyclades-app-cloudbar.conf | 4 +- snf-cyclades-app/synnefo/api/delegate.py | 4 +- .../synnefo/app_settings/default/cloudbar.py | 4 +- snf-cyclades-app/synnefo/ui/views.py | 4 +- snf-pithos-app/pithos/api/delegate.py | 6 +- snf-pithos-app/pithos/api/settings.py | 4 - 29 files changed, 477 insertions(+), 171 deletions(-) rename snf-astakos-app/astakos/{im => }/api/service.py (65%) rename snf-astakos-app/astakos/{im => }/api/user.py (84%) diff --git a/Changelog b/Changelog index 1112432fe..d7cc27023 100644 --- a/Changelog +++ b/Changelog @@ -14,16 +14,12 @@ v0.13next Released: UNRELEASED -* Incorporate quotaholder in astakos - * obsolete settings: - PITHOS_USE_QUOTAHOLDER, PITHOS_QUOTAHOLDER_URL, PITHOS_QUOTAHOLDER_TOKEN - * new settins: - PITHOS_ASTAKOSCLIENT_POOLSIZE - Synnefo-wide ------------ * Create 'snf_django' Python package to hold common code for all Synnefo components. +* CLOUDBAR_SERVICES_URL should point to /astakos/api/get_services +* CLOUDBAR_MENU_URL should point to /astakos/api/get_menu Astakos ------- @@ -51,6 +47,8 @@ Pithos astakos users. * Remove 'PITHOS_USER_CATALOG_URL', 'PITHOS_USER_FEEDBACK_URL' and 'PITHOS_USER_LOGIN_URL' settings. +* Remove PITHOS_USE_QUOTAHOLDER, PITHOS_QUOTAHOLDER_URL, + PITHOS_QUOTAHOLDER_TOKEN and PITHOS_ASTAKOSCLIENT_POOLSIZE Tools ----- diff --git a/astakosclient/astakosclient/__init__.py b/astakosclient/astakosclient/__init__.py index 45e5b60fe..24021fb66 100644 --- a/astakosclient/astakosclient/__init__.py +++ b/astakosclient/astakosclient/__init__.py @@ -173,7 +173,7 @@ class AstakosClient(): raise InvalidResponse(str(err), data) # ------------------------ - # GET /im/authenticate + # GET /astakos/api/authenticate def get_user_info(self, token, usage=False): """Authenticate user and get user's info as a dictionary @@ -186,13 +186,13 @@ class AstakosClient(): """ # Send request - auth_path = "/im/authenticate" + auth_path = "/astakos/api/authenticate" if usage: auth_path += "?usage=1" return self._call_astakos(token, auth_path) # ---------------------------------- - # POST /user_catalogs (or /service/api/user_catalogs) + # POST /astakos/api/user_catalogs (or /astakos/api/service/user_catalogs) # with {'uuids': uuids} def _uuid_catalog(self, token, uuids, req_path): req_headers = {'content-type': 'application/json'} @@ -218,7 +218,7 @@ class AstakosClient(): keys and the corresponding user names as values """ - req_path = "/user_catalogs" + req_path = "/astakos/api/user_catalogs" return self._uuid_catalog(token, uuids, req_path) def get_username(self, token, uuid): @@ -232,7 +232,7 @@ class AstakosClient(): def service_get_usernames(self, token, uuids): """Return a uuid_catalog dict using a service's token""" - req_path = "/service/api/user_catalogs" + req_path = "/astakos/api/service/user_catalogs" return self._uuid_catalog(token, uuids, req_path) def service_get_username(self, token, uuid): @@ -245,7 +245,7 @@ class AstakosClient(): raise NoUserName(uuid) # ---------------------------------- - # POST /user_catalogs (or /service/api/user_catalogs) + # POST /astakos/api/user_catalogs (or /astakos/api/service/user_catalogs) # with {'displaynames': display_names} def _displayname_catalog(self, token, display_names, req_path): req_headers = {'content-type': 'application/json'} @@ -271,7 +271,7 @@ class AstakosClient(): the names as keys and the corresponding uuids as values """ - req_path = "/user_catalogs" + req_path = "/astakos/api/user_catalogs" return self._displayname_catalog(token, display_names, req_path) def get_uuid(self, token, display_name): @@ -285,7 +285,7 @@ class AstakosClient(): def service_get_uuids(self, token, display_names): """Return a display_name catalog using a service's token""" - req_path = "/service/api/user_catalogs" + req_path = "/astakos/api/service/user_catalogs" return self._displayname_catalog(token, display_names, req_path) def service_get_uuid(self, token, display_name): @@ -298,10 +298,10 @@ class AstakosClient(): raise NoUUID(display_name) # ---------------------------------- - # GET "/im/get_services" + # GET "/astakos/api/get_services" def get_services(self): """Return a list of dicts with the registered services""" - return self._call_astakos(None, "/im/get_services") + return self._call_astakos(None, "/astakos/api/get_services") # ---------------------------------- # GET "/astakos/api/resources" diff --git a/astakosclient/astakosclient/tests.py b/astakosclient/astakosclient/tests.py index a2f56ed95..b5d783b02 100644 --- a/astakosclient/astakosclient/tests.py +++ b/astakosclient/astakosclient/tests.py @@ -108,9 +108,9 @@ def _request_status_400(conn, method, url, **kwargs): def _request_ok(conn, method, url, **kwargs): """This request behaves like original Astakos does""" - if url.startswith("/im/authenticate"): + if url.startswith("/astakos/api/authenticate"): return _req_authenticate(conn, method, url, **kwargs) - elif url.startswith("/user_catalogs"): + elif url.startswith("/astakos/api/user_catalogs"): return _req_catalogs(conn, method, url, **kwargs) elif url.startswith("/astakos/api/resources"): return _req_resources(conn, method, url, **kwargs) @@ -472,7 +472,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_offline]) try: client = AstakosClient("https://example.com", use_pool=pool) - client._call_astakos(token_1, "/im/authenticate") + client._call_astakos(token_1, "/astakos/api/authenticate") except AstakosClientException: pass else: @@ -493,7 +493,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("https://example.com", use_pool=pool) - client._call_astakos(token, "/im/authenticate") + client._call_astakos(token, "/astakos/api/authenticate") except Unauthorized: pass except Exception: @@ -516,7 +516,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("https://example.com", use_pool=pool) - client._call_astakos(token_1, "/im/misspelled") + client._call_astakos(token_1, "/astakos/api/misspelled") except NotFound: pass except Exception: @@ -539,7 +539,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("ftp://example.com", use_pool=pool) - client._call_astakos(token_1, "/im/authenticate") + client._call_astakos(token_1, "/astakos/api/authenticate") except BadValue: pass except Exception: @@ -562,7 +562,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("http://example.com", use_pool=pool) - client._call_astakos(token_1, "/im/authenticate") + client._call_astakos(token_1, "/astakos/api/authenticate") except AstakosClientException as err: if err.status != 302: self.fail("Should have returned 302 (Found)") @@ -584,7 +584,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("https://example.com", use_pool=pool) - client._call_astakos(token_1, "/im/authenticate", method="POST") + client._call_astakos(token_1, "/astakos/api/authenticate", method="POST") except BadRequest: pass except Exception: @@ -607,7 +607,7 @@ class TestCallAstakos(unittest.TestCase): _mock_request([_request_ok]) try: client = AstakosClient("https://example.com", use_pool=pool) - client._call_astakos(token_1, "/user_catalogs") + client._call_astakos(token_1, "/astakos/api/user_catalogs") except BadRequest: pass except Exception: diff --git a/docs/astakos-api-guide.rst b/docs/astakos-api-guide.rst index 313004cdf..d6c339a7a 100644 --- a/docs/astakos-api-guide.rst +++ b/docs/astakos-api-guide.rst @@ -20,6 +20,7 @@ Document Revisions ========================= ================================ Revision Description ========================= ================================ +0.14 (May 02, 2013) Change URIs (keep also the old ones until the next version) 0.13 (January 21, 2013) Extend api to export user presentation & quota information. 0.6 (June 06, 2012) Split service and admin API. 0.1 (Feb 10, 2012) Initial release. @@ -30,11 +31,11 @@ Get Services Returns a json formatted list containing information about the supported cloud services. -==================== ========= ================== -Uri Method Description -==================== ========= ================== -``/im/get_services`` GET Get cloud services -==================== ========= ================== +============================= ========= ================== +Uri Method Description +============================= ========= ================== +``/astakos/api/get_services`` GET Get cloud services +============================= ========= ================== Example reply: @@ -44,17 +45,20 @@ Example reply: {"url": "/okeanos.html", "name": "~okeanos", "id": "2"}, {"url": "/ui/", "name": "pithos+", "id": "3"}] +.. warning:: The service is also available under ``/im/get_services``. + It will be removed in the next version. + Get Menu ^^^^^^^^ Returns a json formatted list containing the cloud bar links. -==================== ========= ================== -Uri Method Description -==================== ========= ================== -``/im/get_menu`` GET Get cloud bar menu -==================== ========= ================== +========================= ========= ================== +Uri Method Description +========================= ========= ================== +``/astakos/api/get_menu`` GET Get cloud bar menu +========================= ========= ================== Example reply if request user is not authenticated: @@ -66,10 +70,13 @@ Example reply if request user is authenticated: :: - [{"url": "/im/login", "name": "user@example.com"}, - {"url": "/im/profile", "name": "My account"}, + [{"url": "/im/", "name": "user@example.com"}, + {"url": "/im/landing", "name": "Dashboard"}, {"url": "/im/logout", "name": "Sign out"}] +.. warning:: The service is also available under ``/im/get_menu``. + It will be removed in the next version. + Admin API Operations -------------------- @@ -84,11 +91,11 @@ Authenticate Authenticate API requests require a token. An application that wishes to connect to Astakos, but does not have a token, should redirect the user to ``/login``. (see :ref:`authentication-label`) -==================== ========= ================== -Uri Method Description -==================== ========= ================== -``/im/authenticate`` GET Authenticate user using token -==================== ========= ================== +============================= ========= ================== +Uri Method Description +============================= ========= ================== +``/astakos/api/authenticate`` GET Authenticate user using token +============================= ========= ================== | @@ -225,6 +232,9 @@ Return Code Description 500 (Internal Server Error) The request cannot be completed because of an internal error =========================== ===================== +.. warning:: The service is also available under ``/im/authenticate``. + It will be removed in the next version. + Send feedback ^^^^^^^^^^^^^ @@ -234,7 +244,7 @@ Post user feedback. ========================= ========= ================== Uri Method Description ========================= ========= ================== -``/feedback`` POST Send feedback +``astakos/api/feedback`` POST Send feedback ========================= ========= ================== | @@ -274,7 +284,7 @@ Return a json formatted dictionary containing information about a specific user ================================ ========= ================== Uri Method Description ================================ ========= ================== -``/user_catalogs`` POST Get 2 catalogs containing uuid to displayname mapping and the opposite +``astakos/api/user_catalogs`` POST Get 2 catalogs containing uuid to displayname mapping and the opposite ================================ ========= ================== | @@ -329,11 +339,11 @@ Get User catalogs Return a json formatted dictionary containing information about a specific user -================================ ========= ================== -Uri Method Description -================================ ========= ================== -``/user_catalogs`` POST Get 2 catalogs containing uuid to displayname mapping and the opposite -================================ ========= ================== +===================================== ========= ================== +Uri Method Description +===================================== ========= ================== +``astakos/api/service/user_catalogs`` POST Get 2 catalogs containing uuid to displayname mapping and the opposite +===================================== ========= ================== | diff --git a/docs/astakos.rst b/docs/astakos.rst index 2c03b82f0..264ec6a5e 100644 --- a/docs/astakos.rst +++ b/docs/astakos.rst @@ -86,11 +86,12 @@ Cloud service user Alice requests a specific resource from a cloud service ex. Pithos+. In the request supplies the `X-Auth-Token` to identify whether she is eligible to perform the specific task. The service contacts Astakos through its -``/im/authenticate`` api call (see :ref:`authenticate-api-label`) providing the -specific ``X-Auth-Token``. Astakos checkes whether the token belongs to an -active user and it has not expired and returns a dictionary containing user -related information. Finally the service uses the ``uniq`` field included in -the dictionary as the account string to identify the user accessible resources. +``/astakos/api/authenticate`` api call (see :ref:`authenticate-api-label`) +providing the specific ``X-Auth-Token``. Astakos checkes whether the token +belongs to an active user and it has not expired and returns a dictionary +containing user related information. Finally the service uses the ``uniq`` +field included in the dictionary as the account string to identify the user +accessible resources. .. _registration-flow-label: diff --git a/docs/quick-install-admin-guide.rst b/docs/quick-install-admin-guide.rst index d7bdb89d9..893bd2662 100644 --- a/docs/quick-install-admin-guide.rst +++ b/docs/quick-install-admin-guide.rst @@ -610,9 +610,9 @@ Then edit ``/etc/synnefo/20-snf-astakos-app-cloudbar.conf`` : CLOUDBAR_LOCATION = 'https://node1.example.com/static/im/cloudbar/' - CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' - CLOUDBAR_MENU_URL = 'https://node1.example.com/im/get_menu' + CLOUDBAR_MENU_URL = 'https://node1.example.com/astakos/api/get_menu' Those settings have to do with the black cloudbar endpoints and will be described in more detail later on in this guide. For now, just edit the domain @@ -912,8 +912,8 @@ pithos+ web UI with the astakos web UI (through the top cloudbar): CLOUDBAR_LOCATION = 'https://node1.example.com/static/im/cloudbar/' PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE = '3' - CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' - CLOUDBAR_MENU_URL = 'https://node1.example.com/im/get_menu' + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://node1.example.com/astakos/api/get_menu' The ``CLOUDBAR_LOCATION`` tells the client where to find the astakos common cloudbar. @@ -1722,8 +1722,8 @@ Edit ``/etc/synnefo/20-snf-cyclades-app-cloudbar.conf``: CLOUDBAR_LOCATION = 'https://node1.example.com/static/im/cloudbar/' CLOUDBAR_ACTIVE_SERVICE = '2' - CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' - CLOUDBAR_MENU_URL = 'https://account.node1.example.com/im/get_menu' + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://account.node1.example.com/astakos/api/get_menu' ``CLOUDBAR_LOCATION`` tells the client where to find the Astakos common cloudbar. The ``CLOUDBAR_SERVICES_URL`` and ``CLOUDBAR_MENU_URL`` options are diff --git a/docs/scale/i-astakos.rst b/docs/scale/i-astakos.rst index faf985a55..e4a95f96c 100644 --- a/docs/scale/i-astakos.rst +++ b/docs/scale/i-astakos.rst @@ -39,8 +39,8 @@ In `/etc/synnefo/astakos.conf` add: .. code-block:: console CLOUDBAR_LOCATION = 'https://accounts.example.com/static/im/cloudbar/' - CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/im/get_services' - CLOUDBAR_MENU_URL = 'https://accounts.example.com/im/get_menu' + CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://accounts.example.com/astakos/api/get_menu' ASTAKOS_IM_MODULES = ['local'] diff --git a/docs/scale/i-cms.rst b/docs/scale/i-cms.rst index 00d7801e5..fb877cd0e 100644 --- a/docs/scale/i-cms.rst +++ b/docs/scale/i-cms.rst @@ -42,8 +42,8 @@ In `/etc/synnefo/cloudcms.conf` add: CLOUDBAR_ACTIVE = True CLOUDBAR_LOCATION = 'https://accounts.example.com/static/im/cloudbar/' - CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/im/get_services' - CLOUDBAR_MENU_URL = 'https://accounts.example.com/im/get_menu' + CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://accounts.example.com/astakos/api/get_menu' WEBPROJECT_SERVE_STATIC = True diff --git a/docs/scale/i-cyclades.rst b/docs/scale/i-cyclades.rst index 2aa8b4d0b..f4f206de0 100644 --- a/docs/scale/i-cyclades.rst +++ b/docs/scale/i-cyclades.rst @@ -64,7 +64,7 @@ In `/etc/synnefo/cyclades.conf` add: GANETI_USE_HOTPLUG = True CLOUDBAR_LOCATION = 'https://accounts.example.com/static/im/cloudbar/' CLOUDBAR_ACTIVE_SERVICE = '2' - CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/im/get_services' + CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/astakos/api/get_services' CLOUDBAR_MENU_URL = 'https://accounts.example.com/im/get_menu' BACKEND_DB_CONNECTION = 'postgresql://synnefo:example_passw0rd@db.example.com:5432/snf_pithos' BACKEND_BLOCK_PATH = '/srv/pithos/data/' diff --git a/docs/scale/i-pithos.rst b/docs/scale/i-pithos.rst index 7e47da157..de295a4ac 100644 --- a/docs/scale/i-pithos.rst +++ b/docs/scale/i-pithos.rst @@ -85,8 +85,8 @@ In `/etc/synnefo/webclient.conf` add: .. code-block:: console CLOUDBAR_LOCATION = 'https://accounts.example.com/static/im/cloudbar/' - CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/im/get_services' - CLOUDBAR_MENU_URL = 'https://accounts.example.com/im/get_menu' + CLOUDBAR_SERVICES_URL = 'https://accounts.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://accounts.example.com/astakos/api/get_menu' PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE = 'XXXXXXXX' diff --git a/docs/upgrade/upgrade-0.14.rst b/docs/upgrade/upgrade-0.14.rst index 3431f633c..50272f442 100644 --- a/docs/upgrade/upgrade-0.14.rst +++ b/docs/upgrade/upgrade-0.14.rst @@ -74,3 +74,55 @@ Finally, Astakos needs to inform the quota system for the current number of pending applications per user:: astakos-host$ snf-manage reconcile-resources-astakos --fix + +4 Change Astakos URIs in settings +================================= + +In astakos-host edit ``/etc/synnefo/20-snf-astakos-app-cloudbar.conf`` and replace +the following lines: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' + CLOUDBAR_MENU_URL = 'https://node1.example.com/im/get_menu' + +with: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://node1.example.com/astakos/api/get_menu' + +| + +Also in pithos-host edit ``/etc/synnefo/20-snf-pithos-webclient-cloudbar.conf`` +and the following lines: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' + CLOUDBAR_MENU_URL = 'https://node1.example.com/im/get_menu' + +with: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://node1.example.com/astakos/api/get_menu' + +| + +Finally in cyclades-node edit ``/etc/synnefo/20-snf-cyclades-app-cloudbar.conf`` +and replace the following lines: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/im/get_services' + CLOUDBAR_MENU_URL = 'https://account.node1.example.com/im/get_menu' + +with: + +.. code-block:: console + + CLOUDBAR_SERVICES_URL = 'https://node1.example.com/astakos/api/get_services' + CLOUDBAR_MENU_URL = 'https://account.node1.example.com/astakos/api/get_menu' diff --git a/snf-astakos-app/astakos/api/__init__.py b/snf-astakos-app/astakos/api/__init__.py index e69de29bb..87992af2a 100644 --- a/snf-astakos-app/astakos/api/__init__.py +++ b/snf-astakos-app/astakos/api/__init__.py @@ -0,0 +1,171 @@ +# Copyright 2013 GRNET S.A. All rights reserved. +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and +# documentation are those of the authors and should not be +# interpreted as representing official policies, either expressed +# or implied, of GRNET S.A. + +# Decorator for API methods, using common utils.api_method decorator. +# It is used for 'get_services' and 'get_menu' methods that do not +# require any sort of authentication + +from functools import partial + +from django.http import HttpResponse +from django.utils import simplejson as json +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ +from django.contrib import messages + +from snf_django.lib import api +from astakos.im.models import Service +from astakos.im.settings import (INVITATIONS_ENABLED, QUOTAHOLDER_URL, + PROJECTS_VISIBLE) + +import logging +logger = logging.getLogger(__name__) + +absolute = lambda request, url: request.build_absolute_uri(url) + +api_method = partial(api.api_method, user_required=False, + token_required=False, logger=logger) + + +@api_method(http_method=None) +def get_services(request): + callback = request.GET.get('callback', None) + mimetype = 'application/json' + data = json.dumps(Service.catalog().values()) + + if callback: + # Consume session messages. When get_services is loaded from an astakos + # page, messages should have already been consumed in the html + # response. When get_services is loaded from another domain/service we + # consume them here so that no stale messages to appear if user visits + # an astakos view later on. + # TODO: messages could be served to other services/sites in the dict + # response of get_services and/or get_menu. Services could handle those + # messages respectively. + messages_list = list(messages.get_messages(request)) + mimetype = 'application/javascript' + data = '%s(%s)' % (callback, data) + + return HttpResponse(content=data, mimetype=mimetype) + + +@api_method() +def get_menu(request, with_extra_links=False, with_signout=True): + user = request.user + index_url = reverse('index') + + if user.is_authenticated(): + l = [] + append = l.append + item = MenuItem + item.current_path = absolute(request, request.path) + append(item(url=absolute(request, reverse('index')), + name=user.email)) + if with_extra_links: + append(item(url=absolute(request, reverse('landing')), + name="Overview")) + if with_signout: + append(item(url=absolute(request, reverse('landing')), + name="Dashboard")) + if with_extra_links: + append(item(url=absolute(request, reverse('edit_profile')), + name="Profile")) + + if with_extra_links: + if INVITATIONS_ENABLED: + append(item(url=absolute(request, reverse('invite')), + name="Invitations")) + + append(item(url=absolute(request, reverse('resource_usage')), + name="Usage")) + + if QUOTAHOLDER_URL and PROJECTS_VISIBLE: + append(item(url=absolute(request, reverse('project_list')), + name="Projects")) + #append(item( + #url=absolute(request, reverse('api_access')), + #name="API Access")) + + append(item(url=absolute(request, reverse('feedback')), + name="Contact")) + if with_signout: + append(item(url=absolute(request, reverse('logout')), + name="Sign out")) + else: + l = [{'url': absolute(request, index_url), + 'name': _("Sign in")}] + + callback = request.GET.get('callback', None) + data = json.dumps(tuple(l)) + mimetype = 'application/json' + + if callback: + mimetype = 'application/javascript' + data = '%s(%s)' % (callback, data) + + return HttpResponse(content=data, mimetype=mimetype) + + +class MenuItem(dict): + current_path = '' + + def __init__(self, *args, **kwargs): + super(MenuItem, self).__init__(*args, **kwargs) + if kwargs.get('url') or kwargs.get('submenu'): + self.__set_is_active__() + + def __setitem__(self, key, value): + super(MenuItem, self).__setitem__(key, value) + if key in ('url', 'submenu'): + self.__set_is_active__() + + def __set_is_active__(self): + if self.get('is_active'): + return + if self.current_path.startswith(self.get('url')): + self.__setitem__('is_active', True) + else: + submenu = self.get('submenu', ()) + current = (i for i in submenu if i.get('url') == self.current_path) + try: + current_node = current.next() + if not current_node.get('is_active'): + current_node.__setitem__('is_active', True) + self.__setitem__('is_active', True) + except StopIteration: + return + + def __setattribute__(self, name, value): + super(MenuItem, self).__setattribute__(name, value) + if name == 'current_path': + self.__set_is_active__() diff --git a/snf-astakos-app/astakos/api/quotas.py b/snf-astakos-app/astakos/api/quotas.py index 5743b0efb..c479e9c44 100644 --- a/snf-astakos-app/astakos/api/quotas.py +++ b/snf-astakos-app/astakos/api/quotas.py @@ -36,20 +36,18 @@ from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse from snf_django.lib.db.transaction import commit_on_success_strict -from astakos.api.util import json_response, is_integer, are_integer from snf_django.lib import api from snf_django.lib.api.faults import BadRequest, ItemNotFound -from astakos.im.api.user import user_from_token -from astakos.im.api.service import service_from_token - from astakos.im.resources import get_resources from astakos.im.quotas import get_user_quotas, service_get_quotas import astakos.quotaholder_app.exception as qh_exception import astakos.quotaholder_app.callpoint as qh +from .util import (json_response, is_integer, are_integer, + user_from_token, service_from_token) @api.api_method(http_method='GET', token_required=True, user_required=False) @user_from_token diff --git a/snf-astakos-app/astakos/im/api/service.py b/snf-astakos-app/astakos/api/service.py similarity index 65% rename from snf-astakos-app/astakos/im/api/service.py rename to snf-astakos-app/astakos/api/service.py index 64825ea87..c342a4274 100644 --- a/snf-astakos-app/astakos/im/api/service.py +++ b/snf-astakos-app/astakos/api/service.py @@ -31,56 +31,19 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. -from time import time, mktime -from functools import wraps from django.views.decorators.csrf import csrf_exempt -from . import __get_uuid_displayname_catalogs, __send_feedback from snf_django.lib import api -from snf_django.lib.api import faults -from astakos.im.models import Service +from .util import (__get_uuid_displayname_catalogs, __send_feedback, + service_from_token) import logging logger = logging.getLogger(__name__) -def service_from_token(func): - """Decorator for authenticating service by it's token. - - Check that a service with the corresponding token exists. Also, - if service's token has an expiration token, check that it has not - expired. - - """ - @wraps(func) - def wrapper(request, *args, **kwargs): - try: - token = request.x_auth_token - except AttributeError: - raise faults.Unauthorized("No authentication token") - - if not token: - raise faults.Unauthorized("Invalid X-Auth-Token") - try: - service = Service.objects.get(auth_token=token) - except Service.DoesNotExist: - raise faults.Unauthorized("Invalid X-Auth-Token") - - # Check if the token has expired - expiration_date = service.auth_token_expires - if expiration_date: - expires_at = mktime(expiration_date.timetuple()) - if time() > expires_at: - raise faults.Unauthorized("Authentication expired") - - request.service_instance = service - return func(request, *args, **kwargs) - return wrapper - - @csrf_exempt @api.api_method(http_method='POST', token_required=True, user_required=False, - logger=logger) + logger=logger) @service_from_token # Authenticate service !! def get_uuid_displayname_catalogs(request): # Normal Response Codes: 200 @@ -92,7 +55,7 @@ def get_uuid_displayname_catalogs(request): @csrf_exempt @api.api_method(http_method='POST', token_required=True, user_required=False, - logger=logger) + logger=logger) @service_from_token # Authenticate service !! def send_feedback(request, email_template_name='im/feedback_mail.txt'): # Normal Response Codes: 200 diff --git a/snf-astakos-app/astakos/api/urls.py b/snf-astakos-app/astakos/api/urls.py index d567ed6d7..09be53433 100644 --- a/snf-astakos-app/astakos/api/urls.py +++ b/snf-astakos-app/astakos/api/urls.py @@ -34,6 +34,12 @@ from django.conf.urls.defaults import patterns, url urlpatterns = patterns( + 'astakos.api', + url(r'^get_services/?$', 'get_services'), + url(r'^get_menu/?$', 'get_menu'), +) + +urlpatterns += patterns( 'astakos.api.quotas', url(r'^quotas/?$', 'quotas', name="astakos-api-quotas"), url(r'^service_quotas/?$', 'service_quotas'), @@ -43,3 +49,15 @@ urlpatterns = patterns( url(r'^commissions/(?P\d+)/?$', 'get_commission'), url(r'^commissions/(?P\d+)/action/?$', 'serial_action'), ) + +urlpatterns += patterns( + 'astakos.api.user', + url(r'^feedback/?$', 'send_feedback'), + url(r'^user_catalogs/?$', 'get_uuid_displayname_catalogs'), + url(r'^authenticate/?$', 'authenticate'), +) + +urlpatterns += patterns( + 'astakos.api.service', + url(r'^service/user_catalogs/?$', 'get_uuid_displayname_catalogs'), +) diff --git a/snf-astakos-app/astakos/im/api/user.py b/snf-astakos-app/astakos/api/user.py similarity index 84% rename from snf-astakos-app/astakos/im/api/user.py rename to snf-astakos-app/astakos/api/user.py index f4a4b7fc1..8414c5a0e 100644 --- a/snf-astakos-app/astakos/im/api/user.py +++ b/snf-astakos-app/astakos/api/user.py @@ -31,7 +31,6 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. -from functools import wraps from time import time, mktime from django.http import HttpResponse @@ -40,41 +39,21 @@ from django.views.decorators.csrf import csrf_exempt from snf_django.lib import api from snf_django.lib.api import faults -from . import __get_uuid_displayname_catalogs, __send_feedback -from astakos.im.models import AstakosUser from astakos.im.util import epoch - from astakos.im.api.callpoint import AstakosCallpoint + +from .util import (__get_uuid_displayname_catalogs, + __send_feedback, user_from_token) + callpoint = AstakosCallpoint() import logging logger = logging.getLogger(__name__) -format = ('%a, %d %b %Y %H:%M:%S GMT') - - -def user_from_token(func): - @wraps(func) - def wrapper(request, *args, **kwargs): - try: - token = request.x_auth_token - except AttributeError: - raise faults.Unauthorized("No authentication token") - - if not token: - raise faults.Unauthorized("Invalid X-Auth-Token") - - try: - user = AstakosUser.objects.get(auth_token=token) - except AstakosUser.DoesNotExist: - raise faults.Unauthorized('Invalid X-Auth-Token') - - return func(request, user, *args, **kwargs) - return wrapper @api.api_method(http_method="GET", token_required=True, user_required=False, - logger=logger) + logger=logger) @user_from_token # Authenticate user!! def authenticate(request, user=None): # Normal Response Codes: 200 @@ -125,7 +104,7 @@ def authenticate(request, user=None): @csrf_exempt @api.api_method(http_method="POST", token_required=True, user_required=False, - logger=logger) + logger=logger) @user_from_token # Authenticate user!! def get_uuid_displayname_catalogs(request, user=None): # Normal Response Codes: 200 @@ -138,7 +117,7 @@ def get_uuid_displayname_catalogs(request, user=None): @csrf_exempt @api.api_method(http_method="POST", token_required=True, user_required=False, - logger=logger) + logger=logger) @user_from_token # Authenticate user!! def send_feedback(request, email_template_name='im/feedback_mail.txt', user=None): diff --git a/snf-astakos-app/astakos/api/util.py b/snf-astakos-app/astakos/api/util.py index cdff59e6f..b578fe8d0 100644 --- a/snf-astakos-app/astakos/api/util.py +++ b/snf-astakos-app/astakos/api/util.py @@ -31,9 +31,23 @@ # interpreted as representing official policies, either expressed # or implied, of GRNET S.A. +from functools import wraps +from time import time, mktime + from django.http import HttpResponse from django.utils import simplejson as json +from astakos.im.models import AstakosUser, Service +from snf_django.lib.api import faults + +from astakos.im.forms import FeedbackForm +from astakos.im.functions import send_feedback as send_feedback_func + +import logging +logger = logging.getLogger(__name__) + +absolute = lambda request, url: request.build_absolute_uri(url) + def json_response(content, status_code=None): response = HttpResponse() @@ -52,3 +66,109 @@ def is_integer(x): def are_integer(lst): return all(map(is_integer, lst)) + + +def user_from_token(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + try: + token = request.x_auth_token + except AttributeError: + raise faults.Unauthorized("No authentication token") + + if not token: + raise faults.Unauthorized("Invalid X-Auth-Token") + + try: + user = AstakosUser.objects.get(auth_token=token) + except AstakosUser.DoesNotExist: + raise faults.Unauthorized('Invalid X-Auth-Token') + + return func(request, user, *args, **kwargs) + return wrapper + + +def service_from_token(func): + """Decorator for authenticating service by it's token. + + Check that a service with the corresponding token exists. Also, + if service's token has an expiration token, check that it has not + expired. + + """ + @wraps(func) + def wrapper(request, *args, **kwargs): + try: + token = request.x_auth_token + except AttributeError: + raise faults.Unauthorized("No authentication token") + + if not token: + raise faults.Unauthorized("Invalid X-Auth-Token") + try: + service = Service.objects.get(auth_token=token) + except Service.DoesNotExist: + raise faults.Unauthorized("Invalid X-Auth-Token") + + # Check if the token has expired + expiration_date = service.auth_token_expires + if expiration_date: + expires_at = mktime(expiration_date.timetuple()) + if time() > expires_at: + raise faults.Unauthorized("Authentication expired") + + request.service_instance = service + return func(request, *args, **kwargs) + return wrapper + + +def __get_uuid_displayname_catalogs(request, user_call=True): + # Normal Response Codes: 200 + # Error Response Codes: BadRequest (400) + + try: + input_data = json.loads(request.raw_post_data) + except: + raise faults.BadRequest('Request body should be json formatted.') + else: + uuids = input_data.get('uuids', []) + if uuids is None and user_call: + uuids = [] + displaynames = input_data.get('displaynames', []) + if displaynames is None and user_call: + displaynames = [] + user_obj = AstakosUser.objects + d = {'uuid_catalog': user_obj.uuid_catalog(uuids), + 'displayname_catalog': user_obj.displayname_catalog(displaynames)} + + response = HttpResponse() + response.content = json.dumps(d) + response['Content-Type'] = 'application/json; charset=UTF-8' + response['Content-Length'] = len(response.content) + return response + + +def __send_feedback(request, email_template_name='im/feedback_mail.txt', + user=None): + if not user: + auth_token = request.POST.get('auth', '') + if not auth_token: + raise faults.BadRequest('Missing user authentication') + + try: + user = AstakosUser.objects.get(auth_token=auth_token) + except AstakosUser.DoesNotExist: + raise faults.BadRequest('Invalid user authentication') + + form = FeedbackForm(request.POST) + if not form.is_valid(): + logger.error("Invalid feedback request: %r", form.errors) + raise faults.BadRequest('Invalid data') + + msg = form.cleaned_data['feedback_msg'] + data = form.cleaned_data['feedback_data'] + try: + send_feedback_func(msg, data, user, email_template_name) + except: + return HttpResponse(status=502) + return HttpResponse(status=200) diff --git a/snf-astakos-app/astakos/im/urls.py b/snf-astakos-app/astakos/im/urls.py index 5058460de..729a65250 100644 --- a/snf-astakos-app/astakos/im/urls.py +++ b/snf-astakos-app/astakos/im/urls.py @@ -147,15 +147,15 @@ if 'linkedin' in settings.IM_MODULES: 'linkedin.authenticated')) urlpatterns += patterns( - 'astakos.im.api', + 'astakos.api', url(r'^get_services/?$', 'get_services'), url(r'^get_menu/?$', 'get_menu')) urlpatterns += patterns( - 'astakos.im.api', + 'astakos.api', url(r'^get_services/?$', 'get_services'), url(r'^get_menu/?$', 'get_menu')) urlpatterns += patterns( - 'astakos.im.api.user', + 'astakos.api.user', url(r'^authenticate/?$', 'authenticate')) diff --git a/snf-astakos-app/astakos/im/views.py b/snf-astakos-app/astakos/im/views.py index c307316de..cba5ed050 100644 --- a/snf-astakos-app/astakos/im/views.py +++ b/snf-astakos-app/astakos/im/views.py @@ -110,7 +110,6 @@ from astakos.im.settings import ( ACTIVATION_REDIRECT_URL, MODERATION_ENABLED) from astakos.im import presentation -from astakos.im.api import get_services_dict from astakos.im import settings as astakos_settings from astakos.im.api.callpoint import AstakosCallpoint from astakos.im import auth_providers as auth @@ -425,7 +424,7 @@ def edit_profile(request, template_name='im/profile.html', extra_context=None): # providers that user can add user_available_providers = request.user.get_available_auth_providers() - extra_context['services'] = get_services_dict() + extra_context['services'] = Service.catalog().values() return render_response(template_name, profile_form = form, user_providers = user_providers, diff --git a/snf-astakos-app/astakos/test/settings/local.conf b/snf-astakos-app/astakos/test/settings/local.conf index 68694a1f6..8575e4dd9 100644 --- a/snf-astakos-app/astakos/test/settings/local.conf +++ b/snf-astakos-app/astakos/test/settings/local.conf @@ -21,7 +21,7 @@ HOST = 'http://127.0.0.1' QUOTAHOLDER_URL = HOST + ':8008/quotaholder/v' QUOTAHOLDER_TOKEN = 'token' -ASTAKOS_URL = HOST + ':8000/im/authenticate' +ASTAKOS_URL = HOST + ':8000/astakos/api/authenticate' ASTAKOS_BASEURL = HOST + ':8000/' ASTAKOS_IM_MODULES = ['local'] ASTAKOS_RECAPTCHA_ENABLED = False diff --git a/snf-astakos-app/astakos/urls.py b/snf-astakos-app/astakos/urls.py index bfae48e66..448ce60b3 100644 --- a/snf-astakos-app/astakos/urls.py +++ b/snf-astakos-app/astakos/urls.py @@ -33,10 +33,9 @@ from django.conf.urls.defaults import include, patterns -urlpatterns = patterns('', - (r'^im/', include('astakos.im.urls')), - (r'^astakos/api/', include('astakos.api.urls')), - (r'^login/?$', 'astakos.im.target.redirect.login'), - (r'^feedback/?$', 'astakos.im.api.user.send_feedback'), - (r'^user_catalogs/?$', 'astakos.im.api.user.get_uuid_displayname_catalogs'), - (r'^service/api/user_catalogs/?$', 'astakos.im.api.service.get_uuid_displayname_catalogs')) +urlpatterns = patterns( + '', + (r'^im/', include('astakos.im.urls')), + (r'^login/?$', 'astakos.im.target.redirect.login'), + (r'^astakos/api/', include('astakos.api.urls')), +) diff --git a/snf-astakos-app/conf/20-snf-astakos-app-cloudbar.conf b/snf-astakos-app/conf/20-snf-astakos-app-cloudbar.conf index 7939864cb..0a14224cd 100644 --- a/snf-astakos-app/conf/20-snf-astakos-app-cloudbar.conf +++ b/snf-astakos-app/conf/20-snf-astakos-app-cloudbar.conf @@ -1,5 +1,5 @@ #CLOUDBAR_ACTIVE = True #CLOUDBAR_LOCATION = 'https://accounts.okeanos.grnet.gr/static/im/cloudbar/' #CLOUDBAR_COOKIE_NAME = '_pithos2_a' -#CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/im/get_services' -#CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/im/get_menu' +#CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_services' +#CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_menu' diff --git a/snf-common/synnefo/lib/context_processors.py b/snf-common/synnefo/lib/context_processors.py index cf663bce0..0a18ab2ef 100644 --- a/snf-common/synnefo/lib/context_processors.py +++ b/snf-common/synnefo/lib/context_processors.py @@ -36,9 +36,9 @@ def cloudbar(request): CB_ACTIVE_SERVICE = getattr(settings, 'CLOUDBAR_ACTIVE_SERVICE', 'cloud') CB_SERVICES_URL = getattr(settings, 'CLOUDBAR_SERVICES_URL', - 'https://accounts.okeanos.grnet.gr/im/get_services') + 'https://accounts.okeanos.grnet.gr/astakos/api/get_services') CB_MENU_URL = getattr(settings, 'CLOUDBAR_MENU_URL', - 'https://accounts.okeanos.grnet.gr/im/get_menu') + 'https://accounts.okeanos.grnet.gr/astakos/api/get_menu') CB_HEIGHT = getattr(settings, 'CLOUDBAR_HEIGHT', '35') CB_BGCOLOR = getattr(settings, 'CLOUDBAR_BACKGROUND_COLOR', diff --git a/snf-cyclades-app/conf/20-snf-cyclades-app-cloudbar.conf b/snf-cyclades-app/conf/20-snf-cyclades-app-cloudbar.conf index 184b7396d..0fd2e802b 100644 --- a/snf-cyclades-app/conf/20-snf-cyclades-app-cloudbar.conf +++ b/snf-cyclades-app/conf/20-snf-cyclades-app-cloudbar.conf @@ -2,6 +2,6 @@ #CLOUDBAR_LOCATION = 'https://accounts.okeanos.grnet.gr/static/im/cloudbar/' #CLOUDBAR_COOKIE_NAME = '_pithos2_a' #CLOUDBAR_ACTIVE_SERVICE = 'cloud' -#CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/im/get_services' -#CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/im/get_menu' +#CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_services' +#CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_menu' # diff --git a/snf-cyclades-app/synnefo/api/delegate.py b/snf-cyclades-app/synnefo/api/delegate.py index 5b360bc97..ef09085e9 100644 --- a/snf-cyclades-app/synnefo/api/delegate.py +++ b/snf-cyclades-app/synnefo/api/delegate.py @@ -40,10 +40,10 @@ from django.views.decorators.csrf import csrf_exempt from django.conf import settings ASTAKOS_URL = getattr(settings, 'ASTAKOS_URL', None) -USER_CATALOG_URL = urlparse.urljoin(ASTAKOS_URL, "user_catalogs") -USER_FEEDBACK_URL = urlparse.urljoin(ASTAKOS_URL, "feedback") USER_QUOTA_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/quotas") RESOURCES_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/resources") +USER_CATALOG_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/user_catalogs") +USER_FEEDBACK_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/feedback") from objpool.http import PooledHTTPConnection diff --git a/snf-cyclades-app/synnefo/app_settings/default/cloudbar.py b/snf-cyclades-app/synnefo/app_settings/default/cloudbar.py index 3124b458b..064386998 100644 --- a/snf-cyclades-app/synnefo/app_settings/default/cloudbar.py +++ b/snf-cyclades-app/synnefo/app_settings/default/cloudbar.py @@ -2,6 +2,6 @@ CLOUDBAR_ACTIVE = True CLOUDBAR_LOCATION = 'https://accounts.okeanos.grnet.gr/static/im/cloudbar/' CLOUDBAR_COOKIE_NAME = '_pithos2_a' CLOUDBAR_ACTIVE_SERVICE = 'cloud' -CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/im/get_services' -CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/im/get_menu' +CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_services' +CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/astakos/api/get_menu' diff --git a/snf-cyclades-app/synnefo/ui/views.py b/snf-cyclades-app/synnefo/ui/views.py index 6de33ddc4..56653aedd 100644 --- a/snf-cyclades-app/synnefo/ui/views.py +++ b/snf-cyclades-app/synnefo/ui/views.py @@ -157,8 +157,8 @@ GROUP_PUBLIC_NETWORKS = getattr(settings, 'UI_GROUP_PUBLIC_NETWORKS', True) GROUPED_PUBLIC_NETWORK_NAME = \ getattr(settings, 'UI_GROUPED_PUBLIC_NETWORK_NAME', 'Internet') -USER_CATALOG_URL = getattr(settings, 'UI_USER_CATALOG_URL', '/user_catalogs') -FEEDBACK_POST_URL = getattr(settings, 'UI_FEEDBACK_POST_URL', '/feedback') +USER_CATALOG_URL = getattr(settings, 'UI_USER_CATALOG_URL', '/astakos/api/user_catalogs') +FEEDBACK_POST_URL = getattr(settings, 'UI_FEEDBACK_POST_URL', '/astakos/api/feedback') TRANSLATE_UUIDS = not getattr(settings, 'TRANSLATE_UUIDS', False) ACCOUNTS_API_URL = getattr(settings, 'UI_ACCOUNTS_API_URL', '/astakos/api') diff --git a/snf-pithos-app/pithos/api/delegate.py b/snf-pithos-app/pithos/api/delegate.py index 6fa6b9e6e..a52ea89de 100644 --- a/snf-pithos-app/pithos/api/delegate.py +++ b/snf-pithos-app/pithos/api/delegate.py @@ -40,13 +40,15 @@ from django.http import ( from django.utils.http import urlencode from django.views.decorators.csrf import csrf_exempt -from pithos.api.settings import (USER_LOGIN_URL, USER_FEEDBACK_URL, - USER_CATALOG_URL) +from pithos.api.settings import ASTAKOS_URL from objpool.http import PooledHTTPConnection logger = logging.getLogger(__name__) +USER_CATALOG_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/user_catalogs") +USER_FEEDBACK_URL = urlparse.urljoin(ASTAKOS_URL, "astakos/api/feedback") +USER_LOGIN_URL = urljoin(ASTAKOS_URL, "login") def delegate_to_login_service(request): url = USER_LOGIN_URL diff --git a/snf-pithos-app/pithos/api/settings.py b/snf-pithos-app/pithos/api/settings.py index 6f78b6ed7..ef9be418e 100644 --- a/snf-pithos-app/pithos/api/settings.py +++ b/snf-pithos-app/pithos/api/settings.py @@ -59,10 +59,6 @@ TRANSLATE_UUIDS = getattr(settings, 'PITHOS_TRANSLATE_UUIDS', False) # the requests on its own. PROXY_USER_SERVICES = getattr(settings, 'PITHOS_PROXY_USER_SERVICES', True) -USER_CATALOG_URL = urljoin(ASTAKOS_URL, "user_catalogs") -USER_FEEDBACK_URL = urljoin(ASTAKOS_URL, "feedback") -USER_LOGIN_URL = urljoin(ASTAKOS_URL, "login") - # Set how many random bytes to use for constructing the URL of Pithos public files PUBLIC_URL_SECURITY = getattr(settings, 'PITHOS_PUBLIC_URL_SECURITY', 16) # Set the alphabet to use for constructing the URL of Pithos public files -- GitLab