SOAP.pm 53.3 KB
Newer Older
1
2
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
3
4
5
6
7
8
9
# $Id$

# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
10
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
11
12
13
# Copyright 2017 The Sympa Community. See the AUTHORS.md file at the top-level
# directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
14
#
salaun's avatar
salaun committed
15
16
17
18
19
20
21
22
23
24
25
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
26
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
salaun's avatar
salaun committed
27

IKEDA Soji's avatar
IKEDA Soji committed
28
package Sympa::WWW::SOAP;
salaun's avatar
salaun committed
29

30
31
use strict;
use warnings;
sikeda's avatar
sikeda committed
32
use Encode qw();
salaun's avatar
salaun committed
33

34
use Sympa;
salaun's avatar
salaun committed
35
use Conf;
36
use Sympa::Constants;
37
use Sympa::List;
38
use Sympa::Log;
39
use Sympa::Scenario;
40
use Sympa::Spindle::ProcessRequest;
41
use Sympa::Template;
42
use Sympa::Tools::Text;
sikeda's avatar
sikeda committed
43
use Sympa::User;
IKEDA Soji's avatar
IKEDA Soji committed
44
45
use Sympa::WWW::Auth;
use Sympa::WWW::Session;
salaun's avatar
salaun committed
46

47
## Define types of SOAP type listType
48
49
50
51
52
53
54
55
56
57
58
59
my %types = (
    'listType' => {
        'listAddress'  => 'string',
        'homepage'     => 'string',
        'isSubscriber' => 'boolean',
        'isOwner'      => 'boolean',
        'isEditor'     => 'boolean',
        'subject'      => 'string',
        'email'        => 'string',
        'gecos'        => 'string'
    }
);
60

61
62
my $log = Sympa::Log->instance;

63
sub checkCookie {
salaun's avatar
salaun committed
64
65
    my $class = shift;

salaun's avatar
salaun committed
66
67
68
    my $sender = $ENV{'USER_EMAIL'};

    unless ($sender) {
69
        die SOAP::Fault->faultcode('Client')
70
            ->faultstring('User not authenticated')
71
            ->faultdetail('You should login first');
salaun's avatar
salaun committed
72
73
    }

74
    $log->syslog('debug', 'SOAP checkCookie');
75

salaun's avatar
salaun committed
76
    return SOAP::Data->name('result')->type('string')->value($sender);
salaun's avatar
salaun committed
77
78
}

salaun's avatar
salaun committed
79
sub lists {
80
81
    my $self     = shift;    #$self is a service object
    my $topic    = shift;
salaun's avatar
salaun committed
82
    my $subtopic = shift;
83
    my $mode     = shift;
84
    $mode ||= '';
85

salaun's avatar
salaun committed
86
    my $sender = $ENV{'USER_EMAIL'};
87
    my $robot  = $ENV{'SYMPA_ROBOT'};
88

89
    $log->syslog('notice', '(%s, %s, %s)', $topic, $subtopic, $sender);
salaun's avatar
salaun committed
90

salaun's avatar
salaun committed
91
    unless ($sender) {
92
        die SOAP::Fault->faultcode('Client')
93
            ->faultstring('User not authenticated')
94
            ->faultdetail('You should login first');
salaun's avatar
salaun committed
95
96
    }

97
98
    my @result;

99
    $log->syslog('info', '(%s, %s)', $topic, $subtopic);
100

101
    my $all_lists = Sympa::List::get_lists($robot);
102
103
104
105
106
    foreach my $list (@$all_lists) {

        my $listname = $list->{'name'};

        my $result_item = {};
107
        my $result      = Sympa::Scenario::request_action(
108
            $list,
109
110
111
112
113
114
115
116
117
118
119
            'visibility',
            'md5',
            {   'sender'                  => $sender,
                'remote_application_name' => $ENV{'remote_application_name'}
            }
        );
        my $action;
        $action = $result->{'action'} if (ref($result) eq 'HASH');
        next unless ($action eq 'do_it');

        ##building result packet
120
121
        $result_item->{'listAddress'} = Sympa::get_address($list);
        $result_item->{'subject'}     = $list->{'admin'}{'subject'};
122
        $result_item->{'subject'} =~ s/;/,/g;
123
        $result_item->{'homepage'} = Sympa::get_url($list, 'info');
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

        my $listInfo;
        if ($mode eq 'complex') {
            $listInfo = struct_to_soap($result_item);
        } else {
            $listInfo = struct_to_soap($result_item, 'as_string');
        }

        ## no topic ; List all lists
        if (!$topic) {
            push @result, $listInfo;

        } elsif ($list->{'admin'}{'topics'}) {
            foreach my $list_topic (@{$list->{'admin'}{'topics'}}) {
                my @tree = split '/', $list_topic;

                next if (($topic)    && ($tree[0] ne $topic));
                next if (($subtopic) && ($tree[1] ne $subtopic));

                push @result, $listInfo;
            }
        } elsif ($topic eq 'topicsless') {
            push @result, $listInfo;
        }
    }

150
    return SOAP::Data->name('listInfo')->value(\@result);
salaun's avatar
salaun committed
151
152
}

