| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # ABSTRACT: A simple interface to ArangoDB REST API | 
| 2 |  |  |  |  |  |  | package Arango::Tango; | 
| 3 |  |  |  |  |  |  | $Arango::Tango::VERSION = '0.019'; | 
| 4 | 5 |  |  | 5 |  | 2106 | use base 'Arango::Tango::API'; | 
|  | 5 |  |  |  |  | 55 |  | 
|  | 5 |  |  |  |  | 2288 |  | 
| 5 | 5 |  |  | 5 |  | 2481 | use Arango::Tango::Database; | 
|  | 5 |  |  |  |  | 13 |  | 
|  | 5 |  |  |  |  | 139 |  | 
| 6 | 5 |  |  | 5 |  | 2219 | use Arango::Tango::Collection; | 
|  | 5 |  |  |  |  | 13 |  | 
|  | 5 |  |  |  |  | 142 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 5 |  |  | 5 |  | 33 | use strict; | 
|  | 5 |  |  |  |  | 11 |  | 
|  | 5 |  |  |  |  | 106 |  | 
| 9 | 5 |  |  | 5 |  | 34 | use warnings; | 
|  | 5 |  |  |  |  | 10 |  | 
|  | 5 |  |  |  |  | 136 |  | 
| 10 | 5 |  |  | 5 |  | 27 | use HTTP::Tiny; | 
|  | 5 |  |  |  |  | 11 |  | 
|  | 5 |  |  |  |  | 95 |  | 
| 11 | 5 |  |  | 5 |  | 27 | use JSON; | 
|  | 5 |  |  |  |  | 8 |  | 
|  | 5 |  |  |  |  | 31 |  | 
| 12 | 5 |  |  | 5 |  | 641 | use MIME::Base64 3.11 'encode_base64url'; | 
|  | 5 |  |  |  |  | 108 |  | 
|  | 5 |  |  |  |  | 273 |  | 
| 13 | 5 |  |  | 5 |  | 31 | use URI::Encode qw(uri_encode); | 
|  | 5 |  |  |  |  | 10 |  | 
|  | 5 |  |  |  |  | 2178 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | BEGIN { | 
| 17 |  |  |  |  |  |  | Arango::Tango::API::_install_methods "Arango::Tango" => { | 
| 18 |  |  |  |  |  |  | engine                  => { rest => [ get => '_api/engine' ] }, | 
| 19 |  |  |  |  |  |  | cluster_endpoints       => { rest => [ get => '_api/cluster/endpoints' ] }, | 
| 20 |  |  |  |  |  |  | server_id               => { rest => [ get => '_admin/server/id' ] }, | 
| 21 |  |  |  |  |  |  | status                  => { rest => [ get => '_admin/status' ] }, | 
| 22 |  |  |  |  |  |  | time                    => { rest => [ get => '_admin/time' ] }, | 
| 23 |  |  |  |  |  |  | statistics              => { rest => [ get => '_admin/statistics' ] }, | 
| 24 |  |  |  |  |  |  | statistics_description  => { rest => [ get => '_admin/statistics-description' ] }, | 
| 25 |  |  |  |  |  |  | target_version          => { rest => [ get => '_admin/database/target-version' ] }, | 
| 26 |  |  |  |  |  |  | log_level               => { rest => [ get => '_admin/log/level' ] }, | 
| 27 |  |  |  |  |  |  | server_role             => { rest => [ get => '_admin/server/role' ] }, | 
| 28 |  |  |  |  |  |  | server_mode             => { rest => [ get => '_admin/server/mode' ] }, | 
| 29 |  |  |  |  |  |  | server_availability     => { rest => [ get => '_admin/server/availability' ] }, | 
| 30 |  |  |  |  |  |  | list_users              => { rest => [ get => '_api/user' ] }, | 
| 31 |  |  |  |  |  |  | current_database        => { rest => [ get => '_api/database/current' ] }, | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | version                 => { rest => [ get => '_api/version' ], schema => {  details => { type => 'boolean' } }}, | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | delete_database         => { | 
| 36 |  |  |  |  |  |  | signature => [ 'name' ], | 
| 37 |  |  |  |  |  |  | rest => [ delete => '_api/database/{name}' ] | 
| 38 |  |  |  |  |  |  | }, | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | delete_user             => { | 
| 41 |  |  |  |  |  |  | signature => [ 'username' ], | 
| 42 |  |  |  |  |  |  | rest => [ delete => '_api/user/{username}' ] | 
| 43 |  |  |  |  |  |  | }, | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | replace_user            => { | 
| 46 |  |  |  |  |  |  | signature => [ 'username' ], | 
| 47 |  |  |  |  |  |  | rest => [ put => '_api/user/{username}' ], | 
| 48 |  |  |  |  |  |  | schema => { password => { type => 'string'  }, | 
| 49 |  |  |  |  |  |  | active   => { type => 'boolean' }, | 
| 50 |  |  |  |  |  |  | extra    => { type => 'object', additionalProperties => 1 }}}, | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | user                    => { | 
| 53 |  |  |  |  |  |  | signature => [ 'username' ], | 
| 54 |  |  |  |  |  |  | rest => [ get => '_api/user/{username}' ] }, | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | update_user             => { | 
| 57 |  |  |  |  |  |  | signature => [ 'user' ], | 
| 58 |  |  |  |  |  |  | rest => [ patch => '_api/user/{user}' ], | 
| 59 |  |  |  |  |  |  | schema => { password => { type => 'string'  }, | 
| 60 |  |  |  |  |  |  | active   => { type => 'boolean' }, | 
| 61 |  |  |  |  |  |  | extra    => { type => 'object', additionalProperties => 1 }}}, | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | user_databases  => { | 
| 64 |  |  |  |  |  |  | signature => [ 'username' ], | 
| 65 |  |  |  |  |  |  | rest      => [ get => '_api/user/{username}/database' ], | 
| 66 |  |  |  |  |  |  | schema    => { full => {type => 'boolean' }}}, | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | get_access_level => { | 
| 69 |  |  |  |  |  |  | signature => ['username','database','?collection'], | 
| 70 |  |  |  |  |  |  | rest      => [ get => '_api/user/{username}/database/{database}/{collection}' ], | 
| 71 |  |  |  |  |  |  | }, | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | clear_access_level => { | 
| 74 |  |  |  |  |  |  | signature => ['username','database','?collection'], | 
| 75 |  |  |  |  |  |  | rest      => [ delete => '_api/user/{username}/database/{database}/{collection}' ], | 
| 76 |  |  |  |  |  |  | }, | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | set_access_level => { | 
| 79 |  |  |  |  |  |  | signature => ['username', 'grant', 'database', '?collection'], | 
| 80 |  |  |  |  |  |  | rest      => [ put => '_api/user/{username}/database/{database}/{collection}' ], | 
| 81 |  |  |  |  |  |  | schema    => { grant => { type => 'string', enum => [qw'rw ro none'], default => 'none' }}, | 
| 82 |  |  |  |  |  |  | }, | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | create_database => { | 
| 85 |  |  |  |  |  |  | signature => [ 'name' ], | 
| 86 |  |  |  |  |  |  | rest => [ post => '_api/database' ], | 
| 87 |  |  |  |  |  |  | schema  => { name  => { type => 'string' }, | 
| 88 |  |  |  |  |  |  | users => { | 
| 89 |  |  |  |  |  |  | type => 'array', | 
| 90 |  |  |  |  |  |  | items => { | 
| 91 |  |  |  |  |  |  | type => 'object', | 
| 92 |  |  |  |  |  |  | additionalProperties => 0, | 
| 93 |  |  |  |  |  |  | properties => { | 
| 94 |  |  |  |  |  |  | username => { type => 'string' }, | 
| 95 |  |  |  |  |  |  | passwd   => { type => 'string'}, | 
| 96 |  |  |  |  |  |  | active   => { type => 'boolean' }, | 
| 97 |  |  |  |  |  |  | extra    => { type => 'object', additionalProperties => 1 } | 
| 98 |  |  |  |  |  |  | }}}}, | 
| 99 |  |  |  |  |  |  | builder => sub { | 
| 100 | 0 |  |  |  |  |  | my ($self, %params) = @_; | 
| 101 | 0 |  |  |  |  |  | return Arango::Tango::Database->_new(arango => $self, 'name' => $params{name}); | 
| 102 |  |  |  |  |  |  | }, | 
| 103 |  |  |  |  |  |  | }, | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 5 |  |  | 5 |  | 549 | create_user => { | 
| 106 |  |  |  |  |  |  | signature => [ 'user' ], | 
| 107 |  |  |  |  |  |  | rest => [ post => '_api/user'], | 
| 108 |  |  |  |  |  |  | schema => { | 
| 109 |  |  |  |  |  |  | password => { type => 'string'  }, | 
| 110 |  |  |  |  |  |  | active   => { type => 'boolean' }, | 
| 111 |  |  |  |  |  |  | user     => { type => 'string'  }, | 
| 112 |  |  |  |  |  |  | extra    => { type => 'object', additionalProperties => 1 }, | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  | }, | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | log => { | 
| 117 |  |  |  |  |  |  | rest => [ get => '_admin/log' ], | 
| 118 |  |  |  |  |  |  | schema => { | 
| 119 |  |  |  |  |  |  | upto   => { type => 'string', default => 'info', enum => [qw'fatal error warning info debug 0 1 2 3 4'] }, | 
| 120 |  |  |  |  |  |  | level  => { type => 'string', default => 'info', enum => [qw'fatal error warning info debug'] }, | 
| 121 |  |  |  |  |  |  | size   => { type => 'integer', minimum => 0 }, | 
| 122 |  |  |  |  |  |  | offset => { type => 'integer', minimum => 0 }, | 
| 123 |  |  |  |  |  |  | search => { type => 'string' }, | 
| 124 |  |  |  |  |  |  | sort   => { type => 'string', default => 'asc', enum => [qw'asc desc'] }, # asc, desc | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  | }; | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | sub new { | 
| 134 | 0 |  |  | 0 | 1 |  | my ($package, %opts) = @_; | 
| 135 | 0 |  |  |  |  |  | my $self = bless { %opts } => $package; | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 0 |  | 0 |  |  |  | $self->{host} ||= $ENV{ARANGO_DB_HOST} || "localhost"; | 
|  |  |  | 0 |  |  |  |  | 
| 138 | 0 |  | 0 |  |  |  | $self->{port} ||= $ENV{ARANGO_DB_PORT} || 8529; | 
|  |  |  | 0 |  |  |  |  | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 0 |  | 0 |  |  |  | $self->{scheme} ||= $ENV{ARANGO_DB_SCHEME} || 'http'; | 
|  |  |  | 0 |  |  |  |  | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 0 |  | 0 |  |  |  | $self->{username} ||= $ENV{ARANGO_DB_USERNAME} || "root"; | 
|  |  |  | 0 |  |  |  |  | 
| 143 | 0 |  | 0 |  |  |  | $self->{password} ||= $ENV{ARANGO_DB_PASSWORD} || ""; | 
|  |  |  | 0 |  |  |  |  | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | $self->{headers} = { | 
| 146 | 0 |  |  |  |  |  | Authorization => $self->_auth, | 
| 147 |  |  |  |  |  |  | Accept => 'application/json', | 
| 148 |  |  |  |  |  |  | }; | 
| 149 | 0 |  |  |  |  |  | $self->{http} = HTTP::Tiny->new(default_headers => $self->{headers}); | 
| 150 |  |  |  |  |  |  |  | 
| 151 | 0 |  |  |  |  |  | return $self; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | sub _auth { | 
| 155 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 156 | 0 |  |  |  |  |  | return "Basic " . encode_base64url( $self->{username} . ":" . $self->{password} ); | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | sub database { | 
| 160 | 0 |  |  | 0 | 1 |  | my ($self, $name) = @_; | 
| 161 | 0 |  |  |  |  |  | my $databases = $self->list_databases; | 
| 162 | 0 | 0 |  |  |  |  | if (grep {$name eq $_} @$databases) { | 
|  | 0 |  |  |  |  |  |  | 
| 163 | 0 |  |  |  |  |  | return Arango::Tango::Database->_new( arango => $self, name => $name); | 
| 164 |  |  |  |  |  |  | } else { | 
| 165 | 0 |  |  |  |  |  | die "Arango::Tango | Database not found." | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | sub list_databases { | 
| 170 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 171 | 0 |  |  |  |  |  | return  $self->_api('accessible_databases')->{result}; | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | sub http_status { | 
| 176 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 177 | 0 | 0 |  |  |  |  | return exists($self->{last_error}) ? $self->{last_error} : 0; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | 1; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | __END__ |