0002-api-search-api-keys-from-dedicated-storage-objects-t.patch
tests/test_api.py | ||
---|---|---|
294 | 294 |
) |
295 | 295 |
url = signed_url[len('http://example.net'):] |
296 | 296 |
output = get_app(pub).get(url) |
297 | 297 |
assert output.json['user_display_name'] == u'Jean Darmette' |
298 | 298 |
assert [x['name'] for x in output.json['user_roles']] == ['Foo bar'] |
299 | 299 |
assert [x['slug'] for x in output.json['user_roles']] == ['foo-bar'] |
300 | 300 | |
301 | 301 | |
302 |
def test_api_access_from_xml_storable_object(pub, local_user, admin_user): |
|
303 |
app = login(get_app(pub)) |
|
304 |
resp = app.get('/backoffice/settings/api-access/new') |
|
305 |
resp.form['name'] = 'salut' |
|
306 |
resp.form['access_key'] = '5678' |
|
307 |
resp = resp.form.submit('submit') |
|
308 | ||
309 |
Role.wipe() |
|
310 |
role = Role(name='Foo bar') |
|
311 |
role.store() |
|
312 |
local_user.roles = [role.id] |
|
313 |
local_user.store() |
|
314 |
signed_url = sign_url('http://example.net/api/user/?format=json&orig=UNKNOWN_USER&email=%s' % ( |
|
315 |
urllib.quote(local_user.email)), '5678') |
|
316 |
url = signed_url[len('http://example.net'):] |
|
317 |
output = get_app(pub).get(url, status=403) |
|
318 |
assert output.json['err_desc'] == 'invalid orig' |
|
319 | ||
320 |
signed_url = sign_url('http://example.net/api/user/?format=json&orig=salut&email=%s' % ( |
|
321 |
urllib.quote(local_user.email)), '5678') |
|
322 |
url = signed_url[len('http://example.net'):] |
|
323 |
output = get_app(pub).get(url) |
|
324 |
assert output.json['user_display_name'] == u'Jean Darmette' |
|
325 | ||
326 | ||
302 | 327 |
def test_is_url_signed_check_nonce(pub, local_user, freezer): |
303 | 328 |
ORIG = 'xxx' |
304 | 329 |
KEY = 'xxx' |
305 | 330 | |
306 | 331 |
pub.site_options.add_section('api-secrets') |
307 | 332 |
pub.site_options.set('api-secrets', ORIG, KEY) |
308 | 333 |
pub.site_options.write(open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')) |
309 | 334 |
# test clean_nonces do not bark when nonces directory is empty |
wcs/api_access.py | ||
---|---|---|
63 | 63 |
break |
64 | 64 |
else: |
65 | 65 |
break |
66 | 66 |
if obj.id == self.id: |
67 | 67 |
break |
68 | 68 |
suffix_no += 1 |
69 | 69 |
new_access_id = '%s_%s' % (base_new_access_id, suffix_no) |
70 | 70 |
return new_access_id |
71 | ||
72 |
@classmethod |
|
73 |
def get_access_key(cls, access_id): |
|
74 |
for api_access in cls.select(): |
|
75 |
if api_access.access_id == access_id: |
|
76 |
return api_access.access_key |
|
77 |
return None |
wcs/api_utils.py | ||
---|---|---|
24 | 24 |
import calendar |
25 | 25 | |
26 | 26 |
from django.utils import six |
27 | 27 |
from django.utils.encoding import force_bytes, force_text |
28 | 28 |
from django.utils.six.moves.urllib import parse as urllib |
29 | 29 |
from django.utils.six.moves.urllib import parse as urlparse |
30 | 30 | |
31 | 31 |
from quixote import get_request, get_publisher |
32 |
from .api_access import ApiAccess |
|
32 | 33 |
from .qommon.errors import (AccessForbiddenError, HttpResponse401Error, UnknownNameIdAccessForbiddenError) |
33 | 34 |
import qommon.misc |
34 | 35 | |
35 | 36 |
DEFAULT_DURATION = 30 |
36 | 37 | |
37 | 38 | |
38 | 39 |
def is_url_signed(utcnow=None, duration=DEFAULT_DURATION): |
39 | 40 |
if get_request().signed: |
... | ... | |
44 | 45 |
signature = get_request().form.get('signature') |
45 | 46 |
if not isinstance(signature, six.string_types): |
46 | 47 |
return False |
47 | 48 |
signature = force_bytes(signature) |
48 | 49 |
# verify signature |
49 | 50 |
orig = get_request().form.get('orig') |
50 | 51 |
if not isinstance(orig, six.string_types): |
51 | 52 |
raise AccessForbiddenError('missing/multiple orig field') |
52 |
key = get_publisher().get_site_option(orig, 'api-secrets') |
|
53 |
key = ApiAccess.get_access_key(orig) or get_publisher().get_site_option(orig, 'api-secrets')
|
|
53 | 54 |
if not key: |
54 | 55 |
raise AccessForbiddenError('invalid orig') |
55 | 56 |
algo = get_request().form.get('algo') |
56 | 57 |
if not isinstance(algo, six.string_types): |
57 | 58 |
raise AccessForbiddenError('missing/multiple algo field') |
58 | 59 |
if algo not in hashlib.algorithms_guaranteed: |
59 | 60 |
raise AccessForbiddenError('invalid algo') |
60 | 61 |
try: |
61 |
- |