salaun's avatar
salaun committed
153
sub login {
154
155
    my $class  = shift;
    my $email  = shift;
156
157
158
    my $passwd = shift;

    my $http_host = $ENV{'SERVER_NAME'};
159
    my $robot     = $ENV{'SYMPA_ROBOT'};
160
    $log->syslog('notice', '(%s)', $email);
161

salaun's avatar
salaun committed
162
    #foreach my  $k (keys %ENV) {
163
    #$log->syslog('notice', 'ENV %s = %s', $k, $ENV{$k});
salaun's avatar
salaun committed
164
    #}
165
    unless (defined $http_host) {
166
        $log->syslog('err', 'SERVER_NAME not defined');
167
168
    }
    unless (defined $email) {
169
        $log->syslog('err', 'Email not defined');
170
171
    }
    unless (defined $passwd) {
172
        $log->syslog('err', 'Passwd not defined');
173
    }
174

salaun's avatar
salaun committed
175
    unless ($http_host and $email and $passwd) {
176
        $log->syslog('err', 'Incorrect number of parameters');
177
178
179
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <HTTP host> <email> <password>');
salaun's avatar
salaun committed
180
    }
181

salaun's avatar
salaun committed
182
183
184
    ## Authentication of the sender
    ## Set an env var to find out if in a SOAP context
    $ENV{'SYMPA_SOAP'} = 1;
185

IKEDA Soji's avatar
IKEDA Soji committed
186
    my $user = Sympa::WWW::Auth::check_auth($robot, $email, $passwd);
salaun's avatar
salaun committed
187

188
    unless ($user) {
189
        $log->syslog('notice', 'Login authentication failed');
190
        die SOAP::Fault->faultcode('Server')
191
            ->faultstring('Authentication failed')
192
193
            ->faultdetail("Incorrect password for user $email or bad login");
    }
salaun's avatar
salaun committed
194

IKEDA Soji's avatar
IKEDA Soji committed
195
196
197
    ## Create Sympa::WWW::Session object
    my $session = Sympa::WWW::Session->new($robot,
        {'cookie' => Sympa::WWW::Session::encrypt_session_id($ENV{'SESSION_ID'})});
198
199
200
    $ENV{'USER_EMAIL'} = $email;
    $session->{'email'} = $email;
    $session->store();
201

202
203
    ## Note that id_session changes each time it is saved in the DB
    $ENV{'SESSION_ID'} = $session->{'id_session'};
salaun's avatar
salaun committed
204

205
    ## Also return the cookie value
206
    return SOAP::Data->name('result')->type('string')
IKEDA Soji's avatar
IKEDA Soji committed
207
        ->value(Sympa::WWW::Session::encrypt_session_id($ENV{'SESSION_ID'}));
salaun's avatar
salaun committed
208
209
}

