View | Details | Raw Unified | Return to bug 39190
Collapse All | Expand All

(-)a/Koha/File/Transport.pm (-4 / +3 lines)
Lines 17-26 package Koha::File::Transport; Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
use constant {
19
use constant {
20
    DEFAULT_TIMEOUT      => 10,
20
    DEFAULT_TIMEOUT   => 10,
21
    TEST_FILE_NAME       => '.koha_test_file',
21
    TEST_FILE_NAME    => '.koha_test_file',
22
    TEST_FILE_CONTENT    => "Hello, world!\n",
22
    TEST_FILE_CONTENT => "Hello, world!\n",
23
    KEY_FILE_PERMISSIONS => '0600',
24
};
23
};
25
24
26
use Koha::Database;
25
use Koha::Database;
(-)a/Koha/File/Transport/SFTP.pm (+132 lines)
Lines 19-24 use Modern::Perl; Link Here
19
19
20
use Koha::Logger;
20
use Koha::Logger;
21
21
22
use File::Spec;
23
use IO::File;
22
use Net::SFTP::Foreign;
24
use Net::SFTP::Foreign;
23
use Try::Tiny;
25
use Try::Tiny;
24
26
Lines 28-33 use base qw(Koha::File::Transport); Link Here
28
30
29
Koha::File::Transport::SFTP - SFTP implementation of file transport
31
Koha::File::Transport::SFTP - SFTP implementation of file transport
30
32
33
=head2 Class methods
34
35
=head3 store
36
37
    $server->store;
38
39
Overloaded store method that ensures key_file also gets written to the filesystem.
40
41
=cut
42
43
sub store {
44
    my ($self) = @_;
45
46
    $self->SUPER::store;
47
    $self->discard_changes;
48
    $self->_write_key_file;
49
50
    return $self;
51
}
52
53
=head3 connect
54
55
    my $success = $self->connect;
