0001-api-allow-mixing-anonymous-restriction-and-basic-aut.patch
tests/api/test_formdata.py | ||
---|---|---|
58 | 58 |
''' |
59 | 59 |
) |
60 | 60 | |
61 |
pub.user_class.wipe() |
|
62 | ||
61 | 63 |
return pub |
62 | 64 | |
63 | 65 | |
... | ... | |
67 | 69 | |
68 | 70 |
@pytest.fixture |
69 | 71 |
def local_user(): |
70 |
get_publisher().user_class.wipe() |
|
71 | 72 |
user = get_publisher().user_class() |
72 | 73 |
user.name = 'Jean Darmette' |
73 | 74 |
user.email = 'jean.darmette@triffouilis.fr' |
... | ... | |
78 | 79 | |
79 | 80 |
@pytest.fixture |
80 | 81 |
def admin_user(): |
81 |
get_publisher().user_class.wipe() |
|
82 | 82 |
user = get_publisher().user_class() |
83 | 83 |
user.name = 'John Doe Admin' |
84 | 84 |
user.email = 'john.doe@example.com' |
... | ... | |
788 | 788 |
assert 'name' in resp.json['evolution'][1]['who'] |
789 | 789 | |
790 | 790 | |
791 |
def test_api_access_restrict_to_anonymised_data(pub, local_user): |
|
791 |
@pytest.mark.parametrize('http_basic_auth', [False, True]) |
|
792 |
def test_api_access_restrict_to_anonymised_data(pub, local_user, http_basic_auth): |
|
792 | 793 |
pub.role_class.wipe() |
793 | 794 |
role = pub.role_class(name='test') |
794 | 795 |
role.store() |
... | ... | |
823 | 824 |
access.access_key = '12345' |
824 | 825 |
access.store() |
825 | 826 | |
826 |
resp = get_app(pub).get( |
|
827 |
sign_uri( |
|
828 |
'/api/forms/test/list?full=on', |
|
829 |
user=local_user, |
|
830 |
orig=access.access_identifier, |
|
831 |
key=access.access_key, |
|
832 |
) |
|
833 |
) |
|
827 |
app = get_app(pub) |
|
828 | ||
829 |
if http_basic_auth: |
|
830 |
# there's not "defaults to admin" permissions in case of basic authentication. |
|
831 |
access.roles = [role] |
|
832 |
access.store() |
|
833 | ||
834 |
def get_url(url, **kwargs): |
|
835 |
app.set_authorization(('Basic', ('test', '12345'))) |
|
836 |
return app.get(url, **kwargs) |
|
837 | ||
838 |
else: |
|
839 | ||
840 |
def get_url(url, **kwargs): |
|
841 |
return app.get( |
|
842 |
sign_uri(url, user=local_user, orig=access.access_identifier, key=access.access_key), **kwargs |
|
843 |
) |
|
844 | ||
845 |
resp = get_url('/api/forms/test/list?full=on') |
|
834 | 846 |
assert len(resp.json) == 10 |
835 | 847 |
assert resp.json[0]['fields']['foobar'] == 'FOO BAR1' |
836 | 848 |
assert resp.json[0]['fields']['foobar2'] == 'FOO BAR 2' |
837 | 849 |
assert resp.json[0].get('user') |
838 | 850 | |
851 |
# get a single formdata |
|
852 |
resp = get_url('/api/forms/test/%s/' % formdata.id) |
|
853 |
assert 'user' in resp.json |
|
854 | ||
839 | 855 |
# restrict API access to anonymised data |
840 | 856 |
access.restrict_to_anonymised_data = True |
841 | 857 |
access.store() |
842 | 858 | |
843 |
resp = get_app(pub).get( |
|
844 |
sign_uri( |
|
845 |
'/api/forms/test/list?full=on', |
|
846 |
user=local_user, |
|
847 |
orig=access.access_identifier, |
|
848 |
key=access.access_key, |
|
849 |
) |
|
850 |
) |
|
859 |
resp = get_url('/api/forms/test/list?full=on') |
|
851 | 860 |
assert len(resp.json) == 10 |
852 | 861 |
assert 'foobar' not in resp.json[0]['fields'] |
853 | 862 |
assert resp.json[0]['fields']['foobar2'] == 'FOO BAR 2' |
854 | 863 |
assert not resp.json[0].get('user') |
855 | 864 | |
865 |
# get a single formdata |
|
866 |
resp = get_url('/api/forms/test/%s/' % formdata.id) |
|
867 |
assert 'user' not in resp.json |
|
868 | ||
869 |
if http_basic_auth: |
|
870 |
# for basic HTTP authentication, check there's no access if roles are not given. |
|
871 |
access.roles = [] |
|
872 |
access.store() |
|
873 | ||
874 |
get_url('/api/forms/test/list?full=on', status=403) |
|
875 |
get_url('/api/forms/test/%s/' % formdata.id, status=403) |
|
876 | ||
856 | 877 | |
857 | 878 |
def test_api_geojson_formdata(pub, local_user): |
858 | 879 |
pub.role_class.wipe() |
wcs/api.py | ||
---|---|---|
189 | 189 |
raise TraversalError() |
190 | 190 | |
191 | 191 |
def check_access(self, api_name=None): |
192 |
if get_request().has_anonymised_data_api_restriction(): |
|
193 |
if not is_url_signed() or (get_request().user and get_request().user.is_admin): |
|
194 |
raise AccessForbiddenError('user not authenticated') |
|
195 |
else: |
|
196 |
if get_request().user and get_request().user.is_admin: |
|
197 |
return # grant access to admins, to ease debug |
|
198 |
api_user = get_user_from_api_query_string(api_name=api_name) |
|
199 |
if not api_user: |
|
200 |
raise AccessForbiddenError('user not authenticated') |
|
201 |
if not self.formdef.is_of_concern_for_user(api_user): |
|
202 |
raise AccessForbiddenError('unsufficient roles') |
|
192 |
if get_request().user and get_request().user.is_admin: |
|
193 |
return # grant access to admins, to ease debug |
|
194 | ||
195 |
api_user = get_user_from_api_query_string(api_name=api_name) |
|
196 | ||
197 |
if get_request().has_anonymised_data_api_restriction() and is_url_signed(): |
|
198 |
# when requesting anonymous data, a signature is enough |
|
199 |
return |
|
200 | ||
201 |
if not api_user: |
|
202 |
raise AccessForbiddenError('user not authenticated') |
|
203 |
if not self.formdef.is_of_concern_for_user(api_user): |
|
204 |
raise AccessForbiddenError('unsufficient roles') |
|
203 | 205 | |
204 | 206 |
def _q_lookup(self, component): |
205 | 207 |
if component == 'ics': |
wcs/api_access.py | ||
---|---|---|
89 | 89 |
is_api_user = True |
90 | 90 |
anonymous = False |
91 | 91 | |
92 |
def __init__(self, api_access): |
|
93 |
self.api_access = api_access |
|
94 | ||
92 | 95 |
def can_go_in_admin(self): |
93 | 96 |
return False |
94 | 97 | |
... | ... | |
98 | 101 |
def get_roles(self): |
99 | 102 |
return self.roles |
100 | 103 | |
101 |
user = RestrictedApiUser() |
|
104 |
user = RestrictedApiUser(self)
|
|
102 | 105 |
user.roles = [x.id for x in self.get_roles()] |
103 | 106 |
return user |
104 | 107 |
wcs/forms/common.py | ||
---|---|---|
158 | 158 |
session = get_session() |
159 | 159 |
mine = False |
160 | 160 |
if api_call: |
161 |
if get_request().has_anonymised_data_api_restriction(): |
|
161 |
user = get_user_from_api_query_string() or get_request().user |
|
162 |
if get_request().has_anonymised_data_api_restriction() and (not user or not user.is_api_user): |
|
162 | 163 |
if is_url_signed() or (get_request().user and get_request().user.is_admin): |
163 | 164 |
return None |
164 | 165 |
else: |
165 | 166 |
raise errors.AccessUnauthorizedError() |
166 |
else: |
|
167 |
user = get_user_from_api_query_string() or get_request().user |
|
168 | 167 |
else: |
169 | 168 |
user = get_request().user |
170 | 169 |
if user and not user.anonymous: |
wcs/qommon/http_request.py | ||
---|---|---|
223 | 223 | |
224 | 224 |
if 'anonymise' in self.form: |
225 | 225 |
return True |
226 | ||
226 | 227 |
orig = self.form.get('orig') |
227 | 228 |
if orig: |
228 | 229 |
api_access = ApiAccess.get_by_identifier(orig) |
229 | 230 |
if api_access: |
230 | 231 |
return api_access.restrict_to_anonymised_data |
232 | ||
233 |
if self.user and self.user.is_api_user: |
|
234 |
return self.user.api_access.restrict_to_anonymised_data |
|
235 | ||
231 | 236 |
return False |
232 | 237 | |
233 | 238 |
@property |
234 |
- |