210
sub casLogin {
211
    my $class       = shift;
salaun's avatar
salaun committed
212
213
214
    my $proxyTicket = shift;

    my $http_host = $ENV{'SERVER_NAME'};
215
216
    my $sender    = $ENV{'USER_EMAIL'};
    my $robot     = $ENV{'SYMPA_ROBOT'};
217
    $log->syslog('notice', '(%s)', $proxyTicket);
218

salaun's avatar
salaun committed
219
    unless ($http_host and $proxyTicket) {
220
        $log->syslog('err', 'Incorrect number of parameters');
221
222
223
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <HTTP host> <proxyTicket>');
salaun's avatar
salaun committed
224
    }
225
226

    unless (eval "require AuthCAS") {
227
        $log->syslog('err',
228
229
            "Unable to use AuthCAS library, install AuthCAS (CPAN) first");
        return undef;
230
231
232
    }
    require AuthCAS;

salaun's avatar
salaun committed
233
234
235
    ## Validate the CAS ST against all known CAS servers defined in auth.conf
    ## CAS server response will include the user's NetID
    my ($user, @proxies, $email, $cas_id);
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    foreach my $service_id (0 .. $#{$Conf::Conf{'auth_services'}{$robot}}) {
        my $auth_service = $Conf::Conf{'auth_services'}{$robot}[$service_id];
        ## skip non CAS entries
        next
            unless ($auth_service->{'auth_type'} eq 'cas');

        my $cas = AuthCAS->new(
            casUrl => $auth_service->{'base_url'},
            #CAFile => '/usr/local/apache/conf/ssl.crt/ca-bundle.crt',
        );

        ($user, @proxies) =
            $cas->validatePT(Conf::get_robot_conf($robot, 'soap_url'),
            $proxyTicket);
        unless (defined $user) {
251
            $log->syslog(
252
253
                'err', 'CAS ticket %s not validated by server %s: %s',
                $proxyTicket, $auth_service->{'base_url'},
254
255
256
257
258
                AuthCAS::get_errors()
            );
            next;
        }

259
        $log->syslog('notice', 'User %s authenticated against server %s',
260
261
262
263
264
265
266
267
            $user, $auth_service->{'base_url'});

        ## User was authenticated
        $cas_id = $service_id;
        last;
    }

    unless ($user) {
268
        $log->syslog('notice', 'Login authentication failed');
269
        die SOAP::Fault->faultcode('Server')
270
            ->faultstring('Authentication failed')
271
272
            ->faultdetail("Proxy ticket could not be validated");
    }
salaun's avatar
salaun committed
273
274

    ## Now fetch email attribute from LDAP
275
    unless ($email =
IKEDA Soji's avatar
IKEDA Soji committed
276
        Sympa::WWW::Auth::get_email_by_net_id($robot, $cas_id, {'uid' => $user})) {
277
        $log->syslog('err',
278
279
            'Could not get email address from LDAP for user %s', $user);
        die SOAP::Fault->faultcode('Server')
280
            ->faultstring('Authentication failed')
281
            ->faultdetail("Could not get email address from LDAP directory");
salaun's avatar
salaun committed
282
283
    }

IKEDA Soji's avatar
IKEDA Soji committed
284
285
286
    ## Create Sympa::WWW::Session object
    my $session = Sympa::WWW::Session->new($robot,
        {'cookie' => Sympa::WWW::Session::encrypt_session_id($ENV{'SESSION_ID'})});
287
288
289
    $ENV{'USER_EMAIL'} = $email;
    $session->{'email'} = $email;
    $session->store();
290

291
292
    ## Note that id_session changes each time it is saved in the DB
    $ENV{'SESSION_ID'} = $session->{'id_session'};
salaun's avatar
salaun committed
293

294
    ## Also return the cookie value
295
    return SOAP::Data->name('result')->type('string')
IKEDA Soji's avatar
IKEDA Soji committed
296
        ->value(Sympa::WWW::Session::encrypt_session_id($ENV{'SESSION_ID'}));
297
298
299
300
301
302
}

