Revision 04a1b675
b/contrib/snf-pithos-tools/pithos/tools/sh.py | ||
---|---|---|
96 | 96 |
|
97 | 97 |
if email_re.match(self.user): |
98 | 98 |
try: |
99 |
from synnefo.lib.astakos import get_user_uuid
|
|
99 |
from snf_django.lib.astakos import get_user_uuid
|
|
100 | 100 |
from pithos.api.settings import SERVICE_TOKEN |
101 | 101 |
self.user = get_user_uuid(SERVICE_TOKEN, self.user) |
102 | 102 |
except ImportError: |
/dev/null | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import logging |
|
35 |
|
|
36 |
from urlparse import urlparse |
|
37 |
from urllib import unquote |
|
38 |
from django.utils import simplejson as json |
|
39 |
|
|
40 |
from objpool.http import PooledHTTPConnection |
|
41 |
|
|
42 |
logger = logging.getLogger(__name__) |
|
43 |
|
|
44 |
|
|
45 |
def retry(howmany): |
|
46 |
def execute(func): |
|
47 |
def f(*args, **kwargs): |
|
48 |
attempts = 0 |
|
49 |
while True: |
|
50 |
try: |
|
51 |
return func(*args, **kwargs) |
|
52 |
except Exception, e: |
|
53 |
is_last_attempt = attempts == howmany - 1 |
|
54 |
if is_last_attempt: |
|
55 |
raise e |
|
56 |
if e.args: |
|
57 |
status = e.args[-1] |
|
58 |
# In case of Unauthorized response |
|
59 |
# or Not Found return directly |
|
60 |
if status == 401 or status == 404: |
|
61 |
raise e |
|
62 |
attempts += 1 |
|
63 |
return f |
|
64 |
return execute |
|
65 |
|
|
66 |
|
|
67 |
def call(token, url, headers=None, body=None, method='GET'): |
|
68 |
p = urlparse(url) |
|
69 |
|
|
70 |
kwargs = {} |
|
71 |
if headers is None: |
|
72 |
headers = {} |
|
73 |
kwargs["headers"] = headers |
|
74 |
kwargs['headers']['X-Auth-Token'] = token |
|
75 |
if body: |
|
76 |
kwargs['body'] = body |
|
77 |
kwargs['headers'].setdefault('content-type', |
|
78 |
'application/octet-stream') |
|
79 |
kwargs['headers'].setdefault('content-length', len(body) if body else 0) |
|
80 |
|
|
81 |
with PooledHTTPConnection(p.netloc, p.scheme) as conn: |
|
82 |
conn.request(method, p.path + '?' + p.query, **kwargs) |
|
83 |
response = conn.getresponse() |
|
84 |
headers = response.getheaders() |
|
85 |
headers = dict((unquote(h), unquote(v)) for h, v in headers) |
|
86 |
length = response.getheader('content-length', None) |
|
87 |
data = response.read(length) |
|
88 |
status = int(response.status) |
|
89 |
|
|
90 |
if status < 200 or status >= 300: |
|
91 |
raise Exception(data, status) |
|
92 |
|
|
93 |
return json.loads(data) |
|
94 |
|
|
95 |
|
|
96 |
def authenticate( |
|
97 |
token, authentication_url='http://127.0.0.1:8000/im/authenticate', |
|
98 |
usage=False): |
|
99 |
|
|
100 |
if usage: |
|
101 |
authentication_url += "?usage=1" |
|
102 |
|
|
103 |
return call(token, authentication_url) |
|
104 |
|
|
105 |
|
|
106 |
@retry(3) |
|
107 |
def get_displaynames( |
|
108 |
token, |
|
109 |
uuids, |
|
110 |
url='http://127.0.0.1:8000/user_catalogs', |
|
111 |
override_users={}): |
|
112 |
|
|
113 |
if override_users: |
|
114 |
return dict((u, u) for u in uuids) |
|
115 |
|
|
116 |
try: |
|
117 |
data = call( |
|
118 |
token, url, headers={'content-type': 'application/json'}, |
|
119 |
body=json.dumps({'uuids': uuids}), method='POST') |
|
120 |
except: |
|
121 |
raise |
|
122 |
else: |
|
123 |
return data.get('uuid_catalog') |
|
124 |
|
|
125 |
|
|
126 |
@retry(3) |
|
127 |
def get_uuids( |
|
128 |
token, |
|
129 |
displaynames, |
|
130 |
url='http://127.0.0.1:8000/user_catalogs', |
|
131 |
override_users={}): |
|
132 |
|
|
133 |
if override_users: |
|
134 |
return dict((u, u) for u in displaynames) |
|
135 |
|
|
136 |
try: |
|
137 |
data = call( |
|
138 |
token, url, headers={'content-type': 'application/json'}, |
|
139 |
body=json.dumps({'displaynames': displaynames}), method='POST') |
|
140 |
except: |
|
141 |
raise |
|
142 |
else: |
|
143 |
return data.get('displayname_catalog') |
|
144 |
|
|
145 |
|
|
146 |
def get_user_uuid( |
|
147 |
token, |
|
148 |
displayname, |
|
149 |
url='http://127.0.0.1:8000/user_catalogs', |
|
150 |
override_users={}): |
|
151 |
|
|
152 |
if not displayname: |
|
153 |
return |
|
154 |
|
|
155 |
displayname_dict = get_uuids(token, [displayname], url, override_users) |
|
156 |
return displayname_dict.get(displayname) |
|
157 |
|
|
158 |
|
|
159 |
def get_displayname( |
|
160 |
token, |
|
161 |
uuid, |
|
162 |
url='http://127.0.0.1:8000/user_catalogs', |
|
163 |
override_users={}): |
|
164 |
|
|
165 |
if not uuid: |
|
166 |
return |
|
167 |
|
|
168 |
uuid_dict = get_displaynames(token, [uuid], url, override_users) |
|
169 |
return uuid_dict.get(uuid) |
|
170 |
|
|
171 |
|
|
172 |
def user_for_token(token, authentication_url, usage=False): |
|
173 |
if not token: |
|
174 |
return None |
|
175 |
|
|
176 |
try: |
|
177 |
return authenticate(token, authentication_url, usage=usage) |
|
178 |
except Exception, e: |
|
179 |
# In case of Unauthorized response return None |
|
180 |
if e.args and e.args[-1] == 401: |
|
181 |
return None |
|
182 |
raise e |
|
183 |
|
|
184 |
|
|
185 |
def get_user( |
|
186 |
request, |
|
187 |
authentication_url='http://127.0.0.1:8000/im/authenticate', |
|
188 |
fallback_token=None, |
|
189 |
usage=False): |
|
190 |
request.user = None |
|
191 |
request.user_uniq = None |
|
192 |
|
|
193 |
# Try to find token in a parameter or in a request header. |
|
194 |
user = user_for_token( |
|
195 |
request.GET.get('X-Auth-Token'), authentication_url, |
|
196 |
usage=usage) |
|
197 |
if not user: |
|
198 |
user = user_for_token( |
|
199 |
request.META.get('HTTP_X_AUTH_TOKEN'), |
|
200 |
authentication_url, |
|
201 |
usage=usage) |
|
202 |
if not user: |
|
203 |
user = user_for_token(fallback_token, authentication_url, usage=usage) |
|
204 |
if not user: |
|
205 |
logger.warning("Cannot retrieve user details from %s", |
|
206 |
authentication_url) |
|
207 |
return None |
|
208 |
|
|
209 |
# use user uuid, instead of email, keep email/displayname reference |
|
210 |
# to user_id |
|
211 |
request.user_uniq = user['uuid'] |
|
212 |
request.user = user |
|
213 |
request.user_id = user.get('displayname') |
|
214 |
return user |
|
215 |
|
|
216 |
|
|
217 |
def get_token_from_cookie(request, cookiename): |
|
218 |
""" |
|
219 |
Extract token from the cookie name provided. Cookie should be in the same |
|
220 |
form as astakos service sets its cookie contents:: |
|
221 |
|
|
222 |
<user_uniq>|<user_token> |
|
223 |
""" |
|
224 |
try: |
|
225 |
cookie_content = unquote(request.COOKIES.get(cookiename, None)) |
|
226 |
return cookie_content.split("|")[1] |
|
227 |
except AttributeError: |
|
228 |
pass |
|
229 |
|
|
230 |
return None |
|
231 |
|
|
232 |
|
|
233 |
class UserCache(object): |
|
234 |
"""uuid<->displayname user 'cache'""" |
|
235 |
|
|
236 |
def __init__(self, astakos_url, astakos_token, split=100): |
|
237 |
self.astakos_token = astakos_token |
|
238 |
self.astakos_url = astakos_url |
|
239 |
self.user_catalog_url = astakos_url.replace("im/authenticate", |
|
240 |
"service/api/user_catalogs") |
|
241 |
self.users = {} |
|
242 |
|
|
243 |
self.split = split |
|
244 |
assert(self.split > 0), "split must be positive" |
|
245 |
|
|
246 |
def fetch_names(self, uuid_list): |
|
247 |
total = len(uuid_list) |
|
248 |
split = self.split |
|
249 |
|
|
250 |
for start in range(0, total, split): |
|
251 |
end = start + split |
|
252 |
try: |
|
253 |
names = get_displaynames(token=self.astakos_token, |
|
254 |
url=self.user_catalog_url, |
|
255 |
uuids=uuid_list[start:end]) |
|
256 |
self.users.update(names) |
|
257 |
except Exception as e: |
|
258 |
logger.error("Failed to fetch names: %s", e) |
|
259 |
|
|
260 |
def get_uuid(self, name): |
|
261 |
if not name in self.users: |
|
262 |
try: |
|
263 |
self.users[name] = get_user_uuid(token=self.astakos_token, |
|
264 |
url=self.user_catalog_url, |
|
265 |
displayname=name) |
|
266 |
except Exception as e: |
|
267 |
logger.error("Can not get uuid for name %s: %s", name, e) |
|
268 |
self.users[name] = name |
|
269 |
|
|
270 |
return self.users[name] |
|
271 |
|
|
272 |
def get_name(self, uuid): |
|
273 |
"""Do the uuid-to-email resolving""" |
|
274 |
|
|
275 |
if not uuid in self.users: |
|
276 |
try: |
|
277 |
self.users[uuid] = get_displayname(token=self.astakos_token, |
|
278 |
url=self.user_catalog_url, |
|
279 |
uuid=uuid) |
|
280 |
except Exception as e: |
|
281 |
logging.error("Can not get display name for uuid %s: %s", |
|
282 |
uuid, e) |
|
283 |
self.users[uuid] = "-" |
|
284 |
|
|
285 |
return self.users[uuid] |
b/snf-cyclades-app/synnefo/api/management/commands/cyclades-astakos-migrate-013.py | ||
---|---|---|
47 | 47 |
from synnefo.db.models import Network, VirtualMachine |
48 | 48 |
from synnefo.ui.userdata.models import PublicKeyPair |
49 | 49 |
|
50 |
from synnefo.lib import astakos
|
|
50 |
from snf_django.lib import astakos
|
|
51 | 51 |
|
52 | 52 |
def warn(*msgs): |
53 | 53 |
print "WARNING: %s" % ' '.join(msgs) |
b/snf-cyclades-app/synnefo/api/management/commands/server-inspect.py | ||
---|---|---|
36 | 36 |
from django.core.management.base import BaseCommand, CommandError |
37 | 37 |
|
38 | 38 |
from synnefo.lib.utils import merge_time |
39 |
from synnefo.lib.astakos import UserCache
|
|
39 |
from snf_django.lib.astakos import UserCache
|
|
40 | 40 |
from synnefo.logic.rapi import GanetiApiError |
41 | 41 |
from synnefo.management.common import Omit |
42 | 42 |
from synnefo.management import common |
b/snf-cyclades-app/synnefo/api/management/commands/server-show.py | ||
---|---|---|
35 | 35 |
from synnefo.webproject.management.commands import SynnefoCommand |
36 | 36 |
from synnefo.management.common import (format_vm_state, get_vm, |
37 | 37 |
get_image) |
38 |
from synnefo.lib.astakos import UserCache
|
|
38 |
from snf_django.lib.astakos import UserCache
|
|
39 | 39 |
from synnefo.settings import (CYCLADES_ASTAKOS_SERVICE_TOKEN as ASTAKOS_TOKEN, |
40 | 40 |
ASTAKOS_URL) |
41 | 41 |
from synnefo.webproject.management import utils |
b/snf-cyclades-app/synnefo/api/util.py | ||
---|---|---|
62 | 62 |
BridgePoolTable, MacPrefixPoolTable) |
63 | 63 |
from synnefo.db.pools import EmptyPool |
64 | 64 |
|
65 |
from synnefo.lib.astakos import get_user
|
|
65 |
from snf_django.lib.astakos import get_user
|
|
66 | 66 |
from synnefo.plankton.utils import image_backend |
67 | 67 |
from synnefo.settings import MAX_CIDR_BLOCK |
68 | 68 |
|
b/snf-cyclades-app/synnefo/helpdesk/tests.py | ||
---|---|---|
92 | 92 |
return None |
93 | 93 |
|
94 | 94 |
# mock the astakos authentication function |
95 |
from synnefo.lib import astakos
|
|
95 |
from snf_django.lib import astakos
|
|
96 | 96 |
astakos.get_user = get_user_mock |
97 | 97 |
astakos.get_displayname = get_displayname_mock |
98 | 98 |
astakos.get_user_uuid = get_uuid_mock |
b/snf-cyclades-app/synnefo/helpdesk/views.py | ||
---|---|---|
43 | 43 |
|
44 | 44 |
from urllib import unquote |
45 | 45 |
|
46 |
from synnefo.lib.astakos import get_user
|
|
46 |
from snf_django.lib.astakos import get_user
|
|
47 | 47 |
from synnefo.db.models import VirtualMachine, NetworkInterface, Network |
48 |
from synnefo.lib import astakos
|
|
48 |
from snf_django.lib import astakos
|
|
49 | 49 |
|
50 | 50 |
# server actions specific imports |
51 | 51 |
from synnefo.api import servers |
b/snf-cyclades-app/synnefo/logic/management/commands/network-inspect.py | ||
---|---|---|
41 | 41 |
from synnefo.db.models import (Backend, BackendNetwork, |
42 | 42 |
pooled_rapi_client) |
43 | 43 |
from synnefo.logic.rapi import GanetiApiError |
44 |
from synnefo.lib.astakos import UserCache
|
|
44 |
from snf_django.lib.astakos import UserCache
|
|
45 | 45 |
from synnefo.settings import (CYCLADES_ASTAKOS_SERVICE_TOKEN as ASTAKOS_TOKEN, |
46 | 46 |
ASTAKOS_URL) |
47 | 47 |
from util import pool_map_chunks |
b/snf-cyclades-app/synnefo/plankton/backend.py | ||
---|---|---|
62 | 62 |
|
63 | 63 |
from pithos.backends.base import NotAllowedError |
64 | 64 |
|
65 |
import synnefo.lib.astakos as lib_astakos
|
|
65 |
import snf_django.lib.astakos as lib_astakos
|
|
66 | 66 |
import logging |
67 | 67 |
|
68 | 68 |
from synnefo.settings import (CYCLADES_USE_QUOTAHOLDER, |
b/snf-cyclades-app/synnefo/plankton/util.py | ||
---|---|---|
40 | 40 |
HttpResponseServerError, HttpResponseForbidden) |
41 | 41 |
|
42 | 42 |
from snf_django.lib.api import faults |
43 |
from synnefo.lib.astakos import get_user
|
|
43 |
from snf_django.lib.astakos import get_user
|
|
44 | 44 |
from synnefo.plankton.backend import (ImageBackend, BackendException, |
45 | 45 |
NotAllowedError) |
46 | 46 |
|
b/snf-cyclades-app/synnefo/ui/userdata/rest.py | ||
---|---|---|
41 | 41 |
|
42 | 42 |
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS |
43 | 43 |
|
44 |
from synnefo.lib.astakos import get_user
|
|
44 |
from snf_django.lib.astakos import get_user
|
|
45 | 45 |
from django.conf import settings |
46 | 46 |
|
47 | 47 |
# base view class |
b/snf-cyclades-app/synnefo/ui/userdata/tests.py | ||
---|---|---|
60 | 60 |
request.user = {'uniq': 'test'} |
61 | 61 |
|
62 | 62 |
# mock the astakos authentication function |
63 |
from synnefo.lib import astakos
|
|
63 |
from snf_django.lib import astakos
|
|
64 | 64 |
astakos.get_user = get_user_mock |
65 | 65 |
|
66 | 66 |
settings.SKIP_SSH_VALIDATION = True |
b/snf-cyclades-app/synnefo/ui/userdata/views.py | ||
---|---|---|
40 | 40 |
from synnefo.ui.userdata import rest |
41 | 41 |
from synnefo.ui.userdata.models import PublicKeyPair |
42 | 42 |
from synnefo.ui.userdata.util import exportKey |
43 |
from synnefo.lib.astakos import get_user
|
|
43 |
from snf_django.lib.astakos import get_user
|
|
44 | 44 |
|
45 | 45 |
SUPPORT_GENERATE_KEYS = True |
46 | 46 |
try: |
b/snf-cyclades-app/synnefo/ui/views.py | ||
---|---|---|
49 | 49 |
|
50 | 50 |
from synnefo.util.version import get_component_version |
51 | 51 |
|
52 |
from synnefo.lib.astakos import get_user
|
|
52 |
from snf_django.lib.astakos import get_user
|
|
53 | 53 |
|
54 | 54 |
SYNNEFO_JS_LIB_VERSION = get_component_version('app') |
55 | 55 |
|
b/snf-django-lib/snf_django/lib/astakos.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import logging |
|
35 |
|
|
36 |
from urlparse import urlparse |
|
37 |
from urllib import unquote |
|
38 |
from django.utils import simplejson as json |
|
39 |
|
|
40 |
from objpool.http import PooledHTTPConnection |
|
41 |
|
|
42 |
logger = logging.getLogger(__name__) |
|
43 |
|
|
44 |
|
|
45 |
def retry(howmany): |
|
46 |
def execute(func): |
|
47 |
def f(*args, **kwargs): |
|
48 |
attempts = 0 |
|
49 |
while True: |
|
50 |
try: |
|
51 |
return func(*args, **kwargs) |
|
52 |
except Exception, e: |
|
53 |
is_last_attempt = attempts == howmany - 1 |
|
54 |
if is_last_attempt: |
|
55 |
raise e |
|
56 |
if e.args: |
|
57 |
status = e.args[-1] |
|
58 |
# In case of Unauthorized response |
|
59 |
# or Not Found return directly |
|
60 |
if status == 401 or status == 404: |
|
61 |
raise e |
|
62 |
attempts += 1 |
|
63 |
return f |
|
64 |
return execute |
|
65 |
|
|
66 |
|
|
67 |
def call(token, url, headers=None, body=None, method='GET'): |
|
68 |
p = urlparse(url) |
|
69 |
|
|
70 |
kwargs = {} |
|
71 |
if headers is None: |
|
72 |
headers = {} |
|
73 |
kwargs["headers"] = headers |
|
74 |
kwargs['headers']['X-Auth-Token'] = token |
|
75 |
if body: |
|
76 |
kwargs['body'] = body |
|
77 |
kwargs['headers'].setdefault('content-type', |
|
78 |
'application/octet-stream') |
|
79 |
kwargs['headers'].setdefault('content-length', len(body) if body else 0) |
|
80 |
|
|
81 |
with PooledHTTPConnection(p.netloc, p.scheme) as conn: |
|
82 |
conn.request(method, p.path + '?' + p.query, **kwargs) |
|
83 |
response = conn.getresponse() |
|
84 |
headers = response.getheaders() |
|
85 |
headers = dict((unquote(h), unquote(v)) for h, v in headers) |
|
86 |
length = response.getheader('content-length', None) |
|
87 |
data = response.read(length) |
|
88 |
status = int(response.status) |
|
89 |
|
|
90 |
if status < 200 or status >= 300: |
|
91 |
raise Exception(data, status) |
|
92 |
|
|
93 |
return json.loads(data) |
|
94 |
|
|
95 |
|
|
96 |
def authenticate( |
|
97 |
token, authentication_url='http://127.0.0.1:8000/im/authenticate', |
|
98 |
usage=False): |
|
99 |
|
|
100 |
if usage: |
|
101 |
authentication_url += "?usage=1" |
|
102 |
|
|
103 |
return call(token, authentication_url) |
|
104 |
|
|
105 |
|
|
106 |
@retry(3) |
|
107 |
def get_displaynames( |
|
108 |
token, |
|
109 |
uuids, |
|
110 |
url='http://127.0.0.1:8000/user_catalogs', |
|
111 |
override_users={}): |
|
112 |
|
|
113 |
if override_users: |
|
114 |
return dict((u, u) for u in uuids) |
|
115 |
|
|
116 |
try: |
|
117 |
data = call( |
|
118 |
token, url, headers={'content-type': 'application/json'}, |
|
119 |
body=json.dumps({'uuids': uuids}), method='POST') |
|
120 |
except: |
|
121 |
raise |
|
122 |
else: |
|
123 |
return data.get('uuid_catalog') |
|
124 |
|
|
125 |
|
|
126 |
@retry(3) |
|
127 |
def get_uuids( |
|
128 |
token, |
|
129 |
displaynames, |
|
130 |
url='http://127.0.0.1:8000/user_catalogs', |
|
131 |
override_users={}): |
|
132 |
|
|
133 |
if override_users: |
|
134 |
return dict((u, u) for u in displaynames) |
|
135 |
|
|
136 |
try: |
|
137 |
data = call( |
|
138 |
token, url, headers={'content-type': 'application/json'}, |
|
139 |
body=json.dumps({'displaynames': displaynames}), method='POST') |
|
140 |
except: |
|
141 |
raise |
|
142 |
else: |
|
143 |
return data.get('displayname_catalog') |
|
144 |
|
|
145 |
|
|
146 |
def get_user_uuid( |
|
147 |
token, |
|
148 |
displayname, |
|
149 |
url='http://127.0.0.1:8000/user_catalogs', |
|
150 |
override_users={}): |
|
151 |
|
|
152 |
if not displayname: |
|
153 |
return |
|
154 |
|
|
155 |
displayname_dict = get_uuids(token, [displayname], url, override_users) |
|
156 |
return displayname_dict.get(displayname) |
|
157 |
|
|
158 |
|
|
159 |
def get_displayname( |
|
160 |
token, |
|
161 |
uuid, |
|
162 |
url='http://127.0.0.1:8000/user_catalogs', |
|
163 |
override_users={}): |
|
164 |
|
|
165 |
if not uuid: |
|
166 |
return |
|
167 |
|
|
168 |
uuid_dict = get_displaynames(token, [uuid], url, override_users) |
|
169 |
return uuid_dict.get(uuid) |
|
170 |
|
|
171 |
|
|
172 |
def user_for_token(token, authentication_url, usage=False): |
|
173 |
if not token: |
|
174 |
return None |
|
175 |
|
|
176 |
try: |
|
177 |
return authenticate(token, authentication_url, usage=usage) |
|
178 |
except Exception, e: |
|
179 |
# In case of Unauthorized response return None |
|
180 |
if e.args and e.args[-1] == 401: |
|
181 |
return None |
|
182 |
raise e |
|
183 |
|
|
184 |
|
|
185 |
def get_user( |
|
186 |
request, |
|
187 |
authentication_url='http://127.0.0.1:8000/im/authenticate', |
|
188 |
fallback_token=None, |
|
189 |
usage=False): |
|
190 |
request.user = None |
|
191 |
request.user_uniq = None |
|
192 |
|
|
193 |
# Try to find token in a parameter or in a request header. |
|
194 |
user = user_for_token( |
|
195 |
request.GET.get('X-Auth-Token'), authentication_url, |
|
196 |
usage=usage) |
|
197 |
if not user: |
|
198 |
user = user_for_token( |
|
199 |
request.META.get('HTTP_X_AUTH_TOKEN'), |
|
200 |
authentication_url, |
|
201 |
usage=usage) |
|
202 |
if not user: |
|
203 |
user = user_for_token(fallback_token, authentication_url, usage=usage) |
|
204 |
if not user: |
|
205 |
logger.warning("Cannot retrieve user details from %s", |
|
206 |
authentication_url) |
|
207 |
return None |
|
208 |
|
|
209 |
# use user uuid, instead of email, keep email/displayname reference |
|
210 |
# to user_id |
|
211 |
request.user_uniq = user['uuid'] |
|
212 |
request.user = user |
|
213 |
request.user_id = user.get('displayname') |
|
214 |
return user |
|
215 |
|
|
216 |
|
|
217 |
def get_token_from_cookie(request, cookiename): |
|
218 |
""" |
|
219 |
Extract token from the cookie name provided. Cookie should be in the same |
|
220 |
form as astakos service sets its cookie contents:: |
|
221 |
|
|
222 |
<user_uniq>|<user_token> |
|
223 |
""" |
|
224 |
try: |
|
225 |
cookie_content = unquote(request.COOKIES.get(cookiename, None)) |
|
226 |
return cookie_content.split("|")[1] |
|
227 |
except AttributeError: |
|
228 |
pass |
|
229 |
|
|
230 |
return None |
|
231 |
|
|
232 |
|
|
233 |
class UserCache(object): |
|
234 |
"""uuid<->displayname user 'cache'""" |
|
235 |
|
|
236 |
def __init__(self, astakos_url, astakos_token, split=100): |
|
237 |
self.astakos_token = astakos_token |
|
238 |
self.astakos_url = astakos_url |
|
239 |
self.user_catalog_url = astakos_url.replace("im/authenticate", |
|
240 |
"service/api/user_catalogs") |
|
241 |
self.users = {} |
|
242 |
|
|
243 |
self.split = split |
|
244 |
assert(self.split > 0), "split must be positive" |
|
245 |
|
|
246 |
def fetch_names(self, uuid_list): |
|
247 |
total = len(uuid_list) |
|
248 |
split = self.split |
|
249 |
|
|
250 |
for start in range(0, total, split): |
|
251 |
end = start + split |
|
252 |
try: |
|
253 |
names = get_displaynames(token=self.astakos_token, |
|
254 |
url=self.user_catalog_url, |
|
255 |
uuids=uuid_list[start:end]) |
|
256 |
self.users.update(names) |
|
257 |
except Exception as e: |
|
258 |
logger.error("Failed to fetch names: %s", e) |
|
259 |
|
|
260 |
def get_uuid(self, name): |
|
261 |
if not name in self.users: |
|
262 |
try: |
|
263 |
self.users[name] = get_user_uuid(token=self.astakos_token, |
|
264 |
url=self.user_catalog_url, |
|
265 |
displayname=name) |
|
266 |
except Exception as e: |
|
267 |
logger.error("Can not get uuid for name %s: %s", name, e) |
|
268 |
self.users[name] = name |
|
269 |
|
|
270 |
return self.users[name] |
|
271 |
|
|
272 |
def get_name(self, uuid): |
|
273 |
"""Do the uuid-to-email resolving""" |
|
274 |
|
|
275 |
if not uuid in self.users: |
|
276 |
try: |
|
277 |
self.users[uuid] = get_displayname(token=self.astakos_token, |
|
278 |
url=self.user_catalog_url, |
|
279 |
uuid=uuid) |
|
280 |
except Exception as e: |
|
281 |
logging.error("Can not get display name for uuid %s: %s", |
|
282 |
uuid, e) |
|
283 |
self.users[uuid] = "-" |
|
284 |
|
|
285 |
return self.users[uuid] |
b/snf-pithos-app/pithos/api/functions.py | ||
---|---|---|
40 | 40 |
from django.utils.encoding import smart_str |
41 | 41 |
from django.views.decorators.csrf import csrf_exempt |
42 | 42 |
|
43 |
from synnefo.lib.astakos import get_user, get_uuids as _get_uuids
|
|
43 |
from snf_django.lib.astakos import get_user, get_uuids as _get_uuids
|
|
44 | 44 |
|
45 | 45 |
from snf_django.lib import api |
46 | 46 |
from snf_django.lib.api import faults |
b/snf-pithos-app/pithos/api/util.py | ||
---|---|---|
46 | 46 |
from django.core.files.uploadedfile import UploadedFile |
47 | 47 |
|
48 | 48 |
from snf_django.lib.api.parsedate import parse_http_date_safe, parse_http_date |
49 |
from synnefo.lib.astakos import user_for_token
|
|
49 |
from snf_django.lib.astakos import user_for_token
|
|
50 | 50 |
from snf_django.lib import api |
51 | 51 |
from snf_django.lib.api import faults, utils |
52 | 52 |
|
... | ... | |
67 | 67 |
PUBLIC_URL_ALPHABET) |
68 | 68 |
from pithos.backends.base import (NotAllowedError, QuotaError, ItemNotExists, |
69 | 69 |
VersionNotExists) |
70 |
from synnefo.lib.astakos import (get_user_uuid, get_displayname,
|
|
70 |
from snf_django.lib.astakos import (get_user_uuid, get_displayname,
|
|
71 | 71 |
get_uuids, get_displaynames) |
72 | 72 |
|
73 | 73 |
import logging |
b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/alembic/versions/165ba3fbfe53_update_path_account.py | ||
---|---|---|
13 | 13 |
from alembic import op |
14 | 14 |
from sqlalchemy.sql import table, column, literal, and_ |
15 | 15 |
|
16 |
from synnefo.lib.astakos import get_user_uuid, get_displayname as get_user_displayname
|
|
16 |
from snf_django.lib.astakos import get_user_uuid, get_displayname as get_user_displayname
|
|
17 | 17 |
from pithos.api.settings import ( |
18 | 18 |
SERVICE_TOKEN, USER_CATALOG_URL, AUTHENTICATION_USERS) |
19 | 19 |
|
b/snf-webproject/synnefo/webproject/management/commands/__init__.py | ||
---|---|---|
37 | 37 |
from django.core.exceptions import FieldError |
38 | 38 |
|
39 | 39 |
from synnefo.webproject.management import utils |
40 |
from synnefo.lib.astakos import UserCache
|
|
40 |
from snf_django.lib.astakos import UserCache
|
|
41 | 41 |
|
42 | 42 |
|
43 | 43 |
class SynnefoCommand(BaseCommand): |
Also available in: Unified diff