SOAP.pm 52.6 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

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

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

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

96
97
    my @result;

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

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

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

        my $result_item = {};
IKEDA Soji's avatar
IKEDA Soji committed
106
        my $result = Sympa::Scenario->new($list, 'visibility')->authz(
107
108
109
110
111
112
113
114
115
116
            '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
117
118
        $result_item->{'listAddress'} = Sympa::get_address($list);
        $result_item->{'subject'}     = $list->{'admin'}{'subject'};
119
        $result_item->{'subject'} =~ s/;/,/g;
120
        $result_item->{'homepage'} = Sympa::get_url($list, 'info');
121
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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ## Now fetch email attribute from LDAP
Luc Didry's avatar
Luc Didry committed
272
273
274
275
276
    unless (
        $email = 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
    ## Create Sympa::WWW::Session object
285
286
    my $session =
        Sympa::WWW::Session->new($robot, {cookie => $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')
296
        ->value($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 =
322
        Sympa::WWW::Session->new($ENV{'SYMPA_ROBOT'}, {cookie => $cookie});
323

Sympa authors's avatar
Sympa authors committed
324
325
326
327
328
    unless (defined $session
        && !$session->{'new_session'}
        && $session->{'email'} eq $email) {
        $log->syslog('err',
            'Failed to authenticate user %s with session ID %s',
329
            $email, $cookie);
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_session'};
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) =
Luc Didry's avatar
Luc Didry committed
391
392
        Sympa::WWW::Auth::remote_app_check_password($appname, $apppassword,
        $robot, $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
    }

IKEDA Soji's avatar
IKEDA Soji committed
501
502
    my $result = Sympa::Scenario->new($list, 'info')->authz(
        '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 {
Luc Didry's avatar
Luc Didry committed
563
564
    $log->syslog(
        'info',
565
        '(%s, listname=%s, subject=%s, template=%s, description=%s, topics=%s)',
Luc Didry's avatar
Luc Didry committed
566
567
        @_
    );
568
569
570
    my $class       = shift;
    my $listname    = shift;
    my $subject     = shift;
571
    my $list_tpl    = shift;
572
    my $description = shift;
573
    my $topics      = shift;
574

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

882
883
884