## Used to call a service as an authenticated user without using HTTP cookies
## First parameter is the secret contained in the cookie
sub authenticateAndRun {
    my ($self, $email, $cookie, $service, $parameters) = @_;
303
    my $session_id;
304

305
    if ($parameters) {
306
        $log->syslog('notice', '(%s, %s, %s, %s)',
307
308
            $email, $cookie, $service, join(',', @$parameters));
    } else {
309
        $log->syslog('notice', '(%s, %s, %s)', $email, $cookie, $service);
310
    }
311

312
    unless ($cookie and $service) {
313
        $log->syslog('err', "Missing parameter");
314
315
316
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <email> <cookie> <service>');
317
318
    }

319
320
321
    ## Provided email is not trusted, we fetch the user email from the
    ## session_table instead
    my $session =
IKEDA Soji's avatar
IKEDA Soji committed
322
        Sympa::WWW::Session->new($ENV{'SYMPA_ROBOT'}, {'cookie' => $cookie});
323
    if (defined $session) {
324
325
        $email      = $session->{'email'};
        $session_id = $session->{'id_session'};
326
    }
327
    unless ($email or $email eq 'unknown') {
328
        $log->syslog('err', 'Failed to authenticate user with session ID %s',
329
            $session_id);
330
331
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Could not get email from cookie')->faultdetail('');
332
    }
333

334
    $ENV{'USER_EMAIL'} = $email;
335
    $ENV{'SESSION_ID'} = $session_id;
336

337
    no strict 'refs';
338
    $service->($self, @$parameters);
salaun's avatar
salaun committed
339
}
340
341
342
343
344
## request user email from http cookie
##
sub getUserEmailByCookie {
    my ($self, $cookie) = @_;

345
    $log->syslog('debug3', '(%s)', $cookie);
346

347
    unless ($cookie) {
348
        $log->syslog('err', "Missing parameter cookie");
349
350
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Missing parameter')->faultdetail('Use : <cookie>');
351
352
353
    }

    my $session =
IKEDA Soji's avatar
IKEDA Soji committed
354
        Sympa::WWW::Session->new($ENV{'SYMPA_ROBOT'}, {'cookie' => $cookie});
355
356

    unless (defined $session && ($session->{'email'} ne 'unkown')) {
357
        $log->syslog('err', 'Failed to load session for %s', $cookie);
358
359
360
361
362
363
364
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Could not get email from cookie')->faultdetail('');
    }

    return SOAP::Data->name('result')->type('string')
        ->value($session->{'email'});

365
}
366
## Used to call a service from a remote proxy application
367
368
## First parameter is the application name as defined in the
## trusted_applications.conf file
369
##   2nd parameter is remote application password
370
371
##   3nd a string with multiple cars definition comma separated
##   (var=value,var=value,...)
372
373
374
375
376
377
##   4nd is service name requested
##   5nd service parameters
sub authenticateRemoteAppAndRun {
    my ($self, $appname, $apppassword, $vars, $service, $parameters) = @_;
    my $robot = $ENV{'SYMPA_ROBOT'};

378
    if ($parameters) {
379
        $log->syslog('notice', '(%s, %s, %s, %s)',
380
381
            $appname, $vars, $service, join(',', @$parameters));
    } else {
382
        $log->syslog('notice', '(%s, %s, %s)', $appname, $vars, $service);
383
    }
384
385

    unless ($appname and $apppassword and $service) {
386
387
388
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <appname> <apppassword> <vars> <service>');
389
    }
390
    my ($proxy_vars, $set_vars) =
IKEDA Soji's avatar
IKEDA Soji committed
391
        Sympa::WWW::Auth::remote_app_check_password($appname, $apppassword, $robot,
392
        $service);
393

394
    unless (defined $proxy_vars) {
395
        $log->syslog('notice', 'Authentication failed');
396
        die SOAP::Fault->faultcode('Server')
397
            ->faultstring('Authentication failed')
398
399
400
401
402
403
            ->faultdetail("Authentication failed for application $appname");
    }
    $ENV{'remote_application_name'} = $appname;

    foreach my $var (split(/,/, $vars)) {
        # check if the remote application is trusted proxy for this variable
404
        # $log->syslog('notice',
405
        #     'Remote application is trusted proxy for %s', $var);
406
407
408

        my ($id, $value) = split(/=/, $var);
        if (!defined $id) {
409
            $log->syslog('notice', 'Incorrect syntaxe ID');
410
411
412
413
414
            die SOAP::Fault->faultcode('Server')
                ->faultstring('Incorrect syntaxe id')
                ->faultdetail("Unrecognized syntaxe  $var");
        }
        if (!defined $value) {
415
            $log->syslog('notice', 'Incorrect syntaxe value');
416
417
418
419
420
421
            die SOAP::Fault->faultcode('Server')
                ->faultstring('Incorrect syntaxe value')
                ->faultdetail("Unrecognized syntaxe  $var");
        }
        $ENV{$id} = $value if ($proxy_vars->{$id});
    }
422
423
424
425
    # Set fixed variables.
    foreach my $var (keys %$set_vars) {
        $ENV{$var} = $set_vars->{$var};
    }
426
427

    no strict 'refs';
428
    $service->($self, @$parameters);
429
}
salaun's avatar
salaun committed
430

