API-Google
view release on metacpan or search on metacpan
Added events_list method to GCal.pm
-----------------------------------------
version 0.06 at 2016-11-11 23:42:23 +0000
-----------------------------------------
Change: c248eaf765d7700890f59b16972289be2bfc27eb
Author: Pavel Serikov <pavel.p.serikov@gmail.com>
Date : 2016-11-12 02:42:23 +0000
Added goauth CLI tool
Change: 51d47620e703e493adfa3910e6bbdd5a83b3595d
Author: Pavel Serikov <pavel@serikov.xyz>
Date : 2016-11-10 18:10:50 +0000
Added auto-generation of correct Readme.md
Change: aad0108940e2afef2e89c974fb2393a780a5ac6e
Author: Pavel Serikov <pavel@serikov.xyz>
Date : 2016-11-10 13:24:57 +0000
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.009.
CHANGES
LICENSE
MANIFEST
META.json
META.yml
Makefile.PL
README.md
bin/goauth
dist.ini
lib/API/Google.pm
lib/API/Google/GCal.pm
lib/API/Google/Server.pm
t/00-load.t
t/manifest.t
t/pod.t
{
"abstract" : "Perl library for easy access to Google services via their API",
"author" : [
"Pavel Serikov <pavelsr@cpan.org>"
],
"dynamic_config" : 0,
"generated_by" : "Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150001",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
---
abstract: 'Perl library for easy access to Google services via their API'
author:
- 'Pavel Serikov <pavelsr@cpan.org>'
build_requires:
Test::More: '0'
perl: '5.006'
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 0
generated_by: 'Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150001'
license: perl
meta-spec:
Makefile.PL view on Meta::CPAN
use ExtUtils::MakeMaker;
my %WriteMakefileArgs = (
"ABSTRACT" => "Perl library for easy access to Google services via their API",
"AUTHOR" => "Pavel Serikov <pavelsr\@cpan.org>",
"CONFIGURE_REQUIRES" => {
"ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "API-Google",
"EXE_FILES" => [
"bin/goauth"
],
"LICENSE" => "perl",
"MIN_PERL_VERSION" => "5.006",
"NAME" => "API::Google",
"PREREQ_PM" => {
"Config::JSON" => 0,
"Crypt::JWT" => 0,
"Data::Dumper" => 0,
"Mojo::UserAgent" => 0,
"Mojo::Util" => 0,
#!perl
package goauth;
$goauth::VERSION = '0.12';
# ABSTRACT: CLI tool for easily getting of Google API access tokens. Supports multiple users
use Mojolicious::Commands;
use Data::Dumper;
use Config::JSON;
use Tie::File;
use feature 'say';
use Net::EmptyPort qw(empty_port);
say "File $filename exists";
input_if_not_exists(['gapi/client_id', 'gapi/client_secret']);
runserver();
} else {
say "JSON file $filename with API tokens not found. Creating new file...";
setup();
runserver();
}
sub setup {
my $oauth = {};
say "Obtain app client_id and client_secret from http://console.developers.google.com/";
print "client_id: ";
chomp ($oauth->{client_id} = <STDIN>);
print "client_secret: ";
chomp ($oauth->{client_secret} = <STDIN>);
my $tokensfile = Config::JSON->create($filename);
$tokensfile->set('gapi/client_id', $oauth->{client_id});
$tokensfile->set('gapi/client_secret', $oauth->{client_secret});
say 'OAuth details was updated!';
# Remove comment for Mojolicious::Plugin::JSONConfig compatibility
tie my @array, 'Tie::File', $filename or die $!;
shift @array;
untie @array;
};
sub input_if_not_exists {
my $fields = shift;
my $config = Config::JSON->new($filename);
if (!defined $config->get($i) ) {
print "$i: ";
chomp (my $val = <STDIN>);
$config->set($i, $val);
}
}
}
sub runserver {
my $port = empty_port(3000);
say "Starting web server. Before authorization don't forget to set redirect_uri to http://127.0.0.1:$port/";
$ENV{'GOAUTH_TOKENSFILE'} = $filename;
Mojolicious::Commands->start_app('API::Google::Server', 'daemon', '-l', 'http://*:'.$port);
}
__END__
=pod
=encoding UTF-8
=head1 NAME
goauth - CLI tool for easily getting of Google API access tokens. Supports multiple users
=head1 VERSION
version 0.12
=head1 SYNOPSIS
goauth [tokens.json]
By default if will create config.json in current directory
Structure of config will be like
{ "gapi":
{
"client_id": "001122334455-abcdefghijklmnopqrstuvwxyz012345.apps.googleusercontent.com",
"client_secret": "1ayL76NlEKjj85eZOipFZkyM",
"tokens": {
name = API-Google
author = Pavel Serikov <pavelsr@cpan.org>
license = Perl_5
copyright_holder = Pavel Serikov
copyright_year = 2016
version = 0.12
[PruneCruft]
[ManifestSkip]
[MetaYAML]
[License]
[ExtraTests]
lib/API/Google.pm view on Meta::CPAN
$h->{max_refresh_attempts} = $params->{max_refresh_attempts} || 5;
return bless $h, $class;
}
sub refresh_access_token {
my ($self, $params) = @_;
warn "Attempt to refresh access_token with params: ".Dumper $params if $self->{debug};
$params->{grant_type} = 'refresh_token';
$self->{ua}->post('https://www.googleapis.com/oauth2/v4/token' => form => $params)->res->json; # tokens
};
sub client_id {
shift->{tokensfile}->get('gapi/client_id');
}
sub ua {
shift->{ua};
}
lib/API/Google.pm view on Meta::CPAN
warn "api_query() params : ".Dumper $params if $self->{debug};
$payload = { payload => $payload };
%$params = (%$params, %$payload);
my $tx = $self->build_http_transaction($params);
my $res = $self->{ua}->start($tx)->res->json;
# for future:
# if ( grep { $_->{message} eq 'Invalid Credentials' && $_->{reason} eq 'authError'} @{$res->{error}{errors}} ) { ... }
warn "First api_query() result : ".Dumper $res if $self->{debug};
if (defined $res->{error}) { # token expired error handling
my $attempt = 1;
while ($res->{error}{message} eq 'Invalid Credentials') {
if ($attempt == $self->{max_refresh_attempts}) {
last;
lib/API/Google/Server.pm view on Meta::CPAN
#!perl
package API::Google::Server;
$API::Google::Server::VERSION = '0.12';
# ABSTRACT: Mojolicious::Lite web server for getting Google API tokens via Oauth 2.0
use Mojolicious::Lite;
use Data::Dumper;
use Config::JSON;
use Tie::File;
use Crypt::JWT qw(decode_jwt);
use feature 'say';
use Mojo::Util 'getopt';
use Mojolicious::Plugin::OAuth2;
lib/API/Google/Server.pm view on Meta::CPAN
# my @j = grep { $_ =~ /\w+.json/ } @files;
# return $j[0];
# }
# my $f = return_json_filename();
my $config = Config::JSON->new($ENV{'GOAUTH_TOKENSFILE'});
delete $ENV{'GOAUTH_TOKENSFILE'};
# authorize_url and token_url can be retrieved from OAuth discovery document
# https://github.com/marcusramberg/Mojolicious-Plugin-OAuth2/issues/52
plugin "OAuth2" => {
google => {
key => $config->get('gapi/client_id'), # $config->{gapi}{client_id},
secret => $config->get('gapi/client_secret'), #$config->{gapi}{client_secret},
authorize_url => 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code',
token_url => 'https://www.googleapis.com/oauth2/v4/token'
}
};
helper get_new_tokens => sub {
my ($c,$auth_code) = @_;
my $hash = {};
$hash->{code} = $c->param('code');
$hash->{redirect_uri} = $c->url_for->to_abs->to_string;
$hash->{client_id} = $config->get('gapi/client_id');
$hash->{client_secret} = $config->get('gapi/client_secret');
$hash->{grant_type} = 'authorization_code';
my $tokens = $c->ua->post('https://www.googleapis.com/oauth2/v4/token' => form => $hash)->res->json;
return $tokens;
};
# =method get_all_google_jwk_keys
# Get all Google JWK keys for validation of JSON Web Token
# Check https://jwt.io/ and https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken for more details
# return arrayref
# =cut
# helper get_all_google_jwk_keys => sub {
# my $c = shift;
# my $certs = $c->ua->get('https://www.googleapis.com/oauth2/v3/certs')->res->json;
# # return $certs;
# my @keys = @{$certs->{keys}};
# return \@keys;
# # return $certs->{keys}[1];
# };
# =method get_google_jwk_key_by_kid
# Return JWK key with specified kid
lib/API/Google/Server.pm view on Meta::CPAN
# $c->get_google_cert_by_kid($header->{kid},$crts)
# =cut
# helper get_google_jwk_key_by_kid => sub {
# my ($c, $kid, $jwks_arrayref) = @_;
# if (!defined $jwks_arrayref) {
# warn 'get_google_cert_by_kid(): $ctrs is not defined, obtaining from Google...';
# $jwks_arrayref = $c->ua->get('https://www.googleapis.com/oauth2/v3/certs')->res->json->{keys};
# }
# # my @keys = @{$crts->{keys}};
# my @keys = @$jwks_arrayref;
# my $size = scalar @keys;
# warn "Found $size JWK keys";
# if (!defined $kid) {
# warn 'get_google_cert_by_kid(): $kid is not defined, will return random certificate';
# return $keys[rand @keys];
lib/API/Google/Server.pm view on Meta::CPAN
# };
helper get_email => sub {
my ($c, $access_token) = @_;
my %h = (
'Authorization' => 'Bearer '.$access_token
);
$c->ua->get('https://www.googleapis.com/auth/plus.profile.emails.read' => form => \%h)->res->json;
};
get "/" => sub {
my $c = shift;
app->log->info("Will store tokens at".$config->getFilename ($config->pathToFile));
if ($c->param('code')) {
app->log->info("Authorization code was retrieved: ".$c->param('code'));
my $tokens = $c->get_new_tokens($c->param('code'));
app->log->info("App got new tokens: ".Dumper $tokens);
if ($tokens) {
my $user_data;
# warn Dumper $user_data;
# you can use https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123 for development
if ($tokens->{id_token}) {
# my $jwt = Mojo::JWT->new(claims => $tokens->{id_token});
# warn "Mojo header:".Dumper $jwt->header;
# my $keys = $c->get_all_google_jwk_keys(); # arrayref
# my ($header, $data) = decode_jwt( token => $tokens->{id_token}, decode_header => 1, key => '' ); # exctract kid
# warn "Decode header :".Dumper $header;
$user_data = decode_jwt(
token => $tokens->{id_token},
kid_keys => $c->ua->get('https://www.googleapis.com/oauth2/v3/certs')->res->json,
);
warn "Decoded user data:".Dumper $user_data;
};
#$user_data->{email};
#$user_data->{family_name}
#$user_data->{given_name}
# $tokensfile->set('tokens/'.$user_data->{email}, $tokens->{access_token});
$config->addToHash('gapi/tokens/'.$user_data->{email}, 'access_token', $tokens->{access_token} );
if ($tokens->{refresh_token}) {
$config->addToHash('gapi/tokens/'.$user_data->{email}, 'refresh_token', $tokens->{refresh_token});
}
}
$c->render( json => $config->get('gapi') );
} else {
$c->render(template => 'oauth');
}
};
app->start;
=pod
=encoding UTF-8
=head1 NAME
API::Google::Server - Mojolicious::Lite web server for getting Google API tokens via Oauth 2.0
=head1 VERSION
version 0.12
=head1 METHODS
=head2 get_new_tokens
Get new access_token by auth_code
=head2 get_email
Get email address of API user
=head1 AUTHOR
Pavel Serikov <pavelsr@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Pavel Serikov.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
__DATA__
@@ oauth.html.ep
<%= link_to "Click here to get API tokens", $c->oauth2->auth_url("google",
scope => "email profile https://www.googleapis.com/auth/plus.profile.emails.read https://www.googleapis.com/auth/calendar",
authorize_query => { access_type => 'offline'} )
%>
<br><br>
<a href="https://developers.google.com/+/web/api/rest/oauth#authorization-scopes">
Check more about authorization scopes</a>
( run in 2.810 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )