SOAP.pm 53 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
IKEDA Soji's avatar
IKEDA Soji committed
11
12
# Copyright 2017, 2018, 2019, 2020 The Sympa Community. See the AUTHORS.md
# file at the top-level directory of this distribution and at
13
# <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 = {};
IKEDA Soji's avatar
IKEDA Soji committed
107
        my $result = Sympa::Scenario->new($list, 'visibility')->authz(
108
109
110
111
112
113
114
115
116
117
            '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
118
119
        $result_item->{'listAddress'} = Sympa::get_address($list);
        $result_item->{'subject'}     = $list->{'admin'}{'subject'};
120
        $result_item->{'subject'} =~ s/;/,/g;
121
        $result_item->{'homepage'} = Sympa::get_url($list, 'info');
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

        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;
        }
    }

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

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

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

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

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

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

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

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

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

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

203
    ## Also return the cookie value
204
    return SOAP::Data->name('result')->type('string')
205
        ->value($ENV{SESSION_ID});
salaun's avatar
salaun committed
206
207
}

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

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

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

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

salaun's avatar
salaun committed
231
232
233
    ## 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);
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    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) {
249
            $log->syslog(
250
251
                'err', 'CAS ticket %s not validated by server %s: %s',
                $proxyTicket, $auth_service->{'base_url'},
252
253
254
255
256
                AuthCAS::get_errors()
            );
            next;
        }

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

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

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

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

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

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

295
    ## Also return the cookie value
296
    return SOAP::Data->name('result')->type('string')
297
        ->value($ENV{SESSION_ID});
298
299
300
301
302
303
}

## 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) = @_;
304
    my $session_id;
305

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

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

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

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

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

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

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

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

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

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

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

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

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

395
    unless (defined $proxy_vars) {
396
        $log->syslog('notice', 'Authentication failed');
397
        die SOAP::Fault->faultcode('Server')
398
            ->faultstring('Authentication failed')
399
400
401
402
403
404
            ->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
405
        # $log->syslog('notice',
406
        #     'Remote application is trusted proxy for %s', $var);
407
408
409

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

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

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

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

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

    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);
446
    my $list = Sympa::List->new($listname, $robot);
447

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

    if ($list) {
        if ($function eq 'subscriber') {
            return SOAP::Data->name('result')->type('boolean')
                ->value($list->is_list_member($user));
454
        } elsif ($function eq 'editor') {
455
            return SOAP::Data->name('result')->type('boolean')
456
457
458
459
460
                ->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));
461
462
463
464
465
466
467
468
469
        } 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
470
471
472

}

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

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

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

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

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

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

IKEDA Soji's avatar
IKEDA Soji committed
502
503
    my $result = Sympa::Scenario->new($list, 'info')->authz(
        'md5',
504
505
506
507
        {   'sender'                  => $sender,
            'remote_application_name' => $ENV{'remote_application_name'}
        }
    );
508
509
    my $action;
    $action = $result->{'action'} if (ref($result) eq 'HASH');
510

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

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

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

        ## determine status of user
536
537
        if ($list->is_admin('owner', $sender)
            or Sympa::is_listmaster($list, $sender)) {
538
539
540
            $result_item->{'isOwner'} =
                SOAP::Data->name('isOwner')->type('boolean')->value(1);
        }
541
        if ($list->is_admin('actual_editor', $sender)) {
542
543
544
545
546
547
548
549
550
            $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);
551
        return SOAP::Data->value([$result_item]);
552
    }
553
    $log->syslog('info',
554
555
        'Info %s from %s aborted, unknown requested action in scenario',
        $listname, $sender);
556
    die SOAP::Fault->faultcode('Server')
557
558
559
560
        ->faultstring('Unknown requested action')->faultdetail(
        "SOAP info : %s from %s aborted because unknown requested action in scenario",
        $listname, $sender
        );
561
562
}

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

576
577
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
578
579
580
    my $remote_application_name = $ENV{'remote_application_name'};

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

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

592
    my $reject;
593
594
    unless ($subject) {
        $reject .= 'subject';
595
    }
596
    unless ($list_tpl) {
597
        $reject .= ', template';
598
    }
