http://code.google.com/p/vuser/source/detail?r=579
Added:
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Groups
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Groups/V2_0.pm
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Groups.pm
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning/UserEntry.pm
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning/V2_0.pm
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning.pm
/VUser-Google-ProvisioningAPI/trunk/t/tests
/VUser-Google-ProvisioningAPI/trunk/t/tests/My
/VUser-Google-ProvisioningAPI/trunk/t/tests/My/Test
/VUser-Google-ProvisioningAPI/trunk/t/tests/My/Test/Class.pm
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google/Provisioning
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google/Provisioning/V2_0.pm
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google/Provisioning.pm
Modified:
/VUser-Google-ProvisioningAPI/trunk/t/run.t
=======================================
--- /dev/null
+++ /VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Groups/V2_0.pm Tue
Nov 17 23:17:24 2009
@@ -0,0 +1,53 @@
+use VUser::Google::Groups::V2_0;
+use warnings;
+use strict;
+
+our $VERSION = '0.2.0';
+
+use Moose;
+extends 'VUser::Google::Groups';
+
+has '+base_url' => (default
=> 'https://apps-api.google.com/a/feeds/group/2.0/');
+
+#### Methods ####
+sub CreateGroup {
+}
+
+sub UpdateGroup {
+}
+
+sub RetrieveGroup {
+}
+
+sub RetrieveAllGroupsInDomain {
+}
+
+sub RetrieveAllGroupsForMember {
+}
+
+sub DeleteGroup {
+}
+
+sub AddMemberToGroup {
+}
+
+sub RetrieveAllMembersOfGroup {
+}
+
+sub RetrieveMemberOfGroup {
+}
+
+sub RemoveMemberOfGroup {
+}
+
+sub AddOwnerToGroup {
+}
+
+sub RetrieveAllOwnersOfGroup {
+}
+
+sub RemoveOwnerFromGroup {
+}
+
+
+1;
=======================================
--- /dev/null
+++ /VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Groups.pm Tue Nov
17 23:17:24 2009
@@ -0,0 +1,39 @@
+use VUser::Google::Groups;
+use warnings;
+use strict;
+
+our $VERSION = '0.2.0';
+
+use Moose;
+
+has 'google' => (
+ is => 'rw',
+ isa => 'VUser::Google::ApiProtocol',
+ required => 1
+);
+
+has base_url => (is => 'rw', isa => 'Str');
+
+# Turn on deugging
+has 'debug' => (is => 'rw', default => 0);
+
+#### Methods
+
+## Util
+#print out debugging to STDERR if debug is set
+sub dprint
+{
+ my $self = shift;
+ my $text = shift;
+ my @args = @_;
+ if( $self->debug and defined ($text) ) {
+ print STDERR sprintf ("$text\n", @args);
+ }
+}
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;
+
+__END__
=======================================
--- /dev/null
+++
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning/UserEntry.pm
Tue Nov 17 23:17:24 2009
@@ -0,0 +1,38 @@
+package VUser::Google::Provisioning::UserEntry;
+use warnings;
+use strict;
+
+our $VERSION = '0.2.0';
+
+use Moose;
+
+has 'UserName' => (is => 'rw', isa => 'Str');
+has 'GivenName' => (is => 'rw', isa => 'Str');
+has 'FamilyName' => (is => 'rw', isa => 'Str');
+has 'Password' => (is => 'rw', isa => 'Str');
+has 'HashFunctionName' => (is => 'rw', isa => 'Str');
+has 'Suspended' => (is => 'rw', isa => 'Bool');
+has 'Quota' => (is => 'rw', isa => 'Int');
+has 'ChangePasswordAtNextLogin' => (is => 'rw', isa => 'Bool');
+
+sub as_hash {
+ my $self = shift;
+
+ my %hash = (
+ userName => $self->UserName,
+ givenName => $self->GivenName,
+ familyName => $self->FamilyName,
+ password => $self->Password,
+ hashFunctionName => $self->HashFunctionName,
+ suspended => $self->Suspended,
+ quota => $self->Quota,
+ changePasswordAtNextLogin => $self->ChangePasswordAtNextLogin,
+ );
+
+ return %hash;
+}
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;
=======================================
--- /dev/null
+++
/VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning/V2_0.pm
Tue Nov 17 23:17:24 2009
@@ -0,0 +1,199 @@
+package VUser::Google::Provisioning::V2_0;
+use warnings;
+use strict;
+
+our $VERSION = '0.2.0';
+
+use Moose;
+extends 'VUser::Google::Provisioning';
+
+use VUser::Google::Provisioning::UserEntry;
+
+has '+base_url' => (default => 'https://apps-apis.google.com/a/feeds/');
+
+#### Methods ####
+## Users
+#
+# %options
+# userName*
+# givenName*
+# familyName*
+# password*
+# hashFunctioName (SHA-1|MD5)
+# suspended (bool)
+# quota (in MB)
+# changePasswordAtNextLogin (bool)
+sub CreateUser {
+ my $self = shift;
+
+ my %options = ();
+
+ if (ref $_[0]
+ and $_[0]->isa('VUser::Google::Provisioning::UserEntry')) {
+ %options = $_[0]->as_hash;
+ }
+ else {
+ %options = @_;
+ }
+
+ $self->google()->Login();
+ my $url = $self->base_url.$self->google->domain.'/user/2.0';
+
+ my $post = '<?xml version="1.0" encoding="UTF-8"?>
+<atom:entry xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns:apps="http://schemas.google.com/apps/2006">
+ <atom:category scheme="http://schemas.google.com/g/2005#kind"
+ term="http://schemas.google.com/apps/2006#user"/>
+';
+
+ ## login
+ $post .= '<apps:login ';
+ $post .= " userName=\"$options{'userName'}\"";
+
+ $post .= " password=\""
+ .$self->_escape_quotes($options{'password'})."\"";
+
+ if ($options{hashFunctionName}) {
+ $post .= " hashFunctionName=\"$options{hashFunctionName}\"";
+ }
+
+ if ($options{suspended}) {
+ $post .= ' suspended="'.$self->_as_bool($options{suspended}).'"';
+ }
+
+ if ($options{changePasswordAtNextLogin}) {
+ $post .= ' changePasswordAtNextLogin="'
+ .$self->_as_bool($options{changePasswordAtNextLogin}).'"';
+ }
+
+ $post .= '/>';
+
+ ## quota
+ if ($options{quota}) {
+ $post .= "<apps:quota limit=\"$options{quota}\"/>";
+ }
+
+ ## name
+ $post .= '<apps:name';
+ $post .= " familyName=\"$options{familyName}\"";
+ $post .= " givenName=\"$options{givenName}\"";
+ $post .= '/>';
+
+ $post .= '</atom:entry>';
+
+ if ($self->google->Request('POST', $url, $post)) {
+ ## build UserEntry
+ $self->dprint('Created user');
+ my $entry = $self->_build_user_entry($self->google->result);
+ return $entry;
+ }
+ else {
+ ## ERROR!
+ $self->dprint('CreateUser failed: '.$self->google->result->{reason});
+ return undef;
+ }
+}
+
+sub RetrieveUser {
+ my $self = shift;
+ my $username = shift;
+
+ my $url = $self->base_url.$self->google->domain.'/user/2.0/'.$username;
+
+ if ($self->google->Request('GET', $url)) {
+ return $self->_build_user_entry($self->google->get_result);
+ }
+ else {
+ return undef;
+ }
+}
+
+sub RetrieveAllUsers {
+}
+
+sub UpdateUser {
+}
+
+sub RenameUser {
+}
+
+sub DeleteUser {
+ my $self = shift;
+ my $user;
+
+ if (ref $_[0] and
$_[0]->isa('VUser::Google::Provisioning::UserEntry')) {
+ $user = $_[0]->UserName
+ }
+ else {
+ $user = $_[0];
+ }
+
+ my $url = $self->base_url.$self->google->domain.'/user/2.0/'.$user;
+
+ if ($self->google->Request('DELETE', $url)) {
+ return 1;
+ }
+ else {
+ return undef;
+ }
+}
+
+sub ChangePassword {
+}
+
+## Nicknames
+sub CreateNickname {
+}
+
+sub RetrieveNickname {
+}
+
+sub RetrieveAllNicknamesForUser {
+}
+
+sub RetrieveAllNicknamesInDomain {
+}
+
+sub DeleteNickname {
+}
+
+# Takes the parsed XML object
+sub _build_user_entry {
+ my $self = shift;
+ my $xml = shift;
+
+ my $entry = VUser::Google::Provisioning::UserEntry->new();
+
+ $entry->UserName($xml->{'apps:login'}[0]{'userName'});
+
+ if ($xml->{'apps:login'}[0]{'suspended'}) {
+ if ($xml->{'apps:login'}[0]{'suspended'} eq 'true') {
+ $entry->Suspended(1);
+ }
+ else {
+ $entry->Suspended(0);
+ }
+ }
+
+ if ($xml->{'apps:login'}[0]{'changePasswordAtNextLogin'}) {
+ if ($xml->{'apps:login'}[0]{'changePasswordAtNextLogin'} eq 'true') {
+ $entry->ChangePasswordAtNextLogin(1);
+ }
+ else {
+ $entry->ChangePasswordAtNextLogin(0);
+ }
+ }
+
+ $entry->FamilyName($xml->{'apps:name'}[0]{'familyName'});
+ $entry->GivenName($xml->{'apps:name'}[0]{'givenName'});
+ $entry->Quota($xml->{'apps:quota'}[0]{'limit'});
+
+ return $entry;
+}
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;
+
+__END__
=======================================
--- /dev/null
+++ /VUser-Google-ProvisioningAPI/trunk/lib/VUser/Google/Provisioning.pm
Tue Nov 17 23:17:24 2009
@@ -0,0 +1,57 @@
+package VUser::Google::Provisioning;
+use warnings;
+use strict;
+
+our $VERSION = '0.2.0';
+
+use Moose;
+
+has 'google' => (
+ is => 'rw',
+ isa => 'VUser::Google::ApiProtocol',
+ required => 1
+);
+
+has 'base_url' => (is => 'rw', isa => 'Str');
+
+# Turn on deugging
+has 'debug' => (is => 'rw', default => 0);
+
+#### Methods
+
+## Util
+#print out debugging to STDERR if debug is set
+sub dprint
+{
+ my $self = shift;
+ my $text = shift;
+ my @args = @_;
+ if( $self->debug and defined ($text) ) {
+ print STDERR sprintf ("$text\n", @args);
+ }
+}
+
+# Escape " with " for XML
+sub _escape_quotes {
+ my $self = shift;
+ my $text = shift;
+
+ $text =~ s/\"/"/;
+
+ return $text;
+}
+
+# Replace 1 with 'true' other with 0
+sub _as_bool {
+ my $self = shift;
+ my $value = shift;
+
+ return $value ? 'true' : 'false';
+}
+
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
+1;
+
+__END__
=======================================
--- /dev/null
+++ /VUser-Google-ProvisioningAPI/trunk/t/tests/My/Test/Class.pm Tue Nov 17
23:17:24 2009
@@ -0,0 +1,36 @@
+package My::Test::Class;
+use warnings;
+use strict;
+
+use Test::Most;
+use base qw(Test::Class Class::Data::Inheritable);
+
+BEGIN {
+ __PACKAGE__->mk_classdata('class');
+}
+
+INIT {
+ Test::Class->runtests;
+}
+
+sub startup : Tests( startup => 1 ) {
+ my $test = shift;
+ ( my $class = ref $test ) =~ s/^Test:://;
+ return ok 1, "$class loaded" if $class eq __PACKAGE__;
+ use_ok $class or die;
+ $test->class($class);
+}
+
+sub create_google {
+ use VUser::Google::ApiProtocol::V2_0;
+ my $google = VUser::Google::ApiProtocol::V2_0->new(
+ domain => $ENV{GAPPS_DOMAIN},
+ admin => $ENV{GAPPS_ADMIN},
+ password => $ENV{GAPPS_PASSWD},
+# debug => 1
+ );
+
+ return $google;
+}
+
+1;
=======================================
--- /dev/null
+++
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google/Provisioning/V2_0.pm
Tue Nov 17 23:17:24 2009
@@ -0,0 +1,35 @@
+package Test::VUser::Google::Provisioning::V2_0;
+use warnings;
+use strict;
+
+use Test::Most;
+use base 'Test::VUser::Google::Provisioning';
+
+sub CreateUser : Tests(3) {
+ my $test = shift;
+ my $class = $test->class;
+
+ my $api = $class->new(google => $test->create_google);
+ can_ok $api, 'CreateUser';
+
+ my $user = $test->get_test_user;
+
+ my $res = $api->CreateUser(
+ userName => $user,
+ givenName => 'Test',
+ familyName => 'User',
+ password => 'testing',
+ quota => 2048,
+ changePasswordAtNextLogin => 1,
+ );
+
+ isa_ok $res, 'VUser::Google::Provisioning::UserEntry',
+ '... and the account was created';
+
+ is $res->UserName, $user, "... and the username is $user";
+
+ # clean up
+ $api->DeleteUser($res->UserName);
+}
+
+1;
=======================================
--- /dev/null
+++
/VUser-Google-ProvisioningAPI/trunk/t/tests/Test/VUser/Google/Provisioning.pm
Tue Nov 17 23:17:24 2009
@@ -0,0 +1,39 @@
+package Test::VUser::Google::Provisioning::V2_0;
+use warnings;
+use strict;
+
+use Test::Most;
+use base 'My::Test::Class';
+
+my $acct;
+
+sub constructor : Tests(3) {
+ my $test = shift;
+ my $class = $test->class;
+
+ can_ok $class, 'new';
+ ok my $api = $class->new(google => $test->create_google),
+ '... and the constructor should succeed';
+ isa_ok $api, $class, '... and the object it returns';
+}
+
+sub get_test_user {
+ my $self = shift;
+
+ if (1 || not defined $acct) {
+ my @time = localtime;
+ $acct = sprintf (
+ 'test.%04d.%02d.%02d.%02d.%02d.%02d',
+ $time[5]+1900,
+ $time[4]+1,
+ $time[3],
+ $time[2],
+ $time[1],
+ $time[0]
+ );
+ }
+
+ return $acct;
+}
+
+1;
=======================================
--- /VUser-Google-ProvisioningAPI/trunk/t/run.t Sat Nov 14 16:24:16 2009
+++ /VUser-Google-ProvisioningAPI/trunk/t/run.t Tue Nov 17 23:17:24 2009
@@ -8,7 +8,7 @@
use lib ("$FindBin::Bin/../lib");
my $gapps_domain = $ENV{GAPPS_DOMAIN};
-my $gapps_user = $ENV{GAPPS_USER};
+my $gapps_user = $ENV{GAPPS_ADMIN};
my $gapps_passwd = $ENV{GAPPS_PASSWD};
if (not $gapps_domain