import pytest from django.contrib.contenttypes.models import ContentType from django.urls import reverse from passerelle.apps.oxyd.models import OxydSMSGateway from passerelle.base import signature from passerelle.base.models import AccessRight, ApiUser pytestmark = pytest.mark.django_db @pytest.fixture def oxyd(db): return OxydSMSGateway.objects.create( title='eservices', slug='eservices', username='user', description='oxyd', password='secret' ) def test_anonymous_access(app, oxyd): endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url, params={}, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' api = ApiUser.objects.create( username='public', fullname='public', description='access for all', keytype='', key='' ) obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) resp = app.post_json(endpoint_url, params={}, status=400) # for empty payload the connector returns an APIError with # {"err_desc": "'message' is a required property"} assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'message' is a required property" def test_access_with_signature(app, oxyd): api = ApiUser.objects.create( username='eservices', fullname='Eservices User', description='eservices', keytype='SIGN', key='12345' ) obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) url = signature.sign_url(endpoint_url + '?orig=eservices', '12345') # for empty payload the connector returns an APIError with # {"err_desc": "'message' is a required property"} resp = app.post_json(url, params={}, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'message' is a required property" # bad key url = signature.sign_url(endpoint_url + '?orig=eservices', 'notmykey') resp = app.post_json(url, params={}, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' # add garbage after signature url = signature.sign_url(endpoint_url + '?orig=eservices', '12345') url = '%s&foo=bar' % url resp = app.post_json(url, params={}, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' # trusted user (from settings.KNOWN_SERVICES) url = signature.sign_url(endpoint_url + '?orig=wcs1', 'abcde') resp = app.post_json(url, params={}, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'message' is a required property" # bad key url = signature.sign_url(endpoint_url + '?orig=wcs1', 'notmykey') resp = app.post_json(url, params={}, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' def test_access_http_auth(app, oxyd): username = 'apiuser' password = '12345' api = ApiUser.objects.create( username=username, fullname='Api User', description='api', keytype='SIGN', key=password ) obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) app.authorization = ('Basic', (username, password)) endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url, params={}, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'message' is a required property" def test_access_apikey(app, oxyd): password = 'apiuser_12345' api = ApiUser.objects.create( username='apiuser', fullname='Api User', description='api', keytype='API', key=password ) obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) params = {'message': 'test'} endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url + '?apikey=' + password, params=params, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'from' is a required property" resp = app.post_json(endpoint_url + '?apikey=' + password[:3], params=params, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' def test_access_apiuser_with_no_key(app, oxyd): api = ApiUser.objects.create(username='apiuser', fullname='Api User', description='api') obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) params = {'message': 'test', 'from': 'test api'} endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url, params=params, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'to' is a required property" def test_access_apiuser_with_ip_restriction(app, oxyd): authorized_ip = '176.31.123.109' api = ApiUser.objects.create( username='apiuser', fullname='Api User', description='api', ipsource=authorized_ip ) obj_type = ContentType.objects.get_for_model(OxydSMSGateway) AccessRight.objects.create( codename='can_send_messages', apiuser=api, resource_type=obj_type, resource_pk=oxyd.pk, ) endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url, params={}, extra_environ={'REMOTE_ADDR': '127.0.0.1'}, status=403) assert resp.json['err'] == 1 assert resp.json['err_class'] == 'django.core.exceptions.PermissionDenied' endpoint_url = reverse( 'generic-endpoint', kwargs={'connector': 'oxyd', 'slug': oxyd.slug, 'endpoint': 'send'} ) resp = app.post_json(endpoint_url, params={}, extra_environ={'REMOTE_ADDR': authorized_ip}, status=400) assert resp.json['err'] == 1 assert resp.json['err_desc'] == "'message' is a required property"