[Bps-public-commit] storage-box branch, master, updated. 7a3e76537dda8fc29a6eba3d7251305e56c24608
Dave Goehrig
dave at bestpractical.com
Thu Sep 1 13:14:09 EDT 2016
The branch, master has been updated
via 7a3e76537dda8fc29a6eba3d7251305e56c24608 (commit)
via da0519c18509939412b7def70de167786bb1db2c (commit)
from eecf8c1b68bf18b3c1b61109178f3fc669f4753f (commit)
Summary of changes:
Build.PL | 2 +-
META.json | 11 ++-
README.md | 36 +++++++-
cpanfile | 4 +-
lib/Storage/Box.pm | 201 ++++++++++++++++++++++++++++++++++++++++++++-
lib/Storage/Box/Auth.pm | 171 +++++++++++++++++++++-----------------
lib/Storage/Box/File.pm | 108 ++++++++++++++++++++++++
lib/Storage/Box/Folder.pm | 108 ++++++++++++++++++++++++
lib/Storage/Box/Request.pm | 136 ++++++++++++++++++++++++++++++
lib/Storage/Box/User.pm | 165 +++++++++++++++++++++++++++++++++++++
scripts/auth_enterprise.pl | 18 ++++
scripts/auth_user.pl | 18 ++++
scripts/create_file.pl | 28 +++++++
scripts/create_user.pl | 30 +++++++
scripts/delete_file.pl | 26 ++++++
scripts/delete_user.pl | 28 +++++++
scripts/read_user.pl | 28 +++++++
scripts/update_user.pl | 28 +++++++
18 files changed, 1062 insertions(+), 84 deletions(-)
create mode 100644 lib/Storage/Box/File.pm
create mode 100644 lib/Storage/Box/Folder.pm
create mode 100644 lib/Storage/Box/Request.pm
create mode 100644 lib/Storage/Box/User.pm
create mode 100644 scripts/auth_enterprise.pl
create mode 100644 scripts/auth_user.pl
create mode 100644 scripts/create_file.pl
create mode 100644 scripts/create_user.pl
create mode 100644 scripts/delete_file.pl
create mode 100644 scripts/delete_user.pl
create mode 100644 scripts/read_user.pl
create mode 100644 scripts/update_user.pl
- Log -----------------------------------------------------------------
commit da0519c18509939412b7def70de167786bb1db2c
Author: Dave Goehrig <dave at bestpractical.com>
Date: Thu Aug 25 16:18:19 2016 +0000
manage user objects
diff --git a/META.json b/META.json
index c539095..4acac45 100644
--- a/META.json
+++ b/META.json
@@ -38,7 +38,9 @@
"runtime" : {
"requires" : {
"Crypt::JWT" : "0.017",
+ "Data::UUID" : "1.221",
"Expect" : "1.15",
+ "HTTP::Request" : "6.11",
"Modern::Perl" : "1.20150127",
"perl" : "5.008005"
}
@@ -50,6 +52,17 @@
}
},
"release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "web" : "https://github.com/cthulhuology/Storage-Box/issues"
+ },
+ "homepage" : "https://github.com/cthulhuology/Storage-Box",
+ "repository" : {
+ "type" : "git",
+ "url" : "https://github.com/cthulhuology/Storage-Box.git",
+ "web" : "https://github.com/cthulhuology/Storage-Box"
+ }
+ },
"version" : "0.01",
"x_contributors" : [
"Dave Goehrig <dave at bestpractical.com>"
diff --git a/README.md b/README.md
index 856bf39..7b26244 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@ Storage::Box - Blah blah blah
Storage::Box is
+# METHODS
+
# AUTHOR
Dave Goehrig <dave at dloh.org>
diff --git a/auth_enterprise.pl b/auth_enterprise.pl
new file mode 100644
index 0000000..ed99e77
--- /dev/null
+++ b/auth_enterprise.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+#
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+
+my $enterprise_id = $ARGV[0] || '2064336';
+print "Authorizing $enterprise_id\n";
+
+my $jwt = Storage::Box::Auth::enterprise(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$enterprise_id");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+print $res->{access_token}, "\n";
diff --git a/auth_user.pl b/auth_user.pl
new file mode 100644
index 0000000..cc9882d
--- /dev/null
+++ b/auth_user.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+#
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Data::Dumper;
+
+print "Authorizing $ARGV[0]\n";
+
+my $jwt = Storage::Box::Auth::user(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$ARGV[0]");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+print $res->{access_token}, "\n";
diff --git a/cpanfile b/cpanfile
index 909e1f0..19ad9ad 100644
--- a/cpanfile
+++ b/cpanfile
@@ -5,6 +5,8 @@ requires 'Crypt::JWT', '0.017';
requires 'Expect', '1.15';
requires 'Data::UUID', '1.221';
requires 'HTTP::Request', '6.11';
+requires 'Crypt::OpenSSL::RSA', '0.28';
+requires 'Crypt::PK::RSA';
on test => sub {
requires 'Test::More', '0.96';
diff --git a/create_user.pl b/create_user.pl
new file mode 100644
index 0000000..65e1874
--- /dev/null
+++ b/create_user.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($username,$enterprise_id) = @ARGV;
+$enterprise_id ||= 2064336;
+
+my $jwt = Storage::Box::Auth::enterprise(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$enterprise_id");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+my $token = $res->{access_token};
+
+my $user = Storage::Box::User::create($token,$username);
+
+print $user->{id}, "\n";
diff --git a/delete_user.pl b/delete_user.pl
new file mode 100644
index 0000000..ce483e1
--- /dev/null
+++ b/delete_user.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id) = @ARGV;
+$enterprise_id ||= 2064336;
+
+my $jwt = Storage::Box::Auth::enterprise(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$enterprise_id");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+my $token = $res->{access_token};
+
+my $response = Storage::Box::User::delete($token,$user_id);
+
+print $response ? "ok\n": "failed\n";
diff --git a/lib/Storage/Box/Auth.pm b/lib/Storage/Box/Auth.pm
index 70b9b99..944971d 100644
--- a/lib/Storage/Box/Auth.pm
+++ b/lib/Storage/Box/Auth.pm
@@ -31,6 +31,8 @@ use Expect;
use Data::UUID;
use HTTP::Request;
use LWP::UserAgent;
+use Crypt::PK::RSA;
+use JSON qw/ decode_json /;
=pod
@@ -117,15 +119,14 @@ B<private_key($keyfile)>
=cut
sub private_key {
- my ($keyfile) = @_;
- open my $fh, "< $keyfile" or die "Failed to open $keyfile\n";
- local $/ = undef;
- Crypt::OpenSSL::RSA->new_private_key(<$fh>);
+ my ($keyfile,$password) = @_;
+ print "opening $keyfile with $password\n";
+ Crypt::PK::RSA->new($keyfile,$password);
}
=pod
-B<enterprise($password,$kid,$keyfile,$clientid,$entperpriseid)>
+B<enterprise($kid,$keyfile,$password,$clientid,$entperpriseid)>
Creates a JWT assertion for an enterprise account.
@@ -138,22 +139,23 @@ B<enterprise($password,$kid,$keyfile,$clientid,$entperpriseid)>
=cut
sub enterprise {
- my ($password,$kid,$keyfile,$clientid,$entperpriseid) = @_;
+ my ($kid,$keyfile,$password,$clientid,$enterpriseid) = @_;
my $ug = Data::UUID->new;
my $jti = $ug->to_b64string($ug->create);
+ my $time = time;
my %claims = (
iss => $clientid,
sub => $enterpriseid,
box_sub_type => "enterprise",
aud => "https://api.box.com/oauth2/token",
+ exp => $time + 60,
+ iat => $time,
jti => $jti
);
Crypt::JWT::encode_jwt(
alg => "RS256",
payload => \%claims,
- auto_iat => 1,
- relative_exp =>1,
- key => private_key($keyfile),
+ key => $keyfile,
keypass => $password,
extra_headers => { kid => $kid },
);
@@ -174,22 +176,23 @@ B<user($password,$kid,$keyfile,$clientid,$userid)>
=cut
sub user {
- my ($password,$kid,$keyfile,$clientid,$entperpriseid) = @_;
+ my ($kid,$keyfile,$password,$clientid,$userid) = @_;
my $ug = Data::UUID->new;
my $jti = $ug->to_b64string($ug->create);
+ my $time = time;
my %claims = (
iss => $clientid,
sub => $userid,
box_sub_type => "user",
aud => "https://api.box.com/oauth2/token",
+ exp => $time + 60,
+ iat => $time,
jti => $jti
);
Crypt::JWT::encode_jwt(
alg => "RS256",
payload => \%claims,
- auto_iat => 1,
- relative_exp =>1,
- key => private_key($keyfile),
+ key => $keyfile,
keypass => $password,
extra_headers => { kid => $kid },
);
@@ -214,8 +217,8 @@ sub request {
"client_secret=$secret"
);
my $ua = LWP::UserAgent->new;
- my $resp = $ua->request($req);
-
+ my $response = $ua->request($req);
+ decode_json $response->content;
}
diff --git a/lib/Storage/Box/File.pm b/lib/Storage/Box/File.pm
new file mode 100644
index 0000000..7f13ed0
--- /dev/null
+++ b/lib/Storage/Box/File.pm
@@ -0,0 +1,72 @@
+# vim: ai ts=4 sts=4 et sw=4 ft=perl
+
+package Storage::Box::File;
+
+=pod
+
+=head1 NAME
+
+Storage::Box::File -- manages Box.com File resources
+
+=head1 SYNOPSIS
+
+ my $file = Storage::Box::File::create($user_token,$name,$parent,$data)
+
+
+=head1 DESCRIPTION
+
+This package allows you to manage Box.com Files.
+
+=cut
+
+use Modern::Perl;
+use HTTP::Request;
+use LWP::UserAgent;
+use JSON qw/ encode_json decode_json /;
+use Data::Dumper;
+
+=pod
+
+=head1 METHODS
+
+B<create($user_token,$name,$parent,$data)>
+
+ Creates a new File with the given name in the specified parent Folder.
+
+=cut
+
+sub create {
+ my ($token,$name,$parent,$data) = @_;
+ my $request = HTTP::Request->new( POST => "https://api.box.com/2.0/files/content" );
+ $request->header( Authorization => "Bearer $token" );
+ $request->content <<THERE;
+attributes='{"name":"$name","parent":{"id":"$parent"}}'&
+THERE
+
+ my $ua = LWP::UserAgent->new;
+ my $response = $ua->request($request);
+ print Dumper $response;
+ decode_json($response->content);
+}
+
+=pod
+
+=head1 TO DO
+
+stuff
+
+=head1 BUGS
+
+lots
+
+=head1 COPYRIGHT
+
+Best Practical LLC.
+
+=head1 AUTHORS
+
+Dave Goehrig <dave at dloh.org>
+
+=cut
+
+1;
diff --git a/lib/Storage/Box/User.pm b/lib/Storage/Box/User.pm
new file mode 100644
index 0000000..960a1c7
--- /dev/null
+++ b/lib/Storage/Box/User.pm
@@ -0,0 +1,132 @@
+# vim: ai ts=4 sts=4 et sw=4 ft=perl
+
+package Storage::Box::User;
+
+=pod
+
+=head1 NAME
+
+Storage::Box::User -- manages Box.com App User resources
+
+=head1 SYNOPSIS
+
+ my $user = Storage::Box::User::create($enterprise_token,$name)
+
+
+=head1 DESCRIPTION
+
+This package allows you to manage Box.com App Users.
+
+=cut
+
+use Modern::Perl;
+use HTTP::Request;
+use LWP::UserAgent;
+use JSON qw/ encode_json decode_json /;
+use Data::Dumper;
+
+=pod
+
+=head1 METHODS
+
+B<create($enterprise_token,$username)>
+
+ Creates a new App User, requires an enterprise OAuth token
+
+=cut
+
+sub create {
+ my ($token,$username) = @_;
+ my $request = HTTP::Request->new( POST => "https://api.box.com/2.0/users" );
+ $request->header( Authorization => "Bearer $token" );
+ $request->content( encode_json({ name => $username, is_platform_access_only => JSON::true }));
+ my $response = LWP::UserAgent->new->request($request);
+ decode_json($response->content) if $response->code == 201;
+}
+
+=pod
+
+B<read($enterprise_token,$user_id)>
+
+ Reads the App User metadata for the given user_id
+
+=cut
+
+sub read {
+ my ($token,$id) = @_;
+ my $request = HTTP::Request->new( GET => "https://api.box.com/2.0/users/$id" );
+ $request->header( Authorization => "Bearer $token" );
+ my $response = LWP::UserAgent->new->request($request);
+ decode_json($response->content) if $response->code == 200;
+}
+
+=pod
+
+B<update($enterprise_token,$user_id,$options)>
+
+ Updates the App User resource for the updateable fields only.
+
+ * $enterprise_token = OAuth2 token for the enterprise
+ * $user_id = id of the user resource to update
+ * $options = a hashref containing the fields to update:
+ * name
+ * language
+ * job_title
+ * phone
+ * address
+ * status
+ * timezone
+ * space_ammount
+
+=cut
+
+sub update {
+ my %data = ();
+ my ($token,$id,$options) = @_;
+ my @attributes = qw/ name language job_title phone address status timezone space_amount /;
+ @data{@attributes} = @$options{ @attributes };
+ my $request = HTTP::Request->new( PUT => "https://api.box.com/2.0/users/$id" );
+ $request->header( Authorization => "Bearer $token" );
+ $request->content( encode_json( \%data ));
+ my $response = LWP::UserAgent->new->request($request);
+ decode_json($response->content) if $response->code == 200 || $response->code == 204;
+}
+
+
+=pod
+
+B<delete($enterprise_token,$user_id)>
+
+ Deletes the App User specified by the given user_id
+
+=cut
+
+sub delete {
+ my ($token,$id) = @_;
+ my $request = HTTP::Request->new( DELETE => "https://api.box.com/2.0/users/$id" );
+ $request->header( Authorization => "Bearer $token" );
+ my $response = LWP::UserAgent->new->request($request);
+ $response->code == 204 || $response->code == 404; # if we don't find it, it has been deleted
+}
+
+=pod
+
+=head1 TO DO
+
+stuff
+
+=head1 BUGS
+
+lots
+
+=head1 COPYRIGHT
+
+Best Practical LLC.
+
+=head1 AUTHORS
+
+Dave Goehrig <dave at dloh.org>
+
+=cut
+
+1;
diff --git a/read_user.pl b/read_user.pl
new file mode 100644
index 0000000..f404237
--- /dev/null
+++ b/read_user.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id) = @ARGV;
+$enterprise_id ||= 2064336;
+
+my $jwt = Storage::Box::Auth::enterprise(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$enterprise_id");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+my $token = $res->{access_token};
+
+print Dumper Storage::Box::User::read($token,$user_id);
diff --git a/update_user.pl b/update_user.pl
new file mode 100644
index 0000000..e85f0dc
--- /dev/null
+++ b/update_user.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id,%options) = @ARGV;
+$enterprise_id ||= 2064336;
+
+my $jwt = Storage::Box::Auth::enterprise(
+ "vmqys6db",
+ "keys/private_key.pem",
+ "test",
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "$enterprise_id");
+
+my $res = Storage::Box::Auth::request(
+ "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
+ $jwt);
+
+my $token = $res->{access_token};
+
+print Dumper Storage::Box::User::update($token,$user_id,\%options);
commit 7a3e76537dda8fc29a6eba3d7251305e56c24608
Author: Dave Goehrig <dave at bestpractical.com>
Date: Thu Sep 1 13:14:02 2016 -0400
create functional interface for external storage use
Add JSON as a dependency
nomalize the http interface on curl
fixing dependencies
diff --git a/Build.PL b/Build.PL
index 0cc48bb..70ec54d 100644
--- a/Build.PL
+++ b/Build.PL
@@ -1,4 +1,4 @@
-# This Build.PL for Storage-Box was generated by Dist::Zilla::Plugin::ModuleBuildTiny 0.015.
+# This Build.PL for storage-box was generated by Dist::Zilla::Plugin::ModuleBuildTiny 0.015.
use strict;
use warnings;
diff --git a/META.json b/META.json
index 4acac45..0138c8f 100644
--- a/META.json
+++ b/META.json
@@ -1,5 +1,5 @@
{
- "abstract" : "Blah blah blah",
+ "abstract" : "a module for managing storage at Box.com",
"author" : [
"Dave Goehrig <dave at dloh.org>"
],
@@ -12,7 +12,7 @@
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
- "name" : "Storage-Box",
+ "name" : "storage-box",
"no_index" : {
"directory" : [
"eg",
@@ -40,31 +40,23 @@
"Crypt::JWT" : "0.017",
"Data::UUID" : "1.221",
"Expect" : "1.15",
- "HTTP::Request" : "6.11",
+ "JSON" : "2.90",
"Modern::Perl" : "1.20150127",
+ "WWW::Curl" : "4.17",
"perl" : "5.008005"
}
},
"test" : {
"requires" : {
- "Test::More" : "0.96"
+ "Test::More" : "0.96",
+ "Test::Pod" : "0"
}
}
},
"release_status" : "stable",
- "resources" : {
- "bugtracker" : {
- "web" : "https://github.com/cthulhuology/Storage-Box/issues"
- },
- "homepage" : "https://github.com/cthulhuology/Storage-Box",
- "repository" : {
- "type" : "git",
- "url" : "https://github.com/cthulhuology/Storage-Box.git",
- "web" : "https://github.com/cthulhuology/Storage-Box"
- }
- },
"version" : "0.01",
"x_contributors" : [
+ "Dave Goehrig <=>",
"Dave Goehrig <dave at bestpractical.com>"
],
"x_serialization_backend" : "Cpanel::JSON::XS version 3.0217"
diff --git a/README.md b/README.md
index 7b26244..100afa4 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,50 @@
# NAME
-Storage::Box - Blah blah blah
+Storage::Box - a module for managing storage at Box.com
# SYNOPSIS
use Storage::Box;
+ my $box = Storage::Box->new(
+ key_id => 'lasjfk',
+ enterprise_id => '1231923',
+ private_key => '/etc/box/keys/private_key.pem'
+ password => 'password',
+ client_id => '2lkjlkadsjfoiuawer',
+ client_secret => 'alksdjfoaiusrnre'
+ );
+
+ $box->create_user('bob');
+
# DESCRIPTION
Storage::Box is
# METHODS
+**create\_user($self,$name)**
+
+ Creates a new Box.com App user with the given username
+
+**read\_user($self,$user\_id)**
+
+ Reads a user object for the given user_id
+
+**update\_user($self,$user\_id,%options)**
+
+ Updates a user object specified by user_id with the given hash
+ of key => values. Returns the updated user object.
+
+**delete\_user($self,$user\_id)**
+
+ Deletes the user associated with $user_id. Returns true on success.
+
+**create\_file($self,$filename)**
+
# AUTHOR
-Dave Goehrig <dave at dloh.org>
+Dave Goehrig <dave at dloh.org>
# COPYRIGHT
diff --git a/auth_enterprise.pl b/auth_enterprise.pl
deleted file mode 100644
index ed99e77..0000000
--- a/auth_enterprise.pl
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env perl
-#
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-
-my $enterprise_id = $ARGV[0] || '2064336';
-print "Authorizing $enterprise_id\n";
-
-my $jwt = Storage::Box::Auth::enterprise(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$enterprise_id");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-print $res->{access_token}, "\n";
diff --git a/auth_user.pl b/auth_user.pl
deleted file mode 100644
index cc9882d..0000000
--- a/auth_user.pl
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env perl
-#
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-use Data::Dumper;
-
-print "Authorizing $ARGV[0]\n";
-
-my $jwt = Storage::Box::Auth::user(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$ARGV[0]");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-print $res->{access_token}, "\n";
diff --git a/cpanfile b/cpanfile
index 19ad9ad..df02af6 100644
--- a/cpanfile
+++ b/cpanfile
@@ -4,10 +4,10 @@ requires 'Modern::Perl', '1.20150127';
requires 'Crypt::JWT', '0.017';
requires 'Expect', '1.15';
requires 'Data::UUID', '1.221';
-requires 'HTTP::Request', '6.11';
-requires 'Crypt::OpenSSL::RSA', '0.28';
-requires 'Crypt::PK::RSA';
+requires 'JSON', '2.90';
+requires 'WWW::Curl', '4.17';
on test => sub {
requires 'Test::More', '0.96';
+ requires 'Test::Pod';
};
diff --git a/create_user.pl b/create_user.pl
deleted file mode 100644
index 65e1874..0000000
--- a/create_user.pl
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env perl
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-use Storage::Box::User;
-use Data::Dumper;
-
-my ($username,$enterprise_id) = @ARGV;
-$enterprise_id ||= 2064336;
-
-my $jwt = Storage::Box::Auth::enterprise(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$enterprise_id");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-my $token = $res->{access_token};
-
-my $user = Storage::Box::User::create($token,$username);
-
-print $user->{id}, "\n";
diff --git a/delete_user.pl b/delete_user.pl
deleted file mode 100644
index ce483e1..0000000
--- a/delete_user.pl
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env perl
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-use Storage::Box::User;
-use Data::Dumper;
-
-my ($user_id,$enterprise_id) = @ARGV;
-$enterprise_id ||= 2064336;
-
-my $jwt = Storage::Box::Auth::enterprise(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$enterprise_id");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-my $token = $res->{access_token};
-
-my $response = Storage::Box::User::delete($token,$user_id);
-
-print $response ? "ok\n": "failed\n";
diff --git a/lib/Storage/Box.pm b/lib/Storage/Box.pm
index 89fbaaa..ae30b21 100644
--- a/lib/Storage/Box.pm
+++ b/lib/Storage/Box.pm
@@ -3,18 +3,36 @@
package Storage::Box;
use Modern::Perl;
+use Object::Simple -base;
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Storage::Box::File;
+use Storage::Box::Folder;
+
our $VERSION = '0.01';
+
=pod
=encoding utf-8
=head1 NAME
-Storage::Box - Blah blah blah
+Storage::Box - a module for managing storage at Box.com
=head1 SYNOPSIS
- use Storage::Box;
+ use Storage::Box;
+
+ my $box = Storage::Box->new(
+ key_id => 'lasjfk',
+ enterprise_id => '1231923',
+ private_key => '/etc/box/keys/private_key.pem'
+ password => 'password',
+ client_id => '2lkjlkadsjfoiuawer',
+ client_secret => 'alksdjfoaiusrnre'
+ );
+
+ $box->create_user('bob');
=head1 DESCRIPTION
@@ -24,7 +42,186 @@ Storage::Box is
=cut
+has key_id => '';
+has enterprise_id => '';
+has public_key => '';
+has password => '';
+has client_id => '';
+has client_secret => '';
+has user_id => '';
+has enterprise_auth => '';
+has user_auth => '';
+has user => '';
+
+sub authenticate_enterprise {
+ my $self = shift;
+ $self->enterprise_auth('') if ($self->enterprise_auth and
+ $self->enterprise_auth->expired);
+ unless ($self->enterprise_auth) {
+ $self->enterprise_auth( Storage::Box::Auth->new(
+ key_id => $self->key_id,
+ enterprise_id => $self->enterprise_id,
+ private_key => $self->private_key,
+ password => $self->password,
+ client_id => $self->client_id,
+ client_secret => $self->client_secret
+ ));
+ $self->enterprise_auth->request;
+ }
+ $self;
+}
+
+sub authenticate_user {
+ my $self = shift;
+ $self->user_auth('') if ($self->user_auth and
+ $self->user_auth->expired);
+ unless($self->user_auth) {
+ $self->user_auth( Storage::Box::Auth->new(
+ key_id => $self->key_id,
+ user_id => $self->user_id,
+ private_key => $self->private_key,
+ password => $self->password,
+ client_id => $self->client_id,
+ client_secret => $self->client_secret
+ ));
+ $self->user_auth->request;
+ }
+ $self;
+}
+
+=pod
+B<create_user($self,$name)>
+
+ Creates a new Box.com App user with the given username
+
+=cut
+
+sub create_user {
+ my ($self,$name) = @_;
+ $self->authenticate_enterprise;
+ my $user = Storage::Box::User->new(
+ auth => $self->enterprise_auth,
+ name => $name
+ );
+ $user->create;
+}
+
+=pod
+B<read_user($self,$user_id)>
+
+ Reads a user object for the given user_id
+
+=cut
+
+sub read_user {
+ my ($self,$user_id) = @_;
+ $self->authenticate_enterprise;
+ my $user = Storage::Box::User->new(
+ auth => $self->enterprise_auth,
+ id => $user_id
+ );
+ $user->read;
+}
+
+=pod
+B<update_user($self,$user_id,%options)>
+
+ Updates a user object specified by user_id with the given hash
+ of key => values. Returns the updated user object.
+
+=cut
+
+sub update_user {
+ my ($self,$user_id,%options) = @_;
+ $self->authenticate_enterprise;
+ my $user = Storage::Box::User->new(
+ auth => $self->enterprise_auth,
+ id => $user_id
+ );
+ $user->update(%options);
+}
+
+=pod
+B<delete_user($self,$user_id)>
+
+ Deletes the user associated with $user_id. Returns true on success.
+=cut
+
+sub delete_user {
+ my ($self,$user_id) = @_;
+ $self->authenticate_enterprise;
+ my $user = Storage::Box::User->new(
+ auth => $self->enterprise_auth,
+ id => $user_id
+ );
+ $user->delete;
+}
+
+=pod
+B<create_file($self,$filename)>
+
+=cut
+sub create_file {
+ my ($self,$filename) = @_;
+ $self->authenticate_user;
+ my $file = Storage::Box::File->new(
+ auth => $self->user_auth,
+ name => $filename
+ );
+ $file->create;
+ $file;
+}
+
+sub download_file {
+ my ($self,$file_id) = @_;
+ $self->authenticate_user;
+ my $file = Storage::Box::File->new(
+ auth => $self->user_auth,
+ id => $file_id
+ );
+ $file->download;
+}
+
+sub delete_file {
+ my ($self,$file_id) = @_;
+ $self->authenticate_user;
+ my $file = Storage::Box::File->new(
+ auth => $self->user_auth,
+ id => $file_id
+ );
+ $file->delete;
+}
+
+sub create_folder {
+ my ($self,$name) = @_;
+ $self->authenticate_user;
+ my $folder = Storage::Box::Folder->new(
+ auth => $self->user_auth,
+ name => $name
+ );
+ $folder->create;
+}
+
+sub list_folder {
+ my ($self,$folder_id) = @_;
+ $self->authenticate_user;
+ my $folder = Storage::Box::Folder->new(
+ auth => $self->user_auth,
+ folder_id => $folder_id
+ );
+ $folder->items;
+}
+
+sub delete_folder {
+ my ($self,$folder_id) = @_;
+ $self->authenticate_user;
+ my $folder = Storage::Box::Folder->new(
+ auth => $self->user_auth,
+ folder_id => $folder_id
+ );
+ $folder->delete;
+}
=pod
diff --git a/lib/Storage/Box/Auth.pm b/lib/Storage/Box/Auth.pm
index 944971d..bbee131 100644
--- a/lib/Storage/Box/Auth.pm
+++ b/lib/Storage/Box/Auth.pm
@@ -1,6 +1,7 @@
# vim: ai ts=4 sts=4 et sw=4 ft=perl
package Storage::Box::Auth;
+use Object::Simple -base;
=pod
@@ -29,37 +30,53 @@ use Modern::Perl;
use Crypt::JWT;
use Expect;
use Data::UUID;
-use HTTP::Request;
-use LWP::UserAgent;
-use Crypt::PK::RSA;
+use WWW::Curl::Easy;
+use WWW::Curl::Form;
use JSON qw/ decode_json /;
=pod
=head1 METHODS
-B<generate_private_key($password)>
+
+=cut
+
+has password => ""; # password for private key
+has private_key => 'private_key.pem';
+has public_key => 'public_key.pem';
+has key_id => ''; # id of public key supplied by box.com
+has client_id => ''; # id of the application supplied by box.com
+has client_secret => ''; # secret of the application supplied by box.com
+has enterprise_id => ''; # id of the enterprise supplied by box.com
+has user_id => ''; # id of the user supplied by box.com
+has jwt => ''; # JSON Web Token generated by user or enterprise
+has token => ''; # OAuth2 token generated by request
+has expires => 0;
+
+=pod
+B<generate_private_key()>
Using openssl, this generates a 2048 bit aes256 private key file
=cut
+
sub generate_private_key {
-my ($password) = @_;
- my $exp = Expect->spawn("openssl genrsa -aes256 -out private_key.pem 2048")
- or die "Failed to generate private_key.pem";
+ my $self = shift;
+ my $exp = Expect->spawn("openssl genrsa -aes256 -out " . $self->private_key . " 2048")
+ or die "Failed to generate " . $self->private_key;
$exp->raw_pty(1);
$exp->expect(1,
[ qr/private_key\.pem:/ => sub {
- $exp->send("$password\r"); exp_continue;
+ $exp->send($self->password . "\r"); exp_continue;
} ]
);
$exp->soft_close();
-}
+};
=pod
-B<generate_public_key($password)>
+B<generate_public_key()>
Using openssl, outputs the public key associated with the private_key.pem.
The password must be the password associated with the private key.
@@ -67,17 +84,17 @@ B<generate_public_key($password)>
=cut
sub generate_public_key {
- my ($password) = @_;
- my $exp = Expect->spawn("openssl rsa -pubout -in private_key.pem -out public_key.pem")
- or die "Failed to generate public_key.pem";
+ my $self = shift;
+ my $exp = Expect->spawn("openssl rsa -pubout -in " . $self->private_key . " -out " . $self->public_key)
+ or die "Failed to generate " . $self->public_key;
$exp->raw_pty(1);
$exp->expect(1,
[ qr/private_key\.pem:/ => sub {
- $exp->send("$password\r"); exp_continue;
+ $exp->send($self->password . "\r"); exp_continue;
} ]
);
$exp->soft_close();
-}
+};
=pod
@@ -89,9 +106,9 @@ B<generate_keys($password)>
=cut
sub generate_keys {
- my ($password) = @_;
- generate_private_key $password;
- generate_public_key $password;
+ my ($self) = @_;
+ $self->segenerate_private_key;
+ $self->generate_public_key;
print <<THERE;
To install this key in box.com:
@@ -113,89 +130,77 @@ THERE
=pod
-B<private_key($keyfile)>
-
- Loads a private keyfile
-=cut
-
-sub private_key {
- my ($keyfile,$password) = @_;
- print "opening $keyfile with $password\n";
- Crypt::PK::RSA->new($keyfile,$password);
-}
-
-=pod
-
-B<enterprise($kid,$keyfile,$password,$clientid,$entperpriseid)>
+B<enterprise($self)>
Creates a JWT assertion for an enterprise account.
+ requires the following attributes be set:
- * $password = password for the keyfile
- * $kid = key id generated by Box.com
- * $keyfile = path to the private keyfile
- * $clientid = client id of the application creating the assertion
- * $enterpriseid = token specific to an enterprise when creating and managing app users
+ * password = password for the keyfile
+ * key_id = key id generated by Box.com
+ * private_key = path to the private keyfile
+ * client_id = client id of the application creating the assertion
+ * enterprise_id = token specific to an enterprise when creating and managing app users
=cut
sub enterprise {
- my ($kid,$keyfile,$password,$clientid,$enterpriseid) = @_;
+ my $self = shift;
my $ug = Data::UUID->new;
my $jti = $ug->to_b64string($ug->create);
my $time = time;
my %claims = (
- iss => $clientid,
- sub => $enterpriseid,
+ iss => $self->client_id,
+ sub => $self->enterprise_id,
box_sub_type => "enterprise",
aud => "https://api.box.com/oauth2/token",
exp => $time + 60,
iat => $time,
jti => $jti
);
- Crypt::JWT::encode_jwt(
+ $self->jwt(Crypt::JWT::encode_jwt(
alg => "RS256",
payload => \%claims,
- key => $keyfile,
- keypass => $password,
- extra_headers => { kid => $kid },
- );
+ key => $self->private_key,
+ keypass => $self->password,
+ extra_headers => { kid => $self->key_id },
+ ));
}
=pod
-B<user($password,$kid,$keyfile,$clientid,$userid)>
+B<user($self)>
Creates a JWT assertion for a user account.
- * $password = password for the keyfile
- * $kid = key id generated by Box.com
- * $keyfile = path to the private keyfile
- * $clientid = client id of the application creating the assertion
- * $userid = app user_id for a token specific to an individual app user.
+ * password = password for the keyfile
+ * key_id = key id generated by Box.com
+ * private_key = path to the private keyfile
+ * client_id = client id of the application creating the assertion
+ * user_id = app user_id for a token specific to an individual app user.
=cut
sub user {
- my ($kid,$keyfile,$password,$clientid,$userid) = @_;
+ my $self = shift;
my $ug = Data::UUID->new;
my $jti = $ug->to_b64string($ug->create);
my $time = time;
my %claims = (
- iss => $clientid,
- sub => $userid,
+ iss => $self->client_id,
+ sub => $self->user_id,
box_sub_type => "user",
aud => "https://api.box.com/oauth2/token",
exp => $time + 60,
iat => $time,
jti => $jti
);
- Crypt::JWT::encode_jwt(
+ $self->jwt(Crypt::JWT::encode_jwt(
alg => "RS256",
payload => \%claims,
- key => $keyfile,
- keypass => $password,
- extra_headers => { kid => $kid },
- );
+ key => $self->private_key,
+ keypass => $self->password,
+ extra_headers => { kid => $self->key_id },
+ ));
}
=pod
@@ -207,21 +212,34 @@ B<request($client_id,$client_secret,$jwt)>
=cut
sub request {
- my ($client_id,$secret,$jwt) = @_;
- my $req = HTTP::Request->new(POST => "https://api.box.com/oauth2/token");
- $req->header("Content-Type" => "application/x-www-form-urlencoded");
- $req->content(
- "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&" .
- "assertion=$jwt&" .
- "client_id=$client_id&" .
- "client_secret=$secret"
- );
- my $ua = LWP::UserAgent->new;
- my $response = $ua->request($req);
- decode_json $response->content;
+ my $self = shift;
+ my $body;
+
+ my $form = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&" .
+ "assertion=" . $self->jwt . "&" .
+ "client_id=" . $self->client_id . "&" .
+ "client_secret=" . $self->client_secret;
+
+ my $curl = WWW::Curl::Easy->new;
+ $curl->setopt(CURLOPT_URL,"https://api.box.com/oauth2/token");
+ $curl->setopt(CURLOPT_POST,1);
+ $curl->setopt(CURLOPT_HTTPHEADER, [
+ "Content-Type: application/x-www-form-urlencoded"
+ ]);
+ $curl->setopt(CURLOPT_FILE, \$body );
+ $curl->setopt(CURLOPT_POSTFIELDS,$form);
+
+ return $self if ($curl->perform || $curl->getinfo(CURLINFO_RESPONSE_CODE) != 200 );
+ my $res = decode_json $body;
+ $self->expires(time + $res->{expires_in});
+ $self->token($res->{access_token});
+ $self;
}
-
+sub expired {
+ my $self = time;
+ time >= $self->expires;
+}
=pod
diff --git a/lib/Storage/Box/File.pm b/lib/Storage/Box/File.pm
index 7f13ed0..321ebf2 100644
--- a/lib/Storage/Box/File.pm
+++ b/lib/Storage/Box/File.pm
@@ -1,6 +1,7 @@
# vim: ai ts=4 sts=4 et sw=4 ft=perl
package Storage::Box::File;
+use Object::Simple -base;
=pod
@@ -20,33 +21,68 @@ This package allows you to manage Box.com Files.
=cut
use Modern::Perl;
-use HTTP::Request;
-use LWP::UserAgent;
use JSON qw/ encode_json decode_json /;
-use Data::Dumper;
+use Storage::Box::Request;
=pod
=head1 METHODS
-B<create($user_token,$name,$parent,$data)>
+=cut
+
+has id => '0'; # id of the file, supplied by box.com
+has name => ''; # name of the file
+has parent => '0'; # id of the parent folder, 0 is top level default
+has auth => ''; # Storage::Box::Auth object
+
+=pod
+B<create($user_token,$name,$parent,$filename)>
Creates a new File with the given name in the specified parent Folder.
=cut
sub create {
- my ($token,$name,$parent,$data) = @_;
- my $request = HTTP::Request->new( POST => "https://api.box.com/2.0/files/content" );
- $request->header( Authorization => "Bearer $token" );
- $request->content <<THERE;
-attributes='{"name":"$name","parent":{"id":"$parent"}}'&
-THERE
-
- my $ua = LWP::UserAgent->new;
- my $response = $ua->request($request);
- print Dumper $response;
- decode_json($response->content);
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://upload.box.com/api/2.0/files/content",
+ auth => $self->auth
+ );
+ $req->field('attributes',"{\"name\":\"" . $self->name . "\",\"parent\":{\"id\":\"" . $self->parent . "\"}}");
+ $req->file($self->name);
+ $req->post->request;
+ return $self unless ($req->code == 201);
+ my $json = decode_json($req->body);
+ $self->id($json->{entries}[0]->{id}); # update our id
+ $self;
+}
+
+=pod
+
+B<download($token,$fileid)>
+
+ Downloads a file
+
+=cut
+
+sub download {
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/files/" . $self->id . "/content",
+ auth => $self->auth
+ );
+ $req->get->perform;
+ $req->body;
+}
+
+sub delete {
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/files/" . $self->id,
+ auth => $self->auth
+ );
+ $req->delete->perform;
+ $req->code == 200 || $req->code == 404;
}
=pod
diff --git a/lib/Storage/Box/Folder.pm b/lib/Storage/Box/Folder.pm
new file mode 100644
index 0000000..4bb6b31
--- /dev/null
+++ b/lib/Storage/Box/Folder.pm
@@ -0,0 +1,108 @@
+# vim: ai ts=4 sts=4 et sw=4 ft=perl
+
+package Storage::Box::Folder;
+
+=pod
+
+=head1 NAME
+
+Storage::Box::Folder -- manages Box.com Folder resources
+
+=head1 SYNOPSIS
+
+ my $file = Storage::Box::Folder->new(
+
+ )
+
+
+=head1 DESCRIPTION
+
+This package allows you to manage Box.com Files.
+
+=cut
+
+use Object::Simple -base;
+use Modern::Perl;
+use Storage::Box::Request;
+use JSON qw/ encode_json decode_json /;
+use Data::Dumper;
+
+=pod
+
+=head1 METHODS
+
+=cut
+
+has id => '0'; # id of the file, supplied by box.com
+has name => ''; # name of the file
+has parent => '0'; # id of the parent folder, 0 is top level default
+has auth => ''; # Storage::Box::Auth object
+
+=pod
+B<create($user_token,$name,$parent,$filename)>
+
+ Creates a new File with the given name in the specified parent Folder.
+
+=cut
+
+sub create {
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/folders",
+ auth => $self->auth
+ );
+ $req->content("{\"name\":\"" . $self->name . "\",\"parent\":{\"id\":\"" . $self->parent . "\"}}");
+ $req->post->request;
+ my $json = decode_json $req->body;
+ $self->id($json->{id});
+}
+
+
+sub items {
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/folders/" . $self->id . "/items",
+ auth => $self->auth
+ );
+ $req->get->request;
+ decode_json $req->body;
+}
+
+=pod
+
+B<delete()>
+
+ Delete the folder
+
+=cut
+sub delete {
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/folders/" . $self->id,
+ auth => $self->auth
+ );
+ $req->delete->request;
+ $self;
+}
+
+=pod
+
+=head1 TO DO
+
+stuff
+
+=head1 BUGS
+
+lots
+
+=head1 COPYRIGHT
+
+Best Practical LLC.
+
+=head1 AUTHORS
+
+Dave Goehrig <dave at dloh.org>
+
+=cut
+
+1;
diff --git a/lib/Storage/Box/Request.pm b/lib/Storage/Box/Request.pm
new file mode 100644
index 0000000..7e8a711
--- /dev/null
+++ b/lib/Storage/Box/Request.pm
@@ -0,0 +1,136 @@
+# vim: ai ts=4 sts=4 et sw=4 ft=perl
+#
+package Storage::Box::Request;
+
+=pod
+
+=head1 NAME
+
+Storage::Box::Request
+
+=head1 SYNOPSIS
+
+ my $request = Storage::Box::Request->new(
+ url => "https://api.box.com",
+ auth => $auth
+ );
+
+=head1 DESCRIPTION
+
+=cut
+
+use Object::Simple -base;
+use Modern::Perl;
+use JSON qw/ encode_json decode_json /;
+use WWW::Curl::Easy;
+use WWW::Curl::Form;
+
+has url => '';
+has auth => '';
+has curl => '';
+has body => '';
+has form => '';
+has max_retries => 5;
+has retries => 0;
+has code => 200;
+
+sub get {
+ my $self = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ $self;
+}
+
+sub post {
+ my $self = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ $self->curl->setopt(CURLOPT_POST, 1);
+ $self;
+}
+
+sub put {
+ my $self = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ $self->curl->setopt(CURLOPT_CUSTOMREQUEST,"PUT");
+ $self;
+}
+
+sub delete {
+ my $self = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ $self->curl->setopt(CURLOPT_CUSTOMREQUEST,"DELETE");
+ $self;
+}
+
+sub request {
+ my $self = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ my $headers = [
+ "Accept: */*",
+ "Authorization: Bearer " . $self->auth->token()
+ ];
+ my $body;
+ $self->curl->setopt(CURLOPT_FOLLOWLOCATION,1);
+ $self->curl->setopt(CURLOPT_HTTPHEADER,$headers);
+ $self->curl->setopt(CURLOPT_FILE, \$body );
+ $self->curl->setopt(CURLOPT_URL,$self->url);
+ $self->curl->setopt(CURLOPT_HTTPPOST,$self->form) if ($self->form ne '');
+ if ($self->curl->perform) { # CURLE_OK is 0
+ if ( ++$self->retries < $self->max_retries) {
+ sleep 1;
+ return $self->request;
+ }
+ $self->retries(0);
+ $self->body(''); # fail with empty body
+ return $self;
+ }
+ $self->code($self->curl->getinfo(CURLINFO_RESPONSE_CODE));
+ $self->body($body);
+ $self;
+}
+
+sub field {
+ my $self = shift;
+ my ($key,$value) = @_;
+ $self->form( WWW::Curl::Form->new() ) unless $self->form;
+ $self->form->formadd($key,$value);
+ $self;
+}
+
+sub file {
+ my $self = shift;
+ my $filename = shift;
+ $self->form( WWW::Curl::Form->new() ) unless $self->form;
+ $self->form->formadd('attributes',"{\"name\":\"" . $self->name . "\",\"parent\":{\"id\":\"" . $self->parent . "\"}}");
+ $self->form->formaddfile($filename, 'attachment', "multipart/form-data");
+ $self;
+}
+
+sub content {
+ my $self = shift;
+ my $data = shift;
+ $self->curl( WWW::Curl::Easy->new() ) unless $self->curl;
+ $self->curl->setopt(CURLOPT_POSTFIELDS, $data );
+ $self;
+}
+
+=pod
+
+=head1 TO DO
+
+stuff
+
+=head1 BUGS
+
+lots
+
+=head1 COPYRIGHT
+
+Best Practical LLC.
+
+=head1 AUTHORS
+
+Dave Goehrig <dave at dloh.org>
+
+=cut
+
+1;
diff --git a/lib/Storage/Box/User.pm b/lib/Storage/Box/User.pm
index 960a1c7..6df16f3 100644
--- a/lib/Storage/Box/User.pm
+++ b/lib/Storage/Box/User.pm
@@ -1,6 +1,7 @@
# vim: ai ts=4 sts=4 et sw=4 ft=perl
package Storage::Box::User;
+use Object::Simple -base;
=pod
@@ -10,7 +11,10 @@ Storage::Box::User -- manages Box.com App User resources
=head1 SYNOPSIS
- my $user = Storage::Box::User::create($enterprise_token,$name)
+ my $user = Storage::Box::User->new(
+ auth => $auth,
+ name => 'Dave'
+ )->create;
=head1 DESCRIPTION
@@ -20,49 +24,73 @@ This package allows you to manage Box.com App Users.
=cut
use Modern::Perl;
-use HTTP::Request;
-use LWP::UserAgent;
use JSON qw/ encode_json decode_json /;
-use Data::Dumper;
+use Storage::Box::Request;
=pod
=head1 METHODS
-B<create($enterprise_token,$username)>
- Creates a new App User, requires an enterprise OAuth token
+=cut
+
+has id => '';
+has name => '';
+has auth => '';
+
+=pod
+
+B<create()>
+
+ Creates a new App User, requires:
+
+ * name = name of the user
+ * auth = an enterprise Storage::Box::Auth object
=cut
sub create {
- my ($token,$username) = @_;
- my $request = HTTP::Request->new( POST => "https://api.box.com/2.0/users" );
- $request->header( Authorization => "Bearer $token" );
- $request->content( encode_json({ name => $username, is_platform_access_only => JSON::true }));
- my $response = LWP::UserAgent->new->request($request);
- decode_json($response->content) if $response->code == 201;
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/users",
+ auth => $self->auth
+ );
+ $req->content( encode_json({
+ name => $self->name,
+ is_platform_access_only => JSON::true
+ }));
+ $req->post->request;
+ if ($req->code == 201) {
+ my $json = decode_json($req->body);
+ $self->id($json->{id});
+ }
+ $self;
}
=pod
B<read($enterprise_token,$user_id)>
- Reads the App User metadata for the given user_id
+ Reads the App User metadata for the user
+
+ * id = id of the user
+ * auth = an enterprise Storage::Box::Auth object
=cut
sub read {
- my ($token,$id) = @_;
- my $request = HTTP::Request->new( GET => "https://api.box.com/2.0/users/$id" );
- $request->header( Authorization => "Bearer $token" );
- my $response = LWP::UserAgent->new->request($request);
- decode_json($response->content) if $response->code == 200;
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/users/" . $self->id,
+ auth => $self->auth
+ );
+ $req->get->request;
+ $req->code == 200 ? decode_json($req->body) : {};
}
=pod
-B<update($enterprise_token,$user_id,$options)>
+B<update(%options)>
Updates the App User resource for the updateable fields only.
@@ -82,31 +110,36 @@ B<update($enterprise_token,$user_id,$options)>
sub update {
my %data = ();
- my ($token,$id,$options) = @_;
+ my $self = shift;
+ my (%options) = @_;
my @attributes = qw/ name language job_title phone address status timezone space_amount /;
- @data{@attributes} = @$options{ @attributes };
- my $request = HTTP::Request->new( PUT => "https://api.box.com/2.0/users/$id" );
- $request->header( Authorization => "Bearer $token" );
- $request->content( encode_json( \%data ));
- my $response = LWP::UserAgent->new->request($request);
- decode_json($response->content) if $response->code == 200 || $response->code == 204;
+ @data{@attributes} = @options{ @attributes };
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/users/" . $self->id,
+ auth => $self->auth
+ );
+ $req->content( encode_json( \%data ));
+ $req->put->request;
+ $req->code == 200 ? decode_json($req->body) : {};
}
=pod
-B<delete($enterprise_token,$user_id)>
+B<delete()>
Deletes the App User specified by the given user_id
=cut
sub delete {
- my ($token,$id) = @_;
- my $request = HTTP::Request->new( DELETE => "https://api.box.com/2.0/users/$id" );
- $request->header( Authorization => "Bearer $token" );
- my $response = LWP::UserAgent->new->request($request);
- $response->code == 204 || $response->code == 404; # if we don't find it, it has been deleted
+ my $self = shift;
+ my $req = Storage::Box::Request->new(
+ url => "https://api.box.com/2.0/users/" . $self->id,
+ auth => $self->auth
+ );
+ $req->delete->request;
+ $req->code == 204 || $req->code == 404; # if we don't find it, it has been deleted
}
=pod
diff --git a/read_user.pl b/read_user.pl
deleted file mode 100644
index f404237..0000000
--- a/read_user.pl
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env perl
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-use Storage::Box::User;
-use Data::Dumper;
-
-my ($user_id,$enterprise_id) = @ARGV;
-$enterprise_id ||= 2064336;
-
-my $jwt = Storage::Box::Auth::enterprise(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$enterprise_id");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-my $token = $res->{access_token};
-
-print Dumper Storage::Box::User::read($token,$user_id);
diff --git a/scripts/auth_enterprise.pl b/scripts/auth_enterprise.pl
new file mode 100644
index 0000000..a137882
--- /dev/null
+++ b/scripts/auth_enterprise.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl
+#
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ enterprise_id => ($ARGV[0] || '2064336'),
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->enterprise->request;
+print $auth->token, "\n";
diff --git a/scripts/auth_user.pl b/scripts/auth_user.pl
new file mode 100644
index 0000000..caa42c0
--- /dev/null
+++ b/scripts/auth_user.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl
+#
+
+use lib 'lib';
+use Storage::Box::Auth;
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ user_id => ($ARGV[0]),
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->user->request;
+
+print $auth->token, "\n";
diff --git a/scripts/create_file.pl b/scripts/create_file.pl
new file mode 100644
index 0000000..5a980c2
--- /dev/null
+++ b/scripts/create_file.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+#
+use lib 'lib';
+use Data::Dumper;
+use Storage::Box::File;
+use Storage::Box::Auth;
+
+my ($user_id,$filename) = @ARGV;
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ user_id => $user_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->user->request;
+
+my $file = Storage::Box::File->new(
+ auth => $auth,
+ name => $filename
+);
+
+$file->create;
+
+print $file->id, "\n";
diff --git a/scripts/create_user.pl b/scripts/create_user.pl
new file mode 100644
index 0000000..4c93276
--- /dev/null
+++ b/scripts/create_user.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+
+my ($username,$enterprise_id) = @ARGV;
+
+$enterprise_id ||= '2064336';
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ enterprise_id => $enterprise_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->enterprise->request;
+
+my $user = Storage::Box::User->new(
+ name => $username,
+ auth => $auth
+);
+
+$user->create;
+
+print $user->id, "\n";
diff --git a/scripts/delete_file.pl b/scripts/delete_file.pl
new file mode 100644
index 0000000..c69c2c8
--- /dev/null
+++ b/scripts/delete_file.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+#
+use lib 'lib';
+use Data::Dumper;
+use Storage::Box::Auth;
+use Storage::Box::File;
+
+my ($user_id,$file_id) = @ARGV;
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ user_id => $user_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->user->request;
+
+my $file = Storage::Box::File->new(
+ auth => $auth,
+ id => $file_id
+);
+
+$file->delete;
diff --git a/scripts/delete_user.pl b/scripts/delete_user.pl
new file mode 100644
index 0000000..827fcd3
--- /dev/null
+++ b/scripts/delete_user.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id) = @ARGV;
+$enterprise_id ||= '2064336';
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ enterprise_id => $enterprise_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->enterprise->request;
+
+my $user = Storage::Box::User->new(
+ auth => $auth,
+ id => $user_id
+);
+
+print $user->delete ? "ok\n": "failed\n";
diff --git a/scripts/read_user.pl b/scripts/read_user.pl
new file mode 100644
index 0000000..8868f6e
--- /dev/null
+++ b/scripts/read_user.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id) = @ARGV;
+$enterprise_id ||= '2064336';
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ enterprise_id => $enterprise_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->enterprise->request;
+
+my $user = Storage::Box::User->new(
+ auth => $auth,
+ id => $user_id
+);
+
+print Dumper $user->read;
diff --git a/scripts/update_user.pl b/scripts/update_user.pl
new file mode 100644
index 0000000..5bd3186
--- /dev/null
+++ b/scripts/update_user.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+use lib 'lib';
+
+use Storage::Box::Auth;
+use Storage::Box::User;
+use Data::Dumper;
+
+my ($user_id,$enterprise_id,%options) = @ARGV;
+$enterprise_id ||= '2064336';
+
+my $auth = Storage::Box::Auth->new(
+ key_id => "vmqys6db",
+ enterprise_id => $enterprise_id,
+ public_key => "keys/public_key.pem",
+ private_key => "keys/private_key.pem",
+ password => "test",
+ client_id => "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
+ client_secret => "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3");
+
+$auth->enterprise->request;
+
+my $user = Storage::Box::User->new(
+ auth => $auth,
+ id => $user_id
+);
+
+print Dumper $user->update(%options);
diff --git a/update_user.pl b/update_user.pl
deleted file mode 100644
index e85f0dc..0000000
--- a/update_user.pl
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env perl
-
-use lib 'lib';
-
-use Storage::Box::Auth;
-use Storage::Box::User;
-use Data::Dumper;
-
-my ($user_id,$enterprise_id,%options) = @ARGV;
-$enterprise_id ||= 2064336;
-
-my $jwt = Storage::Box::Auth::enterprise(
- "vmqys6db",
- "keys/private_key.pem",
- "test",
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "$enterprise_id");
-
-my $res = Storage::Box::Auth::request(
- "96o6g1e6mot3j1ord2qq6ptvxcsbn4oh",
- "xhp3us3rX3kNLvMt9y3DcGSasqP6Orl3",
- $jwt);
-
-my $token = $res->{access_token};
-
-print Dumper Storage::Box::User::update($token,$user_id,\%options);
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list