56
57
Start the SFTP transport connect, returns true on success or undefined on failure.
58
31
=cut
59
=cut
32
60
33
sub connect {
61
sub connect {
Lines 35-42 sub connect { Link Here
35
63
36
    $self->{connection} = Net::SFTP::Foreign->new(
64
    $self->{connection} = Net::SFTP::Foreign->new(
37
        host     => $self->host,
65
        host     => $self->host,
66
        port     => $self->port,
38
        user     => $self->user_name,
67
        user     => $self->user_name,
39
        password => $self->plain_text_password,
68
        password => $self->plain_text_password,
69
        key_path => $self->_locate_key_file,
40
        timeout  => $self->DEFAULT_TIMEOUT,
70
        timeout  => $self->DEFAULT_TIMEOUT,
41
        more     => [qw(-o StrictHostKeyChecking=no)],
71
        more     => [qw(-o StrictHostKeyChecking=no)],
42
    );
72
    );
Lines 55-60 sub connect { Link Here
55
    return 1;
85
    return 1;
56
}
86
}
57
87
88
=head3 upload_file
89
90
    my $success =  $transport->upload_file($fh);
91
92
Passed a filehandle, this will upload the file to the current directory of the server connection.
93
94
Returns true on success or undefined on failure.
95
96
=cut
97
58
sub upload_file {
98
sub upload_file {
59
    my ( $self, $local_file, $remote_file ) = @_;
99
    my ( $self, $local_file, $remote_file ) = @_;
60
100
Lines 73-78 sub upload_file { Link Here
73
    return 1;
113
    return 1;
74
}
114
}
75
115
116
=head3 download_file
117
118
    my $success =  $transport->download_file($filename);
119
120
Passed a filename, this will download the file from the current directory of the server connection.
121
122
Returns true on success or undefined on failure.
123
124
=cut
125
76
sub download_file {
126
sub download_file {
77
    my ( $self, $remote_file, $local_file ) = @_;
127
    my ( $self, $remote_file, $local_file ) = @_;
78
128
Lines 89-94 sub download_file { Link Here
89
    return 1;
139
    return 1;
90
}
140
}
91
141
142
=head3 change_directory
143
144
    my $success = $server->change_directory($directory);
145
146
Passed a directory name, this will change the current directory of the server connection.
147
148
Returns true on success or undefined on failure.
149
150
=cut
151
92
sub change_directory {
152
sub change_directory {
93
    my ( $self, $remote_directory ) = @_;
153
    my ( $self, $remote_directory ) = @_;
94
154
Lines 105-110 sub change_directory { Link Here
105
    return 1;
165
    return 1;
106
}
166
}
107
167
168
=head3 list_files
169
170
    my @files = $server->list_files;
171
172
Returns an array of filenames found in the current directory of the server connection.
173
174
=cut
175
108
sub list_files {
176
sub list_files {
109
    my ($self) = @_;
177
    my ($self) = @_;
110
178
Lines 121-126 sub list_files { Link Here
121
    return $file_list;
189
    return $file_list;
122
}
190
}
123
191
192
=head2 Internal methods
193
194
=head3 _write_key_file
195
196
    my $success = $server->_write_key_file;
197
198
Writes the keyfile from the db into a file.
199
200
Returns 1 on success, undef on failure.
201
202
=cut
203
204
sub _write_key_file {
205
    my ($self) = @_;
206
207
    my $upload_path = C4::Context->config('upload_path') or return;
208
    my $logger      = Koha::Logger->get;
209
    my $key_path    = File::Spec->catdir( $upload_path, 'ssh_keys' );
210
    my $key_file    = File::Spec->catfile( $key_path, 'id_ssh_' . $self->id );
211
212
    mkdir $key_path unless -d $key_path;
213
    unlink $key_file if -f $key_file;
214
215
    my $fh = IO::File->new( $key_file, 'w' ) or return;
216
217
    try {
218
        chmod 0600, $key_file if -f $key_file;
219
        print $fh $self->plain_text_key;
220
        close $fh or $logger->warn("Failed to close key file: $!");
221
        return 1;
222
    } catch {
223
        $logger->warn("Error writing key file: $_");
224
        close $fh;
225
        return;
226
    };
227
}
228
229
=head3 _locate_key_file
230
231
    my $path = $server->_locate_key_file;
232
233
Returns the keyfile's path if it exists, undef otherwise.
234
235
=cut
236
237
sub _locate_key_file {
238
    my ($self) = @_;
239
240
    my $upload_path = C4::Context->config('upload_path') or return;
241
    my $key_file    = File::Spec->catfile(
242
        $upload_path,
243
        'ssh_keys',
244
        'id_ssh_' . $self->id
245
    );
246
247
    return ( -f $key_file ) ? $key_file : undef;
248
}
249
250
=head3 _abort_operation
251
252
Helper method to abort the current operation and return.
253
254
=cut
255
124
sub _abort_operation {
256
sub _abort_operation {
125
    my ($self) = @_;
257
    my ($self) = @_;
126
258
(-)a/t/db_dependent/Koha/File/Transport/SFTP.t (-2 / +61 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 5;
20
use Test::More tests => 7;
21
use Test::Exception;
21
use Test::Exception;
22
use Test::Warn;
22
use Test::Warn;
23
23
Lines 29-34 use t::lib::Mocks; Link Here
29
my $schema  = Koha::Database->new->schema;
29
my $schema  = Koha::Database->new->schema;
30
my $builder = t::lib::TestBuilder->new;
30
my $builder = t::lib::TestBuilder->new;
31
31
32
subtest 'store() and _post_store_trigger() tests' => sub {
33
    plan tests => 2;
34
35
    my $transport = $builder->build_object(
36
        {
37
            class => 'Koha::File::Transports',
38
            value => { transport => 'sftp', password => 'testpass' }
39
        }
40
    );
41
42
    my $post_store_called = 0;
43
    no warnings 'redefine';
44
    local *Koha::File::Transport::SFTP::_post_store_trigger = sub {
45
        $post_store_called = 1;
46
    };
47
48
    lives_ok { $transport->store } 'store() should complete without error';
49
    is( $post_store_called, 1, '_post_store_trigger() should be called' );
50
};
51
52
subtest '_write_key_file() tests' => sub {
53
54
    plan tests => 3;
55
56
    $schema->storage->txn_begin;
57
58
    my $transport = $builder->build_object(
59
        {
60
            class => 'Koha::File::Transports',
61
            value => {
62
                transport => 'sftp',
63
                password  => undef,
64
                key_file  => undef,
65
            }
66
        }
67
    );
68
    $transport->set( { key_file => '321test' } )->store();
69
    $transport->discard_changes;
70
71
    my $path = '/tmp/kohadev_test';
72
    t::lib::Mocks::mock_config( 'upload_path', $path );
73
    mkdir $path if !-d $path;
74
75
    my $first_test = $transport->_write_key_file;
76
77
    my $file        = $transport->_locate_key_file;
78
    my $second_test = ( -f $file );
79
80
    open( my $fh, '<', $transport->_locate_key_file );
81
    my $third_test = <$fh>;
82
83
    is( $first_test,  1,           'Writing key file should return 1' );
84
    is( $second_test, 1,           'Written key file should exist' );
85
    is( $third_test,  "321test\n", 'The contents of the key file should be 321test\n' );
86
87
    unlink $file;
88
89
    $schema->storage->txn_rollback;
90
};
91
32
subtest 'connect() tests' => sub {
92
subtest 'connect() tests' => sub {
33
    plan tests => 2;
93
    plan tests => 2;
34
94
35
- 

Return to bug 39190