431
sub amI {
432
433
434
435
    my ($class, $listname, $function, $user) = @_;

    my $robot = $ENV{'SYMPA_ROBOT'};

436
    $log->syslog('notice', '(%s, %s, %s)', $listname, $function, $user);
437
438
439
440
441
442
443
444

    unless ($listname and $user and $function) {
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list> <function> <user email>');
    }

    $listname = lc($listname);
445
    my $list = Sympa::List->new($listname, $robot);
446

447
    $log->syslog('debug', '(%s)', $listname);
448
449
450
451
452

    if ($list) {
        if ($function eq 'subscriber') {
            return SOAP::Data->name('result')->type('boolean')
                ->value($list->is_list_member($user));
453
        } elsif ($function eq 'editor') {
454
            return SOAP::Data->name('result')->type('boolean')
455
456
457
458
459
                ->value($list->is_admin('actual_editor', $user));
        } elsif ($function eq 'owner') {
            return SOAP::Data->name('result')->type('boolean')
                ->value($list->is_admin('owner', $user)
                    || Sympa::is_listmaster($list, $user));
460
461
462
463
464
465
466
467
468
        } else {
            die SOAP::Fault->faultcode('Server')
                ->faultstring('Unknown function.')
                ->faultdetail("Function $function unknown");
        }
    } else {
        die SOAP::Fault->faultcode('Server')->faultstring('Unknown list.')
            ->faultdetail("List $listname unknown");
    }
salaun's avatar
salaun committed
469
470
471

}

472
sub info {
473
474
475
    my $class    = shift;
    my $listname = shift;

476
    my $sender = $ENV{'USER_EMAIL'};
477
    my $robot  = $ENV{'SYMPA_ROBOT'};
478
479

    unless ($sender) {
480
        die SOAP::Fault->faultcode('Client')
481
            ->faultstring('User not authenticated')
482
483
            ->faultdetail('You should login first');
    }
484
485

    unless ($listname) {
486
487
488
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list>');
489
    }
490

491
    $log->syslog('notice', '(%s)', $listname);
492

493
    my $list = Sympa::List->new($listname, $robot);
494
    unless ($list) {
495
        $log->syslog('info', 'Info %s from %s refused, list unknown',
496
497
498
            $listname, $sender);
        die SOAP::Fault->faultcode('Server')->faultstring('Unknown list')
            ->faultdetail("List $listname unknown");
499
500
    }

501
    my $result = Sympa::Scenario::request_action(
502
        $list, 'info', 'md5',
503
504
505
506
        {   'sender'                  => $sender,
            'remote_application_name' => $ENV{'remote_application_name'}
        }
    );
507
508
    my $action;
    $action = $result->{'action'} if (ref($result) eq 'HASH');
509

510
511
    die SOAP::Fault->faultcode('Server')->faultstring('No action available')
        unless (defined $action);
512

513
    if ($action =~ /reject/i) {
514
515
        my $reason_string = get_reason_string(
            [{action => 'info'}, 'auth', $result->{'reason'}], $robot);
516
        $log->syslog('info', 'Info %s from %s refused (not allowed)',
517
518
519
            $listname, $sender);
        die SOAP::Fault->faultcode('Server')->faultstring('Not allowed')
            ->faultdetail($reason_string);
520
521
    }
    if ($action =~ /do_it/i) {
522
523
524
525
        my $result_item;

        $result_item->{'listAddress'} =
            SOAP::Data->name('listAddress')->type('string')
526
            ->value(Sympa::get_address($list));
527
528
529
530
531
        $result_item->{'subject'} =
            SOAP::Data->name('subject')->type('string')
            ->value($list->{'admin'}{'subject'});
        $result_item->{'homepage'} =
            SOAP::Data->name('homepage')->type('string')
532
            ->value(Sympa::get_url($list, 'info'));
533
534

        ## determine status of user
535
536
        if ($list->is_admin('owner', $sender)
            or Sympa::is_listmaster($list, $sender)) {
537
538
539
            $result_item->{'isOwner'} =
                SOAP::Data->name('isOwner')->type('boolean')->value(1);
        }
540
        if ($list->is_admin('actual_editor', $sender)) {
541
542
543
544
545
546
547
548
549
            $result_item->{'isEditor'} =
                SOAP::Data->name('isEditor')->type('boolean')->value(1);
        }
        if ($list->is_list_member($sender)) {
            $result_item->{'isSubscriber'} =
                SOAP::Data->name('isSubscriber')->type('boolean')->value(1);
        }

        #push @result, SOAP::Data->type('listType')->value($result_item);
550
        return SOAP::Data->value([$result_item]);
551
    }
552
    $log->syslog('info',
553
554
        'Info %s from %s aborted, unknown requested action in scenario',
        $listname, $sender);
555
    die SOAP::Fault->faultcode('Server')
556
557
558
559
        ->faultstring('Unknown requested action')->faultdetail(
        "SOAP info : %s from %s aborted because unknown requested action in scenario",
        $listname, $sender
        );
560
561
}

