# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2022  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import json

import pytest
from django.core.files.base import ContentFile
from webtest import Upload

pytestmark = pytest.mark.django_db


def login(app, username='admin', password='admin'):
    login_page = app.get('/login/')
    login_form = login_page.forms[0]
    login_form['username'] = username
    login_form['password'] = password
    resp = login_form.submit()
    assert resp.status_int == 302
    return app


@pytest.fixture
def app(app, admin_user):
    login(app)
    return app


def test_add(app, db, cert_content, key_content, resource_class):
    response = app.get('/manage/ldap/add')
    assert 'this option is actually not supported' in response.text
    response.form.set('slug', 'resource')
    response.form.set('title', 'resource')
    response.form.set('description', 'resource')
    response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
    response.form.set('ldap_bind_dn', 'uid=user,o=orga')
    response.form.set('ldap_bind_password', 'password')
    response.form.set('ldap_tls_cert', Upload('cert.pem', cert_content, 'application/octet-stream'))
    response.form.set('ldap_tls_key', Upload('key.pem', key_content, 'application/octet-stream'))
    response = response.form.submit(status=302)
    assert resource_class.objects.count() == 1
    resource = resource_class.objects.get()
    assert resource.ldap_url == 'ldap://localhost.entrouvert.org'
    assert resource.ldap_bind_dn == 'uid=user,o=orga'
    assert resource.ldap_bind_password == 'password'
    with resource.ldap_tls_cert as fd:
        assert fd.read() == cert_content
    with resource.ldap_tls_key as fd:
        assert fd.read() == key_content


def test_missing_bind_password(app, db, cert_content, key_content, resource_class):
    response = app.get('/manage/ldap/add')
    response.form.set('slug', 'resource')
    response.form.set('title', 'resource')
    response.form.set('description', 'resource')
    response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
    response.form.set('ldap_bind_dn', 'uid=user,o=orga')
    response = response.form.submit(status=200)


def test_missing_bind_dn(app, db, cert_content, key_content, resource_class):
    response = app.get('/manage/ldap/add')
    response.form.set('slug', 'resource')
    response.form.set('title', 'resource')
    response.form.set('description', 'resource')
    response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
    response.form.set('ldap_bind_password', 'password')
    response = response.form.submit(status=200)


def test_missing_tls_key(app, db, cert_content, key_content, resource_class):
    response = app.get('/manage/ldap/add')
    response.form.set('slug', 'resource')
    response.form.set('title', 'resource')
    response.form.set('description', 'resource')
    response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
    response.form.set('ldap_tls_cert', Upload('cert.pem', cert_content, 'application/octet-stream'))
    response = response.form.submit(status=200)


def test_missing_tls_cert(app, db, cert_content, key_content, resource_class):
    response = app.get('/manage/ldap/add')
    response.form.set('slug', 'resource')
    response.form.set('title', 'resource')
    response.form.set('description', 'resource')
    response.form.set('ldap_url', 'ldap://localhost.entrouvert.org')
    response.form.set('ldap_tls_key', Upload('key.pem', key_content, 'application/octet-stream'))
    response = response.form.submit(status=200)


def test_python_ldap_32(app, db):
    response = app.get('/manage/ldap/add')
    assert 'Warning: this option is actually not supported (python-ldap < 3.4)' in response.text