599
600
    unless ($description) {
        $reject .= ', description';
601
    }
602
603
    unless ($topics) {
        $reject .= 'topics';
604
    }
605
    if ($reject) {
606
        $log->syslog('info',
607
            'Create_list %s@%s from %s refused, missing parameter(s) %s',
608
            $listname, $robot, $sender, $reject);
609
610
        die SOAP::Fault->faultcode('Server')
            ->faultstring('Missing parameter')
611
            ->faultdetail("Missing required parameter(s) : $reject");
612
    }
613
614
615
616
617

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

    my $spindle = Sympa::Spindle::ProcessRequest->new(
Luc Didry's avatar
Luc Didry committed
618
619
        context    => $robot,
        action     => 'create_list',
620
        parameters => {
621
622
            listname => $listname,
            owner    => [
Luc Didry's avatar
Luc Didry committed
623
624
625
626
                {   email => $sender,
                    gecos => ($user ? $user->{gecos} : undef),
                }
            ],
627
628
            subject        => $subject,
            creation_email => $sender,
IKEDA Soji's avatar
IKEDA Soji committed
629
            type           => $list_tpl,
630
631
632
633
634
635
636
637
            topics         => $topics,
            description    => $description,
        },
        sender    => $sender,
        md5_check => 1,

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

652
653
654
655
656
657
658
659
660
661
662
663
664
    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);
665
666
667
        }
    }
    return SOAP::Data->name('result')->type('boolean')->value(1);
668
669
}

sympa-authors's avatar
   
sympa-authors committed
670
sub closeList {
671
672
    my $class    = shift;
    my $listname = shift;
sympa-authors's avatar
   
sympa-authors committed
673

674
675
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
sympa-authors's avatar
   
sympa-authors committed
676
677
    my $remote_application_name = $ENV{'remote_application_name'};

678
    $log->syslog('info', '(list = %s\@%s) From %s via proxy application %s',
679
        $listname, $robot, $sender, $remote_application_name);
sympa-authors's avatar
   
sympa-authors committed
680
681

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

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

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

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

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

712
    my $spindle = Sympa::Spindle::ProcessRequest->new(
713
        context      => $list->{'domain'},
Luc Didry's avatar
Luc Didry committed
714
715
        action       => 'close_list',
        current_list => $list,
716
717
718
719
        mode =>
            (($list->{'admin'}{'status'} eq 'pending') ? 'purge' : 'close'),
        sender           => $sender,
        md5_check        => 1,
720
        scenario_context => {
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
            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);
        }
745
    }
746
    return SOAP::Data->name('result')->type('boolean')->value(1);
sympa-authors's avatar
   
sympa-authors committed
747
748
}

sympa-authors's avatar
   
sympa-authors committed
749
sub add {
750
751
752
753
754
755
756
757
    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
758
    my $remote_application_name = $ENV{'remote_application_name'};
759

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

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

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

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

820
    foreach my $report (@{$spindle->{stash} || []}) {
821
        my $reason_string = get_reason_string($report, $robot);
822
823
824
825
        if ($report->[1] eq 'auth') {
            die SOAP::Fault->faultcode('Server')->faultstring('Not allowed.')
                ->faultdetail($reason_string);
        } elsif ($report->[1] eq 'intern') {
826
            die SOAP::Fault->faultcode('Server')
827
828
829
830
831
                ->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')
832
                ->faultdetail($reason_string);
833
        }
sympa-authors's avatar
   
sympa-authors committed
834
    }
835
    return SOAP::Data->name('result')->type('boolean')->value(1);
sympa-authors's avatar
   
sympa-authors committed
836
837
838
}

sub del {
839
840
841
842
    my $class    = shift;
    my $listname = shift;
    my $email    = shift;
    my $quiet    = shift;
sympa-authors's avatar
   
sympa-authors committed
843

844
845
    my $sender                  = $ENV{'USER_EMAIL'};
    my $robot                   = $ENV{'SYMPA_ROBOT'};
sympa-authors's avatar
   
sympa-authors committed
846
    my $remote_application_name = $ENV{'remote_application_name'};
847

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

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

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