562
sub createList {
563
564
565
    $log->syslog('info', 
        '(%s, listname=%s, subject=%s, template=%s, description=%s, topics=%s)',
        @_);
566
567
568
    my $class       = shift;
    my $listname    = shift;
    my $subject     = shift;
569
    my $list_tpl    = shift;
570
    my $description = shift;
571
    my $topics      = shift;
572

573
574
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
575
576
577
    my $remote_application_name = $ENV{'remote_application_name'};

    unless ($sender) {
578
579
580
        die SOAP::Fault->faultcode('Client')
            ->faultstring('User not specified')
            ->faultdetail('Use a trusted proxy or login first ');
581
582
583
    }

    unless ($listname) {
584
585
586
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list>');
587
    }
588

589
    my $reject;
590
591
    unless ($subject) {
        $reject .= 'subject';
592
    }
593
    unless ($list_tpl) {
594
        $reject .= ', template';
595
    }
596
597
    unless ($description) {
        $reject .= ', description';
598
    }
599
600
    unless ($topics) {
        $reject .= 'topics';
601
    }
602
    if ($reject) {
603
        $log->syslog('info',
604
            'Create_list %s@%s from %s refused, missing parameter(s) %s',
605
            $listname, $robot, $sender, $reject);
606
607
        die SOAP::Fault->faultcode('Server')
            ->faultstring('Missing parameter')
608
            ->faultdetail("Missing required parameter(s) : $reject");
609
    }
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

    my $user = Sympa::User::get_global_user($sender)
        if Sympa::User::is_global_user($sender);

    my $spindle = Sympa::Spindle::ProcessRequest->new(
        context      => $robot,
        action       => 'create_list',
        listname     => $listname,
        parameters => {
            owner => [{
                email => $sender,
                gecos => ($user ? $user->{gecos} : undef),
            }],
            subject        => $subject,
            creation_email => $sender,
            template       => $list_tpl,
            topics         => $topics,
            description    => $description,
        },
        sender    => $sender,
        md5_check => 1,

        scenario_context => {
            'sender'                  => $sender,
634
635
            'candidate_listname'      => $listname,
            'candidate_subject'       => $subject,
636
            'candidate_template'      => $list_tpl,
637
638
            'candidate_info'          => $description,
            'candidate_topics'        => $topics,
639
640
641
642
643
            'remote_host'             => $ENV{'REMOTE_HOST'},
            'remote_addr'             => $ENV{'REMOTE_ADDR'},
            'remote_application_name' => $ENV{'remote_application_name'}
        }
    );
644
645
    unless ($spindle and $spindle->spin) {
        die SOAP::Fault->faultcode('Server')->faultstring('Internal error');
646
647
    }

648
649
650
651
652
653
654
655
656
657
658
659
660
    foreach my $report (@{$spindle->{stash} || []}) {
        my $reason_string = get_reason_string($report, $robot);
        if ($report->[1] eq 'auth') {
            die SOAP::Fault->faultcode('Server')->faultstring('Not allowed.')
                ->faultdetail($reason_string);
        } elsif ($report->[1] eq 'intern') {
            die SOAP::Fault->faultcode('Server')
                ->faultstring('Internal error');
        } elsif ($report->[1] eq 'notice') {
            return SOAP::Data->name('result')->type('boolean')->value(1);
        } elsif ($report->[1] eq 'user') {
            die SOAP::Fault->faultcode('Server')->faultstring('Undef')
                ->faultdetail($reason_string);
661
662
663
        }
    }
    return SOAP::Data->name('result')->type('boolean')->value(1);
664
665
}

sympa-authors's avatar
   
