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