ssl option
[freeside.git] / FS / FS / part_export / thirdlane.pm
1 package FS::part_export::thirdlane;
2
3 use base qw( FS::part_export );
4
5 use vars qw(%info $me);
6 use Tie::IxHash;
7 use URI::Escape;
8 use Frontier::Client;
9
10 $me = '['.__PACKAGE__.']';
11
12 tie my %options, 'Tie::IxHash',
13   #'server'           => { label => 'Thirdlane server name or IP address', },
14   'username'         => { label => 'Thirdlane username', },
15   'password'         => { label => 'Thirdlane password', },
16   'ssl'              => { label => 'Enable HTTPS (SSL) connection',
17                           type  => 'checkbox',
18                         },
19   'port'             => { label => 'Port number if not 80 or 443', },
20   'prototype_tenant' => { label => 'Prototype tenant name', },
21   'debug'            => { label => 'Checkbox label', type => 'checkbox' },
22 #  'select_option'   => { label   => 'Select option description',
23 #                         type    => 'select', options=>[qw(chocolate vanilla)],
24 #                         default => 'vanilla',
25 #                       },
26 #  'textarea_option' => { label   => 'Textarea option description',
27 #                         type    => 'textarea',
28 #                         default => 'Default text.',
29 #                      },
30 ;
31
32 %info = (
33   'svc'      => [qw( svc_pbx svc_phone svc_acct )],
34   'desc'     =>
35     'Export tenants, DIDs and admins to Thirdlane PBX manager',
36   'options'  => \%options,
37   'notes'    => <<'END'
38 Exports tenants, DIDs and admins to Thirdlane PBX manager using the XML-RPC API.
39 END
40 );
41
42 sub rebless { shift; }
43
44 sub _export_insert {
45   my($self, $svc_x) = (shift, shift);
46
47   if ( $svc_x->isa('FS::svc_pbx') ) {
48
49     return 'Name must be 19 characters or less (thirdlane restriction?)'
50       if length($svc_x->title) > 19;
51
52     return 'Name must consist of alphanumerics and spaces only (thirdlane restriction?)'
53       unless $svc_x->title =~ /^[\w\s]+$/;
54
55     my $tenant = {
56       'tenant'   => $svc_x->title,
57       'maxusers' => $svc_x->max_extensions,
58       #others?  will they not clone?
59     };
60
61     @what_to_clone = qw(routes schedules menus queues voiceprompts moh);
62
63     my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_create',
64                                             $tenant,
65                                             $self->option('prototype_tenant'),
66                                             \@what_to_clone,
67                                           );
68
69     #use Data::Dumper;
70     #warn Dumper(\$result);
71     $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_create)';
72
73   } elsif ( $svc_x->isa('FS::svc_phone') ) {
74
75     my $result = $self->_thirdlane_command(
76       'asterisk::rpc_did_create',
77       $svc_x->countrycode. $svc_x->phonenum,
78     );
79
80     #use Data::Dumper;
81     #warn Dumper(\$result);
82     $result eq '0' or return 'Thirdlane API failure (rpc_did_create)';
83
84     return '' unless $svc_x->pbxsvc;
85
86     $result = $self->_thirdlane_command(
87       'asterisk::rpc_did_assign',
88       $svc_x->countrycode. $svc_x->phonenum,
89       $svc_x->pbx_title,
90     );
91
92     #use Data::Dumper;
93     #warn Dumper(\$result);
94     $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_assign)';
95
96   } elsif ( $svc_x->isa('FS::svc_acct') ) {
97
98     return 'Must select a PBX' unless $svc_x->pbxsvc;
99
100     my $result = $self->_thirdlane_command(
101       'asterisk::rpc_admin_create',
102       $svc_x->username,
103       $svc_x->_password,
104       $svc_x->pbx_title,
105     );
106
107     #use Data::Dumper;
108     #warn Dumper(\$result);
109     $result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_create)';
110
111   } else {
112     die "guru meditation #10: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
113   }
114
115 }
116
117 sub _export_replace {
118   my($self, $new, $old) = (shift, shift, shift);
119
120 #  #return "can't change username with thirdlane"
121 #  #  if $old->username ne $new->username;
122 #  #return '' unless $old->_password ne $new->_password;
123 #  $err_or_queue = $self->thirdlane_queue( $new->svcnum,
124 #    'replace', $new->username, $new->_password );
125 #  ref($err_or_queue) ? '' : $err_or_queue;
126
127   if ( $new->isa('FS::svc_pbx') ) {
128
129     #need more info on how the API works for changing names.. can it?
130     return "can't change PBX name with thirdlane (yet?)"
131       if $old->title ne $new->title;
132
133     my $tenant = {
134       'tenant'   => $old->title,
135       'maxusers' => $new->max_extensions,
136       #others?  will they not clone?
137     };
138
139     my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_update',
140                                             $tenant
141                                           );
142
143     #use Data::Dumper;
144     #warn Dumper(\$result);
145     $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_update)';
146
147   } elsif ( $new->isa('FS::svc_phone') ) {
148
149     return "can't change DID countrycode with thirdlane"
150       if $old->countrycode ne $new->countrycode;
151     return "can't change DID number with thirdlane"
152       if $old->phonenum ne $new->phonenum;
153
154     if ( $old->pbxsvc != $new->pbxsvc ) {
155
156       if ( $old->pbxsvc ) {
157         my $result = $self->_thirdlane_command(
158           'asterisk::rpc_did_unassign',
159           $new->countrycode. $new->phonenum,
160         );
161         $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
162       }
163
164       if ( $new->pbxsvc ) {
165         my $result = $self->_thirdlane_command(
166           'asterisk::rpc_did_assign',
167           $new->countrycode. $new->phonenum,
168           $new->pbx_title,
169         );
170         $result eq '0' or return 'Thirdlane API failure (rpc_did_assign)';
171       }
172
173
174     }
175
176     '';
177
178   } elsif ( $new->isa('FS::svc_acct') ) {
179
180     return "can't change uesrname with thirdlane"
181       if $old->username ne $new->username;
182
183     return "can't change password with thirdlane"
184       if $old->_password ne $new->_password;
185
186     return "can't change PBX for user with thirdlane"
187       if $old->pbxsvc != $new->pbxsvc;
188
189     ''; #we don't care then
190
191   } else {
192     die "guru meditation #11: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
193   }
194
195 }
196
197 sub _export_delete {
198   my($self, $svc_x) = (shift, shift);
199   #my( $self, $svc_something ) = (shift, shift);
200   #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
201   #  'delete', $svc_something->username );
202   #ref($err_or_queue) ? '' : $err_or_queue;
203
204   if ( $svc_x->isa('FS::svc_pbx') ) {
205
206     my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_delete',
207                                             $svc_x->title,
208                                           );
209
210     #use Data::Dumper;
211     #warn Dumper(\$result);
212     #$result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_delete)';
213     warn "Thirdlane API failure (rpc_tenant_delete); deleting anyway\n"
214       if $result ne '0';
215     '';
216
217   } elsif ( $svc_x->isa('FS::svc_phone') ) {
218
219     if ( $svc_x->pbxsvc ) {
220       my $result = $self->_thirdlane_command(
221         'asterisk::rpc_did_unassign',
222         $svc_x->countrycode. $svc_x->phonenum,
223       );
224       $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
225     }
226
227     my $result = $self->_thirdlane_command(
228       'asterisk::rpc_did_delete',
229       $svc_x->countrycode. $svc_x->phonenum,
230     );
231     $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_delete)';
232
233   } elsif ( $svc_x->isa('FS::svc_acct') ) {
234
235     return '' unless $svc_x->pbxsvc; #error out?  nah
236
237     my $result = $self->_thirdlane_command(
238       'asterisk::rpc_admin_delete',
239       $svc_x->username,
240       $svc_x->pbx_title,
241     );
242
243     #use Data::Dumper;
244     #warn Dumper(\$result);
245     #$result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_delete)';
246     warn "Thirdlane API failure (rpc_admin_delete); deleting anyway\n"
247       if $result ne '0';
248     '';
249
250   } else {
251     die "guru meditation #12: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
252   }
253
254 }
255
256 sub _thirdlane_command {
257   my($self, @param) = @_;
258
259   my $url = $self->option('ssl') ? 'https://' : 'http://';
260   $url .= uri_escape($self->option('username')). ':'.
261           uri_escape($self->option('password')). '@'.
262           $self->machine;
263   $url .= ':'. $self->option('port') if $self->option('port');
264   $url .= '/xmlrpc.cgi';
265
266   warn "$me connecting to $url\n"
267     if $self->option('debug');
268   my $conn = Frontier::Client->new( 'url'   => $url,
269                                     #no, spews output to browser
270                                     #'debug' => $self->option('debug'),
271                                   );
272
273   warn "$me sending command: ". join(' ', @param). "\n"
274     if $self->option('debug');
275   $conn->call(@param);
276   
277 }
278
279   #my( $self, $svc_something ) = (shift, shift);
280   #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
281   #  'delete', $svc_something->username );
282   #ref($err_or_queue) ? '' : $err_or_queue;
283
284 #these three are optional
285 ## fallback for svc_acct will change and restore password
286 #sub _export_suspend {
287 #  my( $self, $svc_something ) = (shift, shift);
288 #  $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
289 #    'suspend', $svc_something->username );
290 #  ref($err_or_queue) ? '' : $err_or_queue;
291 #}
292 #
293 #sub _export_unsuspend {
294 #  my( $self, $svc_something ) = (shift, shift);
295 #  $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
296 #    'unsuspend', $svc_something->username );
297 #  ref($err_or_queue) ? '' : $err_or_queue;
298 #}
299 #
300 #sub export_links {
301 #  my($self, $svc_something, $arrayref) = (shift, shift, shift);
302 #  #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_something->username.
303 #  #                 qq!">!. $svc_something->username. qq!</A>!;
304 #  '';
305 #}
306
307 ####
308 #
309 ##a good idea to queue anything that could fail or take any time
310 #sub thirdlane_queue {
311 #  my( $self, $svcnum, $method ) = (shift, shift, shift);
312 #  my $queue = new FS::queue {
313 #    'svcnum' => $svcnum,
314 #    'job'    => "FS::part_export::thirdlane::thirdlane_$method",
315 #  };
316 #  $queue->insert( @_ ) or $queue;
317 #}
318 #
319 #sub thirdlane_insert { #subroutine, not method
320 #  my( $username, $password ) = @_;
321 #  #do things with $username and $password
322 #}
323 #
324 #sub thirdlane_replace { #subroutine, not method
325 #}
326 #
327 #sub thirdlane_delete { #subroutine, not method
328 #  my( $username ) = @_;
329 #  #do things with $username
330 #}
331 #
332 #sub thirdlane_suspend { #subroutine, not method
333 #}
334 #
335 #sub thirdlane_unsuspend { #subroutine, not method
336 #}
337
338 1;