# passerelle - uniform access to multiple data sources and services # Copyright (C) 2019 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 . import os import pytest from django.core.files.uploadedfile import SimpleUploadedFile from django.db import models from django.utils.encoding import force_str from passerelle.utils.sftp import SFTP, SFTPField, SFTPFormField @pytest.fixture def ssh_key(): with open(os.path.join(os.path.dirname(__file__), 'ssh_key'), 'rb') as fd: yield fd.read() @pytest.fixture def ssh_key_with_password(): with open(os.path.join(os.path.dirname(__file__), 'ssh_key_with_password'), 'rb') as fd: yield fd.read() def test_http_url(sftpserver): with pytest.raises(ValueError): SFTP('https://coin.org/') def test_missing_hostname(sftpserver): with pytest.raises(ValueError): SFTP('sftp://a:x@/hop/') def test_sftp_ok(sftpserver): with sftpserver.serve_content({'DILA': {'a.zip': 'a'}}): with SFTP( 'sftp://john:doe@{server.host}:{server.port}/DILA/'.format(server=sftpserver) ).client() as sftp: assert sftp.listdir() == ['a.zip'] def test_sftp_bad_paths(sftpserver): with sftpserver.serve_content({'DILA': {'a.zip': 'a'}}): with SFTP( 'sftp://john:doe@{server.host}:{server.port}/DILA/'.format(server=sftpserver) ).client() as sftp: with pytest.raises(ValueError): sftp.chdir('..') with pytest.raises(ValueError): sftp.chdir('/') with pytest.raises(ValueError): sftp.chdir('/coin') def test_form_field(sftpserver, ssh_key, ssh_key_with_password): from django import forms class Form(forms.Form): sftp = SFTPFormField(label='sftp') with sftpserver.serve_content({'DILA': {'a.zip': 'a'}}): url = 'sftp://john:doe@{server.host}:{server.port}/DILA/'.format(server=sftpserver) form = Form(data={'sftp_0': 'http://coin.org'}) assert not form.is_valid() assert 'Enter a valid URL.' in str(form.errors) form = Form(data={'sftp_0': url}) assert form.is_valid() sftp = form.cleaned_data['sftp'] assert isinstance(sftp, SFTP) assert sftp.url == url assert sftp.username == 'john' assert sftp.password == 'doe' assert sftp.hostname == sftpserver.host assert sftp.port == sftpserver.port assert sftp.path == 'DILA' assert not sftp.private_key with form.cleaned_data['sftp'].client() as sftp: assert sftp.listdir() == ['a.zip'] form = Form(data={'sftp_0': url, 'sftp_2': force_str(ssh_key, 'ascii')}) assert form.is_valid() sftp = form.cleaned_data['sftp'] assert isinstance(sftp, SFTP) assert sftp.url == url assert sftp.username == 'john' assert sftp.password == 'doe' assert sftp.hostname == sftpserver.host assert sftp.port == sftpserver.port assert sftp.path == 'DILA' assert sftp.private_key with form.cleaned_data['sftp'].client() as sftp: assert sftp.listdir() == ['a.zip'] form = Form( data={'sftp_0': url}, files={'sftp_1': SimpleUploadedFile('ssh_key', ssh_key, 'application/octet-stream')}, ) assert form.is_valid() sftp = form.cleaned_data['sftp'] assert isinstance(sftp, SFTP) assert sftp.url == url assert sftp.username == 'john' assert sftp.password == 'doe' assert sftp.hostname == sftpserver.host assert sftp.port == sftpserver.port assert sftp.path == 'DILA' assert sftp.private_key with form.cleaned_data['sftp'].client() as sftp: assert sftp.listdir() == ['a.zip'] form = Form(data={'sftp_0': url, 'sftp_2': force_str(ssh_key_with_password, 'ascii')}) assert not form.is_valid() assert 'key invalid' in str(form.errors) form = Form( data={ 'sftp_0': url, 'sftp_2': force_str(ssh_key_with_password, 'ascii'), 'sftp_3': 'coucou', } ) assert form.is_valid() with form.cleaned_data['sftp'].client() as sftp: assert sftp.listdir() == ['a.zip'] @pytest.fixture def temp_model(db): from django.db import connection class Model(models.Model): sftp = SFTPField(blank=True) class Meta: app_label = 'test' with connection.schema_editor() as editor: editor.create_model(Model) yield Model editor.delete_model(Model) def test_model_field(temp_model, ssh_key_with_password): instance = temp_model.objects.create() assert instance.sftp is None url = 'sftp://john:doe@example.com:45/a/b' sftp = SFTP(url=url, private_key_content=ssh_key_with_password, private_key_password='coucou') instance.sftp = sftp instance.save() instance = temp_model.objects.get() assert instance.sftp is not None assert instance.sftp.url == url assert instance.sftp.private_key is not None instance.sftp = None instance.save() instance = temp_model.objects.get() assert instance.sftp is None instance.delete() temp_model.objects.create(sftp=sftp) instance = temp_model.objects.get() assert instance.sftp is not None assert instance.sftp.url == url assert instance.sftp.private_key is not None