sympa-authors committed
666
sub closeList {
667
668
    my $class    = shift;
    my $listname = shift;
sympa-authors's avatar
   
sympa-authors committed
669

670
671
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
sympa-authors's avatar
   
sympa-authors committed
672
673
    my $remote_application_name = $ENV{'remote_application_name'};

674
    $log->syslog('info', '(list = %s\@%s) From %s via proxy application %s',
675
        $listname, $robot, $sender, $remote_application_name);
sympa-authors's avatar
   
sympa-authors committed
676
677

    unless ($sender) {
678
679
680
        die SOAP::Fault->faultcode('Client')
            ->faultstring('User not specified')
            ->faultdetail('Use a trusted proxy or login first ');
sympa-authors's avatar
   
sympa-authors committed
681
682
683
    }

    unless ($listname) {
684
685
686
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list>');
sympa-authors's avatar
   
sympa-authors committed
687
    }
688

689
    $log->syslog('debug', '(%s, %s)', $listname, $robot);
sympa-authors's avatar
   
sympa-authors committed
690

691
    my $list = Sympa::List->new($listname, $robot);
sympa-authors's avatar
   
sympa-authors committed
692
    unless ($list) {
693
        $log->syslog('info', 'CloseList %s@%s from %s refused, unknown list',
694
695
696
            $listname, $robot, $sender);
        die SOAP::Fault->faultcode('Client')->faultstring('unknown list')
            ->faultdetail("inknown list $listname");
sympa-authors's avatar
   
sympa-authors committed
697
    }
698

sympa-authors's avatar
   
sympa-authors committed
699
    # check authorization
700
    unless ($list->is_admin('owner', $sender)
701
        or Sympa::is_listmaster($list, $sender)) {
702
        $log->syslog('info', 'CloseList %s from %s not allowed',
703
704
705
706
            $listname, $sender);
        die SOAP::Fault->faultcode('Client')->faultstring('Not allowed')
            ->faultdetail("Not allowed");
    }
sympa-authors's avatar
   
sympa-authors committed
707

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    my $spindle = Sympa::Spindle::ProcessRequest->new(
        context          => $list,
        action           => 'close_list',
        current_list     => $list,
        mode =>
            (($list->{'admin'}{'status'} eq 'pending') ? 'purge' : 'close'),
        sender           => $sender,
        md5_check        => 1,
        scenario_contest => {
            sender                  => $sender,
            remote_host             => $ENV{'REMOTE_HOST'},
            remote_addr             => $ENV{'REMOTE_ADDR'},
            remote_application_name => $ENV{'remote_application_name'}
        }
    );
    unless ($spindle and $spindle->spin) {
        die SOAP::Fault->faultcode('Server')->faultstring('Internal error');
    }

    foreach my $report (@{$spindle->{stash} || []}) {
        my $reason_string = get_reason_string($report, $robot);
        if ($report->[1] eq 'auth') {
            die SOAP::Fault->faultcode('Server')->faultstring('Not allowed.')
                ->faultdetail($reason_string);
        } elsif ($report->[1] eq 'intern') {
            die SOAP::Fault->faultcode('Server')
                ->faultstring('Internal error');
        } elsif ($report->[1] eq 'notice') {
            return SOAP::Data->name('result')->type('boolean')->value(1);
        } elsif ($report->[1] eq 'user') {
            die SOAP::Fault->faultcode('Server')->faultstring('Undef')
                ->faultdetail($reason_string);
        }
741
    }
742
    return SOAP::Data->name('result')->type('boolean')->value(1);
sympa-authors's avatar
   
sympa-authors committed
743
744
}

sympa-authors's avatar
   
sympa-authors committed
745
sub add {
746
747
748
749
750
751
752
753
    my $class    = shift;
    my $listname = shift;
    my $email    = shift;
    my $gecos    = shift;
    my $quiet    = shift;

    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
sympa-authors's avatar
   
sympa-authors committed
754
    my $remote_application_name = $ENV{'remote_application_name'};
755

756
    $log->syslog(
757
        'info',
758
        '(list = %s@%s, email = %s, quiet = %s) From %s via proxy application %s',
759
760
761
762
763
764
765
        $listname,
        $robot,
        $email,
        $quiet,
        $sender,
        $remote_application_name
    );
sympa-authors's avatar
   
sympa-authors committed
766
767

    unless ($sender) {
768
769
770
        die SOAP::Fault->faultcode('Client')
            ->faultstring('User not specified')
            ->faultdetail('Use a trusted proxy or login first ');
sympa-authors's avatar
   
sympa-authors committed
771
    }
772

sympa-authors's avatar
   
sympa-authors committed
773
    unless ($listname) {
774
775
776
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list>');
sympa-authors's avatar
   
sympa-authors committed
777
778
    }
    unless ($email) {
779
780
781
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <email>');
sympa-authors's avatar
   
sympa-authors committed
782
    }
783
    unless (Sympa::Tools::Text::valid_email($email)) {
784
785
786
787
        my $error = "Invalid email address provided: '$email'";
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Unable to add user')->faultdetail($error);
    }
788
    my $list = Sympa::List->new($listname, $robot);
sympa-authors's avatar
   
sympa-authors committed
789
    unless ($list) {
790
        $log->syslog('info', 'Add %s@%s %s from %s refused, no such list',
791
792
793
            $listname, $robot, $email, $sender);
        die SOAP::Fault->faultcode('Server')->faultstring('Undefined list')
            ->faultdetail("Undefined list");
sympa-authors's avatar
   
sympa-authors committed
794
795
    }

796
797
798
799
800
801
802
803
804
805
806
807
808
809
    my $spindle = Sympa::Spindle::ProcessRequest->new(
        context          => $list,
        action           => 'add',
        sender           => $sender,
        email            => $email,
        gecos            => $gecos,
        quiet            => $quiet,
        md5_check        => 1,
        scenario_contest => {
            sender                  => $sender,
            email                   => $email,
            remote_host             => $ENV{'REMOTE_HOST'},
            remote_addr             => $ENV{'REMOTE_ADDR'},
            remote_application_name => $ENV{'remote_application_name'}
810
811
        }
    );
812
813
    unless ($spindle and $spindle->spin) {
        die SOAP::Fault->faultcode('Server')->faultstring('Internal error');
sympa-authors's avatar
   
sympa-authors committed
814
815
    }

816
    foreach my $report (@{$spindle->{stash} || []}) {
817
        my $reason_string = get_reason_string($report, $robot);
818
819
820
821
        if ($report->[1] eq 'auth') {
            die SOAP::Fault->faultcode('Server')->faultstring('Not allowed.')
                ->faultdetail($reason_string);
        } elsif ($report->[1] eq 'intern') {
822
            die SOAP::Fault->faultcode('Server')
823
824
825
826
827
                ->faultstring('Internal error');
        } elsif ($report->[1] eq 'notice') {
            return SOAP::Data->name('result')->type('boolean')->value(1);
        } elsif ($report->[1] eq 'user') {
            die SOAP::Fault->faultcode('Server')->faultstring('Undef')
828
                ->faultdetail($reason_string);
829
        }
sympa-authors's avatar
   
sympa-authors committed
830
    }
831
    return SOAP::Data->name('result')->type('boolean')->value(1);
sympa-authors's avatar
   
sympa-authors committed
832
833
834
}

