1package REST::Google::Apps::Provisioning;
2
3use Carp;
4use LWP::UserAgent;
5use XML::Simple;
6
7use strict;
8use warnings;
9
10our $VERSION = '1.1.10';
11
12
13
14sub new {
15    my $self = bless {}, shift;
16
17    my ( $arg );
18    %{$arg} = @_;
19
20    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
21
22    $self->{'domain'} = $arg->{'domain'} || croak( "Missing required 'domain' argument" );
23
24    $self->{'lwp'} = LWP::UserAgent->new();
25    $self->{'lwp'}->agent( 'RESTGoogleAppsProvisioning/' . $VERSION );
26
27    if ( $arg->{'username'} && $arg->{'password'} ) {
28        $self->authenticate(
29            'username' => $arg->{'username'},
30            'password' => $arg->{'password'}
31        )
32        || croak qq(Unable to retrieve authentication token);
33    }
34
35    $self->{'xml'} = XML::Simple->new();
36
37    return( $self );
38}
39
40
41
42sub authenticate {
43    my $self = shift;
44
45    return( 1 ) if $self->{'token'};
46
47    my ( $arg );
48    %{$arg} = @_;
49
50    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
51
52    foreach my $param ( qw/ username password / ) {
53        $arg->{$param} || croak( "Missing required '$param' argument" );
54    }
55
56    my $response = $self->{'lwp'}->post(
57        'https://www.google.com/accounts/ClientLogin',
58        [
59            'accountType' => 'HOSTED',
60            'service'     => 'apps',
61            'Email'       => $arg->{'username'} . '@' . $self->{'domain'},
62            'Passwd'      => $arg->{'password'}
63        ]
64    );
65
66    $response->is_success() || return( 0 );
67
68    foreach ( split( /\n/, $response->content() ) ) {
69        $self->{'token'} = $1 if /^Auth=(.+)$/;
70        last if $self->{'token'};
71    }
72
73    return( 1 ) if $self->{'token'} || return( 0 );
74}
75
76
77
78sub createUser {
79    my $self = shift;
80
81    my ( $arg );
82    %{$arg} = @_;
83
84    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
85
86    foreach my $param ( qw/ username givenname familyname password / ) {
87        $arg->{$param} || croak( "Missing required '$param' argument" );
88    }
89
90    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0);
91
92    my ( $body );
93
94    $body  = $self->_xmlpre();
95
96    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#user" />\n);
97    $body .= qq(  <apps:login userName="$arg->{'username'}" password="$arg->{'password'}" suspended="false");
98
99    if ( $arg->{'passwordhashfunction'}) {
100        $arg->{'passwordhashfunction'} = uc( $arg->{'passwordhashfunction'} );
101
102        unless (
103            ( $arg->{'passwordhashfunction'} eq 'SHA-1' ) ||
104            ( $arg->{'passwordhashfunction'} eq 'MD5' )
105        ) {
106            croak( "Valid passwordHashFunction values are 'MD5' or 'SHA-1'" );
107        }
108
109        $body .= qq( hashFunctionName="$arg->{'passwordhashfunction'}" />\n);
110    }
111    else {
112        $body .= qq( />\n);
113    }
114
115    $body .= qq(  <apps:login admin="$arg->{'admin'} />\n) if $arg->{'admin'};
116    $body .= qq(  <apps:quota limit="$arg->{'quotalimitinmb'}" />\n) if $arg->{'quotalimitinmb'};
117    $body .= qq(  <apps:name familyName="$arg->{'familyname'}" givenName="$arg->{'givenname'}" />\n);
118
119    $body .= $self->_xmlpost();
120
121    my $result = $self->_request(
122        'method' => 'POST',
123        'url'    => $url,
124        'body'   => $body
125    ) || return( 0 );
126
127    my ( $ref );
128
129    $ref->{$arg->{'username'}} = {
130        %{$result->{'apps:name'}},
131        %{$result->{'apps:login'}},
132        %{$result->{'apps:quota'}}
133    };
134
135    return( $ref );
136}
137
138sub deleteUser {
139    my $self = shift;
140
141    my ( $arg );
142    %{$arg} = @_;
143
144    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
145
146    foreach my $param ( qw/ username / ) {
147        $arg->{$param} || croak( "Missing required '$param' argument" );
148    }
149
150    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0/$arg->{'username'});
151
152    my $result = $self->_request( 'method' => 'DELETE', 'url' => $url ) || return( 0 );
153
154    return( 1 ) if $result;
155}
156
157sub getUser {
158    my $self = shift;
159
160    my ( $arg );
161    %{$arg} = @_;
162
163    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
164
165    foreach my $param ( qw/ username / ) {
166        $arg->{$param} || croak( "Missing required '$param' argument" );
167    }
168
169    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0/$arg->{'username'});
170
171    my $result = $self->_request( 'method' => 'GET', 'url' => $url ) || return( 0 );
172
173    my ( $ref );
174
175    $ref->{$arg->{'username'}} = {
176        %{$result->{'apps:name'}},
177        %{$result->{'apps:login'}},
178        %{$result->{'apps:quota'}}
179    };
180
181    return( $ref );
182}
183
184sub getAllUsers {
185    my $self = shift;
186
187    my ( @url, $result, $ref );
188
189    push @url, qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0);
190
191    foreach my $u ( @url ) {
192        $result = $self->_request( 'method' => 'GET', 'url' => $u ) || return( 0 );
193
194        foreach my $link ( @{$result->{'link'}} ) {
195            if ( $link->{'rel'} eq 'next' ) {
196                push @url, $link->{'href'};
197            }
198        }
199
200        foreach ( keys %{$result->{'entry'}} ) {
201            my $username = $1 if /^.*\/(.+)$/;
202            $ref->{$username} = {
203                %{$result->{'entry'}->{$_}->{'apps:name'}},
204                %{$result->{'entry'}->{$_}->{'apps:login'}},
205                %{$result->{'entry'}->{$_}->{'apps:quota'}}
206            };
207        }
208    }
209
210    return( $ref );
211}
212
213sub renameUser {
214    my $self = shift;
215
216    my ( $arg );
217    %{$arg} = @_;
218
219    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
220
221    foreach my $param ( qw/ username newname / ) {
222        $arg->{$param} || croak( "Missing required '$param' argument" );
223    }
224
225    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0/$arg->{'username'});
226
227    my ( $body );
228
229    $body  = $self->_xmlpre();
230
231    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#user" />\n);
232    $body .= qq(  <apps:login userName="$arg->{'newname'}" />\n);
233
234    $body .= $self->_xmlpost();
235
236    my $result = $self->_request(
237        'method' => 'PUT',
238        'url'    => $url,
239        'body'   => $body
240    ) || return( 0 );
241
242    return( 1 );
243}
244
245sub updateUser {
246    my $self = shift;
247
248    my ( $arg );
249    %{$arg} = @_;
250
251    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
252
253    foreach my $param ( qw/ username / ) {
254        $arg->{$param} || croak( "Missing required '$param' argument" );
255    }
256
257    my $user = $self->getUser( username => $arg->{'username'} );
258
259    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/user/2.0/$arg->{'username'});
260
261    my ( $body );
262
263    $body  = $self->_xmlpre();
264
265    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#user" />\n);
266
267    if ( $arg->{'givenname'} || $arg->{'familyname'} ) {
268        $arg->{'givenname'}  ||= $user->{$arg->{'username'}}->{'givenName'};
269        $arg->{'familyname'} ||= $user->{$arg->{'username'}}->{'familyName'};
270        $body .= qq(  <apps:name familyName="$arg->{'familyname'}" givenName="$arg->{'givenname'}" />\n);
271    }
272
273    if ( $arg->{'password'} ) {
274        $body .= qq(  <apps:login userName="$arg->{'username'}" password="$arg->{'password'}");
275        if ( $arg->{'passwordhashfunction'} ) {
276            $arg->{'passwordhashfunction'} = uc( $arg->{'passwordhashfunction'} );
277
278            unless (
279                ( $arg->{'passwordhashfunction'} eq 'SHA-1' ) ||
280                ( $arg->{'passwordhashfunction'} eq 'MD5' )
281            ) {
282                croak( "Valid passwordHashFunction values are 'MD5' or 'SHA-1'" );
283            }
284
285            $body .= qq( hashFunctionName="$arg->{'passwordhashfunction'}" />\n);
286        }
287        else {
288            $body .= qq( />\n);
289        }
290    }
291
292    if ( $arg->{'suspended'} ) {
293        $body .= qq(  <apps:login userName="$arg->{'username'}" suspended="$arg->{'suspended'}" />\n);
294    }
295
296    if ( $arg->{'admin'} ) {
297        $body .= qq(  <apps:login userName="$arg->{'username'}" admin="$arg->{'admin'}" />\n);
298    }
299
300    $body .= $self->_xmlpost();
301
302    my $result = $self->_request(
303        'method' => 'PUT',
304        'url'    => $url,
305        'body'   => $body
306    ) || return( 0 );
307
308    return( 1 );
309}
310
311
312
313sub createGroup {
314    my $self  = shift;
315
316    my ( $arg );
317    %{$arg} = @_;
318
319    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
320
321    foreach my $param ( qw/ group / ) {
322        $arg->{$param} || croak( "Missing required '$param' argument" );
323    }
324
325    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'});
326
327    my ( $body );
328
329    $body  = $self->_xmlpre();
330
331    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#group" />\n);
332    $body .= qq(  <apps:property name="groupId" value="$arg->{'group'}\@$self->{'domain'}" />\n);
333    $body .= qq(  <apps:property name="groupName" value="$arg->{'group'}" />\n);
334
335    if ( $arg->{'description'} ) {
336        $body .= qq( <apps:property name="description" value="$arg->{'description'}"></apps:property> \n);
337    }
338
339    if ( $arg->{'permission'} ) {
340        $arg->{'permission'} = ucfirst( lc( $arg->{'permission'} ) );
341        $body .= qq( <apps:property name="emailPermission" value="$arg->{'permission'}"></apps:property> \n);
342    }
343
344    $body .= $self->_xmlpost();
345
346    my $result = $self->_request(
347        'method' => 'POST',
348        'url'    => $url,
349        'body'   => $body
350    ) || return( 0 );
351
352    my ( $ref );
353
354    foreach ( keys %{$result->{'apps:property'}} ) {
355        $ref->{$arg->{'group'}}->{$_} = $result->{'apps:property'}->{$_}->{'value'};
356    }
357
358    $ref->{$arg->{'group'}}->{'updated'} = $result->{'updated'};
359
360    return( $ref );
361}
362
363sub deleteGroup {
364    my $self = shift;
365
366    my ( $arg );
367    %{$arg} = @_;
368
369    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
370
371    foreach my $param ( qw/ group / ) {
372        $arg->{$param} || croak( "Missing required '$param' argument" );
373    }
374
375    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'});
376
377    my $result = $self->_request( 'method' => 'DELETE', 'url' => $url ) || return( 0 );
378
379    return( 1 ) if $result;
380}
381
382sub getGroup {
383    my $self  = shift;
384
385    my ( $arg );
386    %{$arg} = @_;
387
388    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
389
390    foreach my $param ( qw/ group / ) {
391        $arg->{$param} || croak( "Missing required '$param' argument" );
392    }
393
394    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'});
395
396    my $result = $self->_request( 'method' => 'GET', 'url' => $url ) || return( 0 );
397
398    my ( $ref );
399
400    foreach ( keys %{$result->{'apps:property'}} ) {
401        $ref->{$arg->{'group'}}->{$_} = $result->{'apps:property'}->{$_}->{'value'};
402    }
403
404    $ref->{$arg->{'group'}}->{'updated'} = $result->{'updated'};
405
406    return( $ref );
407}
408
409sub getAllGroups {
410    my $self  = shift;
411
412    my ( @url, $result, $ref );
413
414    push @url, qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'});
415
416    foreach my $u ( @url ) {
417        $result = $self->_request( 'method' => 'GET', 'url' => $u ) || return( 0 );
418
419        foreach my $link ( @{$result->{'link'}} ) {
420            if ( $link->{'rel'} eq 'next' ) {
421                push @url, $link->{'href'};
422            }
423        }
424
425        if ( $result->{'entry'}->{'apps:property'} ) {
426             my $group = $result->{'entry'}->{'apps:property'}->{'groupName'}->{'value'};
427
428            foreach ( keys %{$result->{'entry'}->{'apps:property'}} ) {
429                $ref->{$group}->{$_} = $result->{'entry'}->{'apps:property'}->{$_}->{'value'};
430            }
431
432            $ref->{$group}->{'updated'} = $result->{'entry'}->{'updated'};
433        }
434        else {
435            foreach my $e ( keys %{$result->{'entry'}} ) {
436                my $group = $result->{'entry'}->{$e}->{'apps:property'}->{'groupName'}->{'value'};
437
438                foreach ( keys %{$result->{'entry'}->{$e}->{'apps:property'}} ) {
439                    $ref->{$group}->{$_} = $result->{'entry'}->{$e}->{'apps:property'}->{$_}->{'value'};
440                }
441
442                $ref->{$group}->{'updated'} = $result->{'entry'}->{$e}->{'updated'};
443            }
444        }
445    }
446
447    return( $ref );
448}
449
450sub addGroupMember {
451    my $self = shift;
452
453    my ( $arg );
454    %{$arg} = @_;
455
456    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
457
458    foreach my $param ( qw/ group member / ) {
459        $arg->{$param} || croak( "Missing required '$param' argument" );
460    }
461
462    $arg->{'member'} .= '@' . $self->{'domain'} unless ( $arg->{'member'} =~ /[@]/ );
463
464    if ( $arg->{'owner'} && lc( $arg->{'owner'} ) eq 'true' ) {
465        return $self->addGroupOwner(
466            group => $arg->{'group'},
467            owner => $arg->{'member'}
468        );
469    }
470
471    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/member);
472
473    my ( $body );
474
475    $body  = $self->_xmlpre();
476
477    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#group" />\n);
478    $body .= qq(  <apps:property name="groupId" value="$arg->{'group'}\@$self->{'domain'}" />\n);
479    $body .= qq(  <apps:property name="memberId" value="$arg->{'member'}" />\n);
480
481    $body .= $self->_xmlpost();
482
483    my $result = $self->_request(
484        'method' => 'POST',
485        'url'    => $url,
486        'body'   => $body
487    ) || return( 0 );
488
489    return( 1 );
490}
491
492sub deleteGroupMember {
493    my $self = shift;
494
495    my ( $arg );
496    %{$arg} = @_;
497
498    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
499
500    foreach my $param ( qw/ group member / ) {
501        $arg->{$param} || croak( "Missing required '$param' argument" );
502    }
503
504    $arg->{'member'} .= '@' . $self->{'domain'} unless ( $arg->{'member'} =~ /[@]/ );
505
506    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/member/$arg->{'member'});
507
508    my $result = $self->_request( 'method' => 'DELETE', 'url' => $url ) || return( 0 );
509
510    return( 1 ) if $result;
511}
512
513sub getGroupMember {
514    # Not yet implemented
515}
516
517sub getGroupMembers {
518    my $self = shift;
519
520    my ( $arg );
521    %{$arg} = @_;
522
523    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
524
525    foreach my $param ( qw/ group / ) {
526        $arg->{$param} || croak( "Missing required '$param' argument" );
527    }
528
529    my ( @url, $result, $ref );
530
531    push @url, qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/member);
532
533    foreach my $u ( @url ) {
534        $result = $self->_request( 'method' => 'GET', 'url' => $u ) || return( 0 );
535
536        foreach my $link ( @{$result->{'link'}} ) {
537            if ( $link->{'rel'} eq 'next' ) {
538                push @url, $link->{'href'};
539            }
540        }
541
542        if ( $result->{'entry'}->{'apps:property'} ) {
543            my $member = $result->{'entry'}->{'apps:property'}->{'memberId'}->{'value'};
544            $member =~ s/^(.*)\@\Q$self->{'domain'}\E$/$1/g;
545
546            foreach ( keys %{$result->{'entry'}->{'apps:property'}} ) {
547                $ref->{$member}->{$_} = $result->{'entry'}->{'apps:property'}->{$_}->{'value'};
548            }
549        }
550        else {
551            foreach my $e ( keys %{$result->{'entry'}} ) {
552                my $member = $result->{'entry'}->{$e}->{'apps:property'}->{'memberId'}->{'value'};
553                $member =~ s/^(.*)\@.*$/$1/g;
554
555                foreach ( keys %{$result->{'entry'}->{$e}->{'apps:property'}} ) {
556                    $ref->{$member}->{$_} = $result->{'entry'}->{$e}->{'apps:property'}->{$_}->{'value'};
557                }
558            }
559        }
560    }
561
562    return( $ref );
563}
564
565sub addGroupOwner {
566    my $self = shift;
567
568    my ( $arg );
569    %{$arg} = @_;
570
571    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
572
573    foreach my $param ( qw/ group owner / ) {
574        $arg->{$param} || croak( "Missing required '$param' argument" );
575    }
576
577    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/owner);
578
579    my ( $body );
580
581    $body  = $self->_xmlpre();
582
583    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#group" />\n);
584    $body .= qq(  <apps:property name="groupId" value="$arg->{'group'}\@$self->{'domain'}" />\n);
585    $body .= qq(  <apps:property name="email" value="$arg->{'owner'}\@$self->{'domain'}" />\n);
586
587    $body .= $self->_xmlpost();
588
589    my $result = $self->_request(
590        'method' => 'POST',
591        'url'    => $url,
592        'body'   => $body
593    ) || return( 0 );
594
595    return( 1 );
596}
597
598sub deleteGroupOwner {
599    my $self = shift;
600
601    my ( $arg );
602    %{$arg} = @_;
603
604    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
605
606    foreach my $param ( qw/ group owner / ) {
607        $arg->{$param} || croak( "Missing required '$param' argument" );
608    }
609
610    my $url = qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/owner/$arg->{'owner'});
611
612    my $result = $self->_request( 'method' => 'DELETE', 'url' => $url ) || return( 0 );
613
614    return( 1 ) if $result;
615}
616
617sub getGroupOwner {
618    # Not yet implemented
619}
620
621sub getGroupOwners {
622    my $self = shift;
623
624    my ( $arg );
625    %{$arg} = @_;
626
627    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
628
629    foreach my $param ( qw/ group / ) {
630        $arg->{$param} || croak( "Missing required '$param' argument" );
631    }
632
633    my ( @url, $result, $ref );
634
635    push @url, qq(https://apps-apis.google.com/a/feeds/group/2.0/$self->{'domain'}/$arg->{'group'}/owner);
636
637    foreach my $u ( @url ) {
638        $result = $self->_request( 'method' => 'GET', 'url' => $u ) || return( 0 );
639
640        foreach my $link ( @{$result->{'link'}} ) {
641            if ( $link->{'rel'} eq 'next' ) {
642                push @url, $link->{'href'};
643            }
644        }
645
646        if ( $result->{'entry'}->{'apps:property'} ) {
647            my $owner = $result->{'entry'}->{'apps:property'}->{'email'}->{'value'};
648            $owner =~ s/^(.*)\@.*$/$1/g;
649
650            foreach ( keys %{$result->{'entry'}->{'apps:property'}} ) {
651                $ref->{$owner}->{$_} = $result->{'entry'}->{'apps:property'}->{$_}->{'value'};
652            }
653        }
654        else {
655            foreach my $e ( keys %{$result->{'entry'}} ) {
656                my $owner = $result->{'entry'}->{$e}->{'apps:property'}->{'email'}->{'value'};
657                $owner =~ s/^(.*)\@.*$/$1/g;
658
659                foreach ( keys %{$result->{'entry'}->{$e}->{'apps:property'}} ) {
660                    $ref->{$owner}->{$_} = $result->{'entry'}->{$e}->{'apps:property'}->{$_}->{'value'};
661                }
662            }
663        }
664    }
665
666    return( $ref );
667}
668
669
670
671sub createNickname {
672    my $self = shift;
673
674    my ( $arg );
675    %{$arg} = @_;
676
677    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
678
679    foreach my $param ( qw/ username nickname / ) {
680        $arg->{$param} || croak( "Missing required '$param' argument" );
681    }
682
683    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/nickname/2.0);
684
685    my ( $body );
686
687    $body  = $self->_xmlpre();
688
689    $body .= qq(  <atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/apps/2006#nickname" />\n);
690    $body .= qq(  <apps:login userName="$arg->{'username'}" />\n);
691    $body .= qq(  <apps:nickname name="$arg->{'nickname'}" />\n);
692
693    $body .= $self->_xmlpost();
694
695    my $result = $self->_request(
696        'method' => 'POST',
697        'url'    => $url,
698        'body'   => $body
699    ) || return( 0 );
700
701    my ( $ref );
702
703    $ref->{$arg->{'username'}} = {
704        %{$result->{'apps:nickname'}}
705    };
706
707    return( $ref );
708}
709
710sub deleteNickname {
711    my $self = shift;
712
713    my ( $arg );
714    %{$arg} = @_;
715
716    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
717
718    foreach my $param ( qw/ nickname / ) {
719        $arg->{$param} || croak( "Missing required '$param' argument" );
720    }
721
722    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/nickname/2.0/$arg->{'nickname'});
723
724    my $result = $self->_request( 'method' => 'DELETE', 'url' => $url ) || return( 0 );
725
726    return( 1 ) if $result;
727}
728
729sub getNickname {
730    my $self = shift;
731
732    my ( $arg );
733    %{$arg} = @_;
734
735    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
736
737    foreach my $param ( qw/ nickname / ) {
738        $arg->{$param} || croak( "Missing required '$param' argument" );
739    }
740
741    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/nickname/2.0/$arg->{'nickname'});
742
743    my $result = $self->_request( 'method' => 'GET', 'url' => $url ) || return( 0 );
744
745    my ( $ref );
746
747    unless ( $arg->{'nickname'} ) {
748        foreach ( keys %{$result->{'entry'}} ) {
749            $arg->{'nickname'} = $1 if /^.*\/(.+)$/;
750            $ref->{$arg->{'nickname'}} = {
751                %{$result->{'entry'}->{$_}->{'apps:login'}},
752                %{$result->{'entry'}->{$_}->{'apps:nickname'}}
753            }
754        }
755    }
756    else {
757        $ref->{$arg->{'nickname'}} = {
758            %{$result->{'apps:login'}},
759            %{$result->{'apps:nickname'}}
760        };
761    }
762
763    return( $ref );
764}
765
766sub getUserNicknames {
767    my $self = shift;
768
769    my ( $arg );
770    %{$arg} = @_;
771
772    map { $arg->{lc($_)} = $arg->{$_} } keys %{$arg};
773
774    foreach my $param ( qw/ username / ) {
775        $arg->{$param} || croak( "Missing required '$param' argument" );
776    }
777
778    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/nickname/2.0?username=$arg->{'username'});
779
780    my $result = $self->_request( 'method' => 'GET', 'url' => $url )
781    || return( 0 );
782
783    my ( $ref, $nickname );
784
785    $nickname = $result->{'entry'}->{'apps:nickname'}->{'name'};
786
787    if ( $nickname ) {
788        $ref->{$nickname} = {
789            %{$result->{'entry'}->{'apps:login'}},
790            %{$result->{'entry'}->{'apps:nickname'}}
791        };
792    }
793    else {
794        foreach ( keys %{$result->{'entry'}} ) {
795            if ( /^.*\/(.+)$/ ) {
796                $nickname = $1;
797            }
798            else { next; }
799
800            next if $ref->{$nickname};
801
802            $ref->{$nickname} = {
803                %{$result->{'entry'}->{$_}->{'apps:login'}},
804                %{$result->{'entry'}->{$_}->{'apps:nickname'}}
805            };
806        }
807    }
808
809    return( $ref );
810}
811
812sub getAllNicknames {
813    my $self = shift;
814
815    my $url = qq(https://apps-apis.google.com/a/feeds/$self->{'domain'}/nickname/2.0/);
816
817    my $result = $self->_request( 'method' => 'GET', 'url' => $url )
818    || return( 0 );
819
820    my ( $ref, $nickname );
821
822    foreach ( keys %{$result->{'entry'}} ) {
823        $nickname = $1 if /^.*\/(.+)$/;
824        $ref->{$nickname} = {
825            %{$result->{'entry'}->{$_}->{'apps:login'}},
826            %{$result->{'entry'}->{$_}->{'apps:nickname'}}
827        }
828    }
829
830    return( $ref );
831}
832
833
834
835sub _request {
836    my $self = shift;
837
838    $self->{'token'}
839    || croak qq(Authenticate first!);
840
841    my ( $arg );
842    %{$arg} = @_;
843
844    my $request = HTTP::Request->new( $arg->{'method'} => $arg->{'url'} );
845
846    $request->header( 'Content-Type'  => 'application/atom+xml' );
847    $request->header( 'Authorization' => 'GoogleLogin auth=' . $self->{'token'} );
848
849    if ( $arg->{'body'} ) {
850        $request->header( 'Content-Length' => length( $arg->{'body'} ) );
851        $request->content( $arg->{'body'} );
852    }
853
854    my $response = $self->{'lwp'}->request( $request );
855
856    $response->is_success() || return( 0 );
857    $response->content()    || return( 1 );
858
859    return( $self->{'xml'}->XMLin( $response->content() ) );
860}
861
862
863
864sub _xmlpre {
865    ( my $xml = << '    END' ) =~ s/^\s+//gm;
866        <?xml version="1.0" encoding="UTF-8" ?>
867        <atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:apps="http://schemas.google.com/apps/2006">
868    END
869
870    return( $xml );
871}
872
873sub _xmlpost {
874    ( my $xml = << '    END' ) =~ s/^\s+//gm;
875        </atom:entry>
876    END
877
878    return( $xml );
879}
880
881
882
8831;
884
885