Revision cd303dbe
Von Jan Büren vor mehr als 1 Jahr hinzugefügt
SL/BackgroundJob/SyncWebDAV.pm | ||
---|---|---|
1 |
package SL::BackgroundJob::SyncWebDAV; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use warnings; |
|
5 |
|
|
6 |
use parent qw(SL::BackgroundJob::Base); |
|
7 |
|
|
8 |
use SL::DB::BackgroundJobHistory; |
|
9 |
use HTTP::DAV; |
|
10 |
use File::Find; |
|
11 |
use Cwd; |
|
12 |
use Data::Dumper; |
|
13 |
|
|
14 |
sub create_job { |
|
15 |
$_[0]->create_standard_job('0 3 * * *'); # daily at 3:00 am |
|
16 |
} |
|
17 |
|
|
18 |
sub run { |
|
19 |
my $self = shift; |
|
20 |
my $db_obj = shift; |
|
21 |
|
|
22 |
my $options = $db_obj->data_as_hash; |
|
23 |
my $DELETE_ONLY = 0 || $options->{delete}; |
|
24 |
|
|
25 |
return unless $::instance_conf->get_webdav_sync_extern; |
|
26 |
|
|
27 |
my $ret; |
|
28 |
|
|
29 |
my $dav = HTTP::DAV->new(); |
|
30 |
my $url = $::instance_conf->get_webdav_sync_extern_url; |
|
31 |
$url =~ s|/\z||; # no trailing slashes |
|
32 |
|
|
33 |
$dav->credentials( |
|
34 |
-user => $::instance_conf->get_webdav_sync_extern_login, |
|
35 |
-pass => $::instance_conf->get_webdav_sync_extern_pass, |
|
36 |
-url => $url, |
|
37 |
); |
|
38 |
my $client_id = $options->{client_id} || $::auth->get_session_value('client_id'); |
|
39 |
my $cwd = getcwd(); |
|
40 |
|
|
41 |
my @fails; |
|
42 |
|
|
43 |
eval { |
|
44 |
|
|
45 |
my (@webdav_dir_temp, @webdav_dir, @webdav_files); |
|
46 |
|
|
47 |
# chdir to client root |
|
48 |
my $webdav = $cwd. "/webdav/$client_id/"; |
|
49 |
chdir($webdav) or die "couldn't change into webdav dir"; # TODO throw better error message (Permission denied, etc) |
|
50 |
|
|
51 |
find( { wanted => sub { push @webdav_dir_temp, -d && $_}, no_chdir => 1 }, '.'); |
|
52 |
find( { wanted => sub { push @webdav_files, -f && $_}, no_chdir => 1 }, '.'); |
|
53 |
|
|
54 |
shift @webdav_dir_temp; # first element would be undef after substr |
|
55 |
foreach (@webdav_dir_temp) { |
|
56 |
next unless $_; |
|
57 |
push @webdav_dir, substr($_,2); |
|
58 |
} |
|
59 |
@webdav_files = map { substr($_,2) } grep { $_ =~ m/.*pdf/ } @webdav_files; |
|
60 |
|
|
61 |
$ret = $dav->open(-url => $url) or die "Can't open url $url"; |
|
62 |
# Make a null lock on repo for 5minutes |
|
63 |
#$ret = $dav->lock(-url => $url, -timeout => "30m") or die; |
|
64 |
|
|
65 |
foreach (@webdav_dir) { |
|
66 |
last if $DELETE_ONLY; |
|
67 |
|
|
68 |
$ret = $dav->options(-url => $url . '/' . $_); |
|
69 |
next unless $ret =~ m/MKCOL/; |
|
70 |
|
|
71 |
unless ( $dav->mkcol($_) ) { |
|
72 |
push(@fails, "Cannot make dir $_"); |
|
73 |
}; |
|
74 |
} |
|
75 |
|
|
76 |
#$dav->unlock(-url => $url); # UNLOCK after DIR sync |
|
77 |
# now we have all dirs in sync, therefore we can place files |
|
78 |
foreach (@webdav_files) { |
|
79 |
last if $DELETE_ONLY; |
|
80 |
|
|
81 |
$ret = $dav->options(-url => $url . '/' . $_); |
|
82 |
# $main::lxdebug->message(0, 'verzeichnis:'. $_ . '::' . $ret . ':' . $dav->message); |
|
83 |
next unless $ret =~ m/MKCOL/; # file not there #owncloud gives DELETE even if file not there |
|
84 |
#$dav->lock(-url => $url . '/' . $_); # UNLOCK after DIR sync |
|
85 |
|
|
86 |
# $main::lxdebug->message(0, 'datei:'. $_); |
|
87 |
unless ( $dav->put(-local => $_, -url => $url . '/' . $_) ) { |
|
88 |
push(@fails, "Cannot put file $_"); |
|
89 |
}; |
|
90 |
#$dav->unlock(-url => $url . '/' . $_); # UNLOCK after put |
|
91 |
} |
|
92 |
|
|
93 |
# maybe we delete some stuff |
|
94 |
# TODO delete stuff here |
|
95 |
if ($DELETE_ONLY) { |
|
96 |
foreach (qw(anfragen bestellungen einkaufslieferscheine einkaufsrechnungen angebote |
|
97 |
gutschriften lieferantenbestellungen rechnungen verkaufslieferscheine)) { |
|
98 |
$ret = $dav->delete($url . "/$_"); |
|
99 |
} |
|
100 |
|
|
101 |
# better, but not implemented - delete only local deleted stuff |
|
102 |
# idea: propfind all the above dirs and check if child (rel_uri) exists locally |
|
103 |
# if not, we can safely delete remote |
|
104 |
# if (my $r=$dav->propfind( -url=>"$_/", -depth=>1) ) { ... |
|
105 |
} |
|
106 |
|
|
107 |
#$dav->unlock(-url => $url); |
|
108 |
chdir($cwd); |
|
109 |
|
|
110 |
1; |
|
111 |
|
|
112 |
} or do { |
|
113 |
my $error = "dav: " . $dav->message . ", eval: " . $! . ", eval 2: " . $@; |
|
114 |
# $dav->unlock(-url => $url); # unlock, just in case |
|
115 |
# chdir($cwd); |
|
116 |
die("Couldn't sync with external webdav repo at $url error code/protocol return:" . $error); |
|
117 |
}; |
|
118 |
|
|
119 |
if ( @fails ) { |
|
120 |
die join("\n", @fails); |
|
121 |
}; |
|
122 |
|
|
123 |
return 1; |
|
124 |
} |
|
125 |
|
|
126 |
1; |
|
127 |
|
|
128 |
__END__ |
|
129 |
|
|
130 |
=encoding utf8 |
|
131 |
|
|
132 |
=head1 NAME |
|
133 |
|
|
134 |
SL::BackgroundJob::ExternalSyncWebDAV - Background job for |
|
135 |
syncing all folders and files for current client to a external |
|
136 |
webdav-repository |
|
137 |
|
|
138 |
=head1 SYNOPSIS |
|
139 |
|
|
140 |
This background job copies all files and folders for one client |
|
141 |
to a external webdav-repo. |
|
142 |
A optional param C<delete> can be set to 1 to delete (clean) |
|
143 |
the external repo. If set to undef or 0 a folderwise copy will be |
|
144 |
executed. |
|
145 |
To test with different clients a param C<client_id> will overload |
|
146 |
the current client id. |
|
147 |
The settings for the external repo are in client config. |
|
148 |
If a lock still exists, the job returns a Internal Server Error |
|
149 |
from the webdav server. |
|
150 |
Only pdf files are considered valid files to copy. |
|
151 |
|
|
152 |
The job is supposed to run once a day. |
|
153 |
|
|
154 |
=head1 BUGS |
|
155 |
|
|
156 |
Nothing here yet. |
|
157 |
|
|
158 |
=head1 AUTHOR |
|
159 |
|
|
160 |
Jan Büren E<lt>jan@kivitendo-premium.deE<gt> |
|
161 |
|
|
162 |
=cut |
|
163 |
|
SL/DB/MetaSetup/Default.pm | ||
---|---|---|
223 | 223 |
warn_no_delivery_order_for_invoice => { type => 'boolean', default => 'false' }, |
224 | 224 |
webdav => { type => 'boolean', default => 'false' }, |
225 | 225 |
webdav_documents => { type => 'boolean', default => 'false' }, |
226 |
webdav_sync_extern => { type => 'boolean', default => 'false' }, |
|
227 |
webdav_sync_extern_login => { type => 'text' }, |
|
228 |
webdav_sync_extern_pass => { type => 'text' }, |
|
229 |
webdav_sync_extern_url => { type => 'text' }, |
|
226 | 230 |
weightunit => { type => 'varchar', length => 5 }, |
227 | 231 |
workflow_po_ap_chart_id => { type => 'integer' }, |
228 | 232 |
); |
SL/InstallationCheck.pm | ||
---|---|---|
77 | 77 |
); |
78 | 78 |
|
79 | 79 |
@optional_modules = ( |
80 |
{ name => 'HTTP::DAV', version => 0.46, url => 'http://search.cpan.org/~cosimo/', debian => 'libhttp-dav-perl' }, |
|
80 | 81 |
{ name => "IO::Socket::SSL", url => "http://search.cpan.org/~sullr/", debian => 'libio-socket-ssl-perl' }, |
81 | 82 |
{ name => "Net::LDAP", url => "http://search.cpan.org/~gbarr/", debian => 'libnet-ldap-perl' }, |
82 | 83 |
# Net::SMTP is core since 5.7.3 |
sql/Pg-upgrade2/defaults_webdav.sql | ||
---|---|---|
1 |
-- @tag: defaults_webdav |
|
2 |
-- @description: Synchronisation mit externem WebDAV-Server |
|
3 |
-- @depends: release_3_8_0 |
|
4 |
ALTER TABLE defaults ADD COLUMN webdav_sync_extern boolean DEFAULT false; |
|
5 |
ALTER TABLE defaults ADD COLUMN webdav_sync_extern_url text; |
|
6 |
ALTER TABLE defaults ADD COLUMN webdav_sync_extern_login text; |
|
7 |
ALTER TABLE defaults ADD COLUMN webdav_sync_extern_pass text; |
templates/design40_webpages/client_config/_features.html | ||
---|---|---|
34 | 34 |
<td>[% L.yes_no_tag('defaults.webdav_documents', SELF.defaults.webdav_documents) %]</td> |
35 | 35 |
<td class="long-desc">[% LxERP.t8('Save document in WebDAV repository') %]</td> |
36 | 36 |
</tr> |
37 |
<tr> |
|
38 |
<th>[% LxERP.t8('WebDAV sync extern') %]</td> |
|
39 |
<td>[% L.yes_no_tag('defaults.webdav_sync_extern', SELF.defaults.webdav_sync_extern) %]</td> |
|
40 |
<td class="long-desc">[% LxERP.t8('Synchronize WebDAV with owncloud repository') %]</td> |
|
41 |
</tr> |
|
42 |
<tr> |
|
43 |
<th>[% LxERP.t8('Destination URL for sync') %]</td> |
|
44 |
<td class="long-desc"> [% L.input_tag('defaults.webdav_sync_extern_url', SELF.defaults.webdav_sync_extern_url, style=style) %]</td> |
|
45 |
<td>[% LxERP.t8('Complete URL for WebDAV sync external, including port and folders, i.e.: https://foo.com:4433/owncloud/kivitendo') %]</td> |
|
46 |
</tr> |
|
47 |
<tr> |
|
48 |
<th>[% LxERP.t8('Login for sync') %]</td> |
|
49 |
<td class="long-desc">[% L.input_tag('defaults.webdav_sync_extern_login', SELF.defaults.webdav_sync_extern_login, style=style) %]</td> |
|
50 |
<td>[% LxERP.t8('Login for WebDAV sync external') %]</td> |
|
51 |
</tr> |
|
52 |
<tr> |
|
53 |
<th>[% LxERP.t8('Password for sync') %]</td> |
|
54 |
<td class="long-desc">[% L.input_tag('defaults.webdav_sync_extern_pass', SELF.defaults.webdav_sync_extern_pass, style=style) %]</td> |
|
55 |
<td>[% LxERP.t8('Password for WebDAV sync external') %]</td> |
|
56 |
</tr> |
|
37 | 57 |
<tr> |
38 | 58 |
<th>[% LxERP.t8('Filemanagement') %]</th> |
39 | 59 |
<td>[% L.yes_no_tag('defaults.doc_storage', SELF.defaults.doc_storage) %]</td> |
templates/webpages/client_config/_features.html | ||
---|---|---|
29 | 29 |
<td>[% L.yes_no_tag('defaults.webdav_documents', SELF.defaults.webdav_documents) %]</td> |
30 | 30 |
<td>[% LxERP.t8('Save document in WebDAV repository') %]</td> |
31 | 31 |
</tr> |
32 |
<tr> |
|
33 |
<td align="right">[% LxERP.t8('WebDAV sync extern') %]</td> |
|
34 |
<td>[% L.yes_no_tag('defaults.webdav_sync_extern', SELF.defaults.webdav_sync_extern) %]</td> |
|
35 |
<td>[% LxERP.t8('Synchronize WebDAV with owncloud repository') %]</td> |
|
36 |
</tr> |
|
37 |
<tr> |
|
38 |
<td align="right">[% LxERP.t8('Destination URL for sync') %]</td> |
|
39 |
<td>[% L.input_tag('defaults.webdav_sync_extern_url', SELF.defaults.webdav_sync_extern_url, style=style) %]</td> |
|
40 |
<td>[% LxERP.t8('Complete URL for WebDAV sync external, including port and folders, i.e.: https://foo.com:4433/owncloud/kivitendo') %]</td> |
|
41 |
</tr> |
|
42 |
<tr> |
|
43 |
<td align="right">[% LxERP.t8('Login for sync') %]</td> |
|
44 |
<td>[% L.input_tag('defaults.webdav_sync_extern_login', SELF.defaults.webdav_sync_extern_login, style=style) %]</td> |
|
45 |
<td>[% LxERP.t8('Login for WebDAV sync external') %]</td> |
|
46 |
</tr> |
|
47 |
<tr> |
|
48 |
<td align="right">[% LxERP.t8('Password for sync') %]</td> |
|
49 |
<td>[% L.input_tag('defaults.webdav_sync_extern_pass', SELF.defaults.webdav_sync_extern_pass, style=style) %]</td> |
|
50 |
<td>[% LxERP.t8('Password for WebDAV sync external') %]</td> |
|
51 |
</tr> |
|
32 | 52 |
<tr> |
33 | 53 |
<td align="right">[% LxERP.t8('Filemanagement') %]</td> |
34 | 54 |
<td>[% L.yes_no_tag('defaults.doc_storage', SELF.defaults.doc_storage) %]</td> |
Auch abrufbar als: Unified diff
Hintergrund-Job externe WebDAV-Synchronisation von um kivi-WebDAV-Ordnern