sub del {
835
836
837
838
    my $class    = shift;
    my $listname = shift;
    my $email    = shift;
    my $quiet    = shift;
sympa-authors's avatar
   
sympa-authors committed
839

840
841
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
sympa-authors's avatar
   
sympa-authors committed
842
    my $remote_application_name = $ENV{'remote_application_name'};
843

844
    $log->syslog(
845
        'info',
846
        '(list = %s@%s, email = %s, quiet = %s) From %s via proxy application %s',
847
848
849
850
851
852
853
        $listname,
        $robot,
        $email,
        $quiet,
        $sender,
        $remote_application_name
    );
sympa-authors's avatar
   
sympa-authors committed
854
855

    unless ($sender) {
856
857
858
        die SOAP::Fault->faultcode('Client')
            ->faultstring('User not specified')
            ->faultdetail('Use a trusted proxy or login first ');
sympa-authors's avatar
   
sympa-authors committed
859
    }
860

sympa-authors's avatar
   
sympa-authors committed
861
    unless ($listname) {
862
863
864
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <list>');
sympa-authors's avatar
   
sympa-authors committed
865
866
    }
    unless ($email) {
867
868
869
        die SOAP::Fault->faultcode('Client')
            ->faultstring('Incorrect number of parameters')
            ->faultdetail('Use : <email>');
sympa-authors's avatar
   
sympa-authors committed
870
    }
871
    my $list = Sympa::List->new($listname, $robot);
sympa-authors's avatar
   
sympa-authors committed
872
    unless ($list) {
873
        $log->syslog('info', 'Del %s@%s %s from %s refused, no such list',
874
875
876
            $listname, $robot, $email, $sender);
        die SOAP::Fault->faultcode('Server')->faultstring('Undefined list')
            ->faultdetail("Undefined list");
sympa-authors's avatar
   
sympa-authors committed
877
878
    }

879
880
881
882
883
884
885
886
887
888
889
890
891
    my $spindle = Sympa::Spindle::ProcessRequest->new(
        context          => $list,
        action           => 'del',
        sender           => $sender,
        email            => $email,
        quiet            => $quiet,
        md5_check        => 1,
        scenario_contest => {
            sender                  => $sender,
            email                   => $email,
            remote_host             => $ENV{'REMOTE_HOST'},
            remote_addr             => $ENV{'REMOTE_ADDR'},
            remote_application_name => $ENV{'remote_application_name'}
892
893
        }
    );
894
895
    unless ($spindle and $spindle->spin) {
        die SOAP::Fault->faultcode('Server')->faultstring('Internal error');
896
897
    }

898
    foreach my $report (@{$spindle->{stash} || []}) {
899
        my $reason_string = get_reason_string($report, $robot);