EXPORT_JSON = {
    'resources': [
        {
            '@type': 'passerelle-resource',
            'access_rights': [{'apiuser': 'all', 'codename': 'can_access'}],
            'description': 'resource',
            'ldap_bind_dn': None,
            'ldap_bind_password': None,
            'ldap_tls_cert': {
                'name': 'cert.pem',
                'content': 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCakNDQWU2Z0F3SUJBZ0lVVEtvcFQ3NkNGbHNWY0k3RkFpbGFZTElMejBvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RWhNQjhHQTFVRUF3d1liRzlqWVd4b2IzTjBMbVZ1ZEhKdmRYWmxjblF1YjNKbk1CNFhEVEU0TVRJdwpOVEUyTlRreU5Gb1hEVEk0TVRJd01qRTJOVGt5TkZvd0l6RWhNQjhHQTFVRUF3d1liRzlqWVd4b2IzTjBMbVZ1CmRISnZkWFpsY25RdWIzSm5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTR4c0wKbjI1eWl0dGJqazViY0t2WTJJOHpQaXZMNllXbjJNSmltYVFRU056Q3cvOFBPbVZQTG1NSWIzbGNaanlkRlJhZAorUlR4WmZudXZDQ0pybkdyRzdoT3NKTmVuVExMVTB1Z04veVExODY5Y00wN2E5dGpTekw3TkN6OUgxTklLMStRCmNCc1RFeGM3N2RPV3B3V0k5VGpxWVlSTCt6ZXgzbWw4Y2RxY1E3QlFVUXhBdkE0VVU2M0RNMkcrNU8zZEU3bDgKdXZ5QlVVM2tXL3NoSHloZndlV05YTzhJWFhJanZEZlBZa09zamM2ZW4ya0ZNcitzRU5TVUtnZkRLanovVXpxeQpTN0xCYjR0a0pBTFpNOFFQNTZWZVFBRzFKWkYySjIveTFScUJmSUdSSUVrWW9hSGNqNlVBVFphMXhjWmpNdWJMCnozb3RSTlljUlhLSk1ZV0diUUlEQVFBQm96SXdNREFKQmdOVkhSTUVBakFBTUNNR0ExVWRFUVFjTUJxQ0dHeHYKWTJGc2FHOXpkQzVsYm5SeWIzVjJaWEowTG05eVp6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGVlBhdkJhaAptSWpnblRqcTZaYkZ4WFROSlcwVHJxTjhvbGJLSjZTZndXVmswSThweDdQT2VrRmFYZCtlZ3NGSmxXWXlIOXE0CkhrS290ZGRSWVlyV29YY1Bpb2ROZlVhK2JSbmgyV1lsMnJFR01XNWRiQmYvTVlDRHRzNjhjM1NvQTdKSVlKOHcKMFFaR0FraWpLTnRWTUwwL0ZyTHVKV2JmRkJBV0g4SkI0NkJjQWcvOGZsYk1IQVVMelYzRjFnL3YwQTNGRzNZLwo5ZlZyK2xONXFzK05COU5YSU1kZjV3WHJtSlFZUmpvdHlPalVPNnlURnFERnZxRTdERXBLUUQ1aG52cUpvWEN6CnpZUVMxRGpIMXFTUmM1dkM4STdZbEpvd0Nmbkk5TXNFSUNTcnNrNzVEaFQwOTFhSkMyWFg5M280emhmTnhtTzUKS2oyOGhQODdHSGdOSWc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==',  # pylint: disable=line-too-long
            },
            'ldap_tls_key': {
                'name': 'key.pem',
                'content': 'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRRGpHd3VmYm5LSzIxdU8KVGx0d3E5allqek0rSzh2cGhhZll3bUtacEJCSTNNTEQvdzg2WlU4dVl3aHZlVnhtUEowVkZwMzVGUEZsK2U2OApJSW11Y2FzYnVFNndrMTZkTXN0VFM2QTMvSkRYenIxd3pUdHIyMk5MTXZzMExQMGZVMGdyWDVCd0d4TVRGenZ0CjA1YW5CWWoxT09waGhFdjdON0hlYVh4eDJweERzRkJSREVDOERoUlRyY016WWI3azdkMFR1WHk2L0lGUlRlUmIKK3lFZktGL0I1WTFjN3doZGNpTzhOODlpUTZ5TnpwNmZhUVV5djZ3UTFKUXFCOE1xUFA5VE9ySkxzc0Z2aTJRawpBdGt6eEEvbnBWNUFBYlVsa1hZbmIvTFZHb0Y4Z1pFZ1NSaWhvZHlQcFFCTmxyWEZ4bU15NXN2UGVpMUUxaHhGCmNva3hoWVp0QWdNQkFBRUNnZ0VBT1VaSTJCeHlwckpMbE1nT0o0d3ZVKzVKYmhSOWlKYzhqVjM0bitiUWRJKzQKVHRXMGNYVzdVbWVIYVJXaVIrWmhkMEFNOXhSaERPYkxYb2FXTW5oWVB0VnNndnVua04yT2lhTTQ5T1d0WWIreAo1eERiTzRoSXNsNVpHLzk4bHJuYUtaWWdSeVdNMmZPeUdYaVROZXdmYmppOFkzdUo3Z0ZOeWxtd0dNYVpRamhyCllOYXFORVY3VnMybjdvRVJ4cXpLRzk5NDdvQkF4MmhwbW9hVzZlTXlYY1dsMm92N2lIcEpTS1VCS2hvKzVQV2MKSjczMW5vME9zR3VTKzNqSGEvMG5aWHJUOG5LbWVteURNZFNmV210VHY2NTlML2d1RkluWnBIUGZGVkxmNTZ2YwpKNnpiL0l6RUpWK05oN0NmQnNNYkhsVFlCZVVGbFJXc3k5dDcwK09ad1FLQmdRRDNKNGFWTjR2SmhYWDF6RGdMCmRWQWN6d0xHS1hZMzhCb0JqT2VSdFZoWEhzNXAvZU5JcWVaMlliWXdCQnkzbkw0MTRVbjdncWI5ZkR0ZzBpM24KNW1RSU9XaHZwSVlVeHR3SVBnWXd6dW14eHAvbjdYZFU0QlBEYnhlalp4a3VDN0FSNWJCMzRwd0pBSnZXUkdFZgowWDFUeEpscVVMaGlaNmcxOE8zUzBvaUp0d0tCZ1FEck85Uk9hajZra3hqWUhtbGpCWklYWGhkS0RjbjBBcVBpCncyMEFhYWZ4MG94TlFBb3E4R3R1MjJaMVFId1JkQmVVSndxQ2JtSFZDQ3diTWYvNTY4ekZBQU51VDliS01lNlgKSjBwMG5URGl5bjh3OU1mZHVGdUc0Y1VNbjRvSzZkSXVZbHNjZ3VvUFFDdlFkY2l3RytkanF3VHJIaWI1VEVibQpqZUtFa1kyQSt3S0JnUUR2WHQrd3kyQmVxQnpNRjZNOExiMk9lVXdWZ25pVnlyeFZQaFBWZ2s1eDZrcytTb0FECmsxRzYyLzNvMlVLNjdsc21zZkRHWUE2OXVNR0ZqMnFZakFIY0dVVzF3eUY5SS9CZEp6MDFybUNXSm1vZTVWWEsKNVU4ZTNBeUgzTVY5WENLRjR2Q2IyK1VGcndvL1puQ3VzV1Z4YVJxdzVrYitQNmlodlp1SXNSRStWd0tCZ1FDNwoyZHVCZzNiakZsVVF3YmlIU3p1UFRhUnJqdmRuMVhQcTh3Vm8vdmNQTm9TMGJCK3lpcXhBcXhUM0xiZm1lRDhjCklORlR0N0tJM1MzYnllSVJReTBUWlI5WVNJbk9qbkZxWkFZaGVpWS85bFg4VW40Sm9kLzFwdllsVG9KK2xKczAKVDNkVEhYaXRGU0hvSnlkTSsvdWNyRVlSUE5NQzR0Yjc1dkt0eTA2bFlRS0JnUUN4NDkrZzVrUWFhUlorNHBzdworZW9sTXBBd0tEa3BLNWdZZW42T3NyVDhtNGhweFRtdGl0ZU1zSDVBdmIvZnhxb0pXTE9qaE40RW5FWlRNSnpyCkx5R29Lc1R2N3JoWndoUnpuRTE1ck96eG1sZFdyY0NrbDdER3VNMkdjS2dndWhDWUY3VTdLQSt2VUNlcUNFMEgKTEEyZ3JrWStUeEZwZzFwd1lkRjFoZWttVHc9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==',  # pylint: disable=line-too-long
            },
            'ldap_tls_cacert': None,
            'ldap_tls_check_hostname': True,
            'ldap_tls_check_cert': True,
            'ldap_url': 'ldap://localhost.entrouvert.org:52271',
            'log_level': 'INFO',
            'resource_type': 'ldap.resource',
            'slug': 'resource',
            'title': 'resource',
        }
    ],
}


class TestImportExport:
    @pytest.fixture
    def resource_params(self, resource_params, cert_content, key_content):
        return {
            **resource_params,
            'ldap_url': 'ldap://localhost.entrouvert.org:52271',
            'ldap_tls_cert': ContentFile(cert_content, name='cert.pem'),
            'ldap_tls_key': ContentFile(key_content, name='key.pem'),
        }

    def test_import(self, app, resource_class, resource_params):
        assert not resource_class.objects.count()
        response = app.get('/manage/')
        response = response.click('Import')
        response.form.set('site_json', Upload('ldap.json', json.dumps(EXPORT_JSON).encode()))
        response.form.set('import_users', False)
        response = response.form.submit(status=302)
        instance = resource_class.objects.get()

        for key, value in resource_params.items():
            instance_value = getattr(instance, key)
            if isinstance(value, ContentFile):
                with instance_value as fd1:
                    with value as fd2:
                        assert fd1.read() == fd2.read()
            else:
                assert instance_value == value

    def test_export(self, app, resource, cert_content, key_content):
        response = app.get('/ldap/resource/')
        response = response.click('Export')
        content = response.json
        for r in content['resources']:
            if r.get('ldap_tls_cert'):
                r['ldap_tls_cert']['name'] = 'cert.pem'
            if r.get('ldap_tls_key'):
                r['ldap_tls_key']['name'] = 'key.pem'
        assert content == EXPORT_JSON
