# HG changeset patch # User ymh # Date 1461316817 -7200 # Node ID 338bcc78d431f00a5bb3302c7c88ae7e9ab3c298 # Parent dd6b3adde73bc7c100108e042a6a7be8560046c0 add HandleClient implementation + configuration + tests diff -r dd6b3adde73b -r 338bcc78d431 .hgignore --- a/.hgignore Wed Apr 13 13:38:40 2016 +0200 +++ b/.hgignore Fri Apr 22 11:20:17 2016 +0200 @@ -1,4 +1,5 @@ syntax: regexp +^\.projectile$ ^dev2 ^dev/\.vagrant ^dev/handle @@ -8,6 +9,8 @@ ^server/data ^server/src/\.git.* ^server/src/\.env +^server/src/.dir-locals.el$ +^server/src/.projectile$ ^server/src/composer.phar$ ^server/src/vendor ^server/src/node_modules diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/custom.yaml.tmpl --- a/dev/provisioning/custom.yaml.tmpl Wed Apr 13 13:38:40 2016 +0200 +++ b/dev/provisioning/custom.yaml.tmpl Fri Apr 22 11:20:17 2016 +0200 @@ -28,9 +28,13 @@ # handle host sysconfig::params::hdl_host : 172.16.1.6 +# handle db name +sysconfig::params::hdl_db_name : handle +# handle prefix +sysconfig::params::hdl_prefix : "12345.100" +# handle test prefix +sysconfig::params::hdl_test_prefix : "12345.101" -# handle database -sysconfig::params::hdl_db_name : handle # memory percentage used by memcached sysconfig::params::memcached_max_memory : 25% diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/modules/sysconfig/files/handle/handle_script_corpus_admin_dsa_keys.exp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dev/provisioning/modules/sysconfig/files/handle/handle_script_corpus_admin_dsa_keys.exp Fri Apr 22 11:20:17 2016 +0200 @@ -0,0 +1,53 @@ +#!/bin/expect -f +# +# This Expect script was generated by autoexpect on Wed Mar 23 13:16:38 2016 +# Expect and autoexpect were both written by Don Libes, NIST. +# +# Note that autoexpect does not guarantee a working script. It +# necessarily has to guess about certain things. Two reasons a script +# might fail are: +# +# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, +# etc.) and devices discard or ignore keystrokes that arrive "too +# quickly" after prompts. If you find your new script hanging up at +# one spot, try adding a short sleep just before the previous send. +# Setting "force_conservative" to 1 (see below) makes Expect do this +# automatically - pausing briefly before sending each character. This +# pacifies every program I know of. The -c flag makes the script do +# this in the first place. The -C flag allows you to define a +# character to toggle this mode off and on. +# exp_internal 1 +set force_conservative 0 ;# set to 1 to force conservative mode even if + ;# script wasn't run conservatively originally +if {$force_conservative} { + set send_slow {1 .1} + proc send {ignore arg} { + sleep .1 + exp_send -s -- $arg + } +} + +# +# 2) differing output - Some programs produce different output each time +# they run. The "date" command is an obvious example. Another is +# ftp, if it produces throughput statistics at the end of a file +# transfer. If this causes a problem, delete these patterns or replace +# them with wildcards. An alternative is to use the -p flag (for +# "prompt") which makes Expect only look for the last line of output +# (i.e., the prompt). The -P flag allows you to define a character to +# toggle this mode off and on. +# +# Read the man page for more info. +# +# -Don + + +set timeout -1 +spawn /opt/handle/bin/hdl-keygen -alg dsa -keysize 2048 /var/lib/handle/corpusadmdsapriv.bin /var/lib/handle/corpusadmdsapub.bin +match_max 5000 + + +expect -re "Would you like to encrypt your private key\\\? \\\(y\\\/n\\\) \\\[y\\\] $" +send -- "n\r" + +expect eof diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/modules/sysconfig/manifests/handle.pp --- a/dev/provisioning/modules/sysconfig/manifests/handle.pp Wed Apr 13 13:38:40 2016 +0200 +++ b/dev/provisioning/modules/sysconfig/manifests/handle.pp Fri Apr 22 11:20:17 2016 +0200 @@ -5,6 +5,7 @@ $hdl_web_port = hiera('sysconfig::params::hdl_web_port', $sysconfig::params::hdl_web_port), $hdl_key_pswd = hiera('sysconfig::params::hdl_key_pswd', $sysconfig::params::hdl_key_pswd), $hdl_prefix = hiera('sysconfig::params::hdl_prefix', $sysconfig::params::hdl_prefix), + $hdl_test_prefix = hiera('sysconfig::params::hdl_test_prefix', $sysconfig::params::hdl_test_prefix), $hdl_prefix_admin = hiera('sysconfig::params::hdl_prefix_admin', $sysconfig::params::hdl_prefix_admin), $hdl_db_name = hiera('sysconfig::params::hdl_db_name', $sysconfig::params::hdl_db_name), $db_user = hiera('sysconfig::params::db_user', $sysconfig::params::db_user), @@ -109,6 +110,77 @@ require => [Archive["handle-8.1"], Package['java-install'], Package['expect']] } + exec { "convert-handle-corpus-admin-keys-priv": + command => "/opt/handle/bin/hdl-convert-key /var/lib/handle/corpusadmpriv.bin -o /var/lib/handle/corpusadmpriv.pem", + cwd => "/opt/handle/bin", + creates => "/var/lib/handle/corpusadmpriv.pem", + user => $hdl_user, + require => [Archive["handle-8.1"], Package['java-install'], Exec['init-handle-corpus-admin-keys']] + } + + exec { "convert-handle-corpus-admin-keys-pub": + command => "/opt/handle/bin/hdl-convert-key /var/lib/handle/corpusadmpub.bin -o /var/lib/handle/corpusadmpub.pem", + cwd => "/opt/handle/bin", + creates => "/var/lib/handle/corpusadmpub.pem", + user => $hdl_user, + require => [Archive["handle-8.1"], Package['java-install'], Exec['init-handle-corpus-admin-keys']] + } + + # create handle admin handle dsa keys + file { "/tmp/handle/handle_script_corpus_admin_dsa_keys.exp": + ensure => file, + source => "puppet:///modules/sysconfig/handle/handle_script_corpus_admin_dsa_keys.exp", + owner => "$hdl_user", + group => "$hdl_user", + mode => "0750" + }-> + exec { "init-handle-corpus-admin-dsa-keys": + command => "/tmp/handle/handle_script_corpus_admin_dsa_keys.exp", + cwd => "/opt/handle/bin", + provider => 'shell', + creates => "/var/lib/handle/corpusadmdsapriv.bin", + user => $hdl_user, + notify => Exec['rm-tmp-handle-corpus-admin-dsa-key'], + require => [Archive["handle-8.1"], Package['java-install'], Package['expect']] + } + + + exec { "convert-handle-corpus-admin-dsa-keys-pub": + command => "/opt/handle/bin/hdl-convert-key /var/lib/handle/corpusadmdsapub.bin -o /var/lib/handle/corpusadmdsapub.pem", + cwd => "/opt/handle/bin", + creates => "/var/lib/handle/corpusadmdsapub.pem", + user => $hdl_user, + require => [Archive["handle-8.1"], Package['java-install'], Exec['init-handle-corpus-admin-dsa-keys']] + } + + exec { "convert-handle-corpus-admin-dsa-keys-priv": + command => "/opt/handle/bin/hdl-convert-key /var/lib/handle/corpusadmdsapriv.bin -o /var/lib/handle/corpusadmdsapriv.pem", + cwd => "/opt/handle/bin", + creates => "/var/lib/handle/corpusadmdsapriv.pem", + user => $hdl_user, + require => [Archive["handle-8.1"], Package['java-install'], Exec['init-handle-corpus-admin-dsa-keys']] + } + + + exec { "convert-handle-corpus-admin-cert": + command => "/usr/bin/openssl req -pubkey -x509 -new -sha256 -subj \"/CN=300:${hdl_prefix}\\/${hdl_prefix_admin}\" -key /var/lib/handle/corpusadmpriv.pem | /usr/bin/openssl x509 -inform PEM -out /var/lib/handle/corpusadmcrt.pem", + creates => "/var/lib/handle/corpusadmcrt.pem", + user => $hdl_user, + require => Exec["convert-handle-corpus-admin-keys-priv"] + }-> + exec { "concat-handle-corpus-admin-pkey-cert": + command => "/usr/bin/cat /var/lib/handle/corpusadmpriv.pem /var/lib/handle/corpusadmcrt.pem > /var/lib/handle/corpusadmpkeycrt.pem", + creates => "/var/lib/handle/corpusadmpkeycrt.pem", + user => $hdl_user + } + + exec { "convert-handle-corpus-admin-test-cert": + command => "/usr/bin/openssl req -pubkey -x509 -new -sha256 -subj \"/CN=300:${hdl_test_prefix}\\/${hdl_prefix_admin}\" -key /var/lib/handle/corpusadmpriv.pem | /usr/bin/openssl x509 -inform PEM -out /var/lib/handle/corpusadmcrttest.pem", + creates => "/var/lib/handle/corpusadmcrttest.pem", + user => $hdl_user, + require => Exec["convert-handle-corpus-admin-keys-priv"] + } + file { '/tmp/handle/handle_data.sql.sh': ensure => file, content => template("sysconfig/handle/handle_data.sql.sh.erb"), @@ -208,6 +280,11 @@ refreshonly => true } + exec { "rm-tmp-handle-corpus-admin-dsa-key": + command => "/usr/bin/rm -f /tmp/handle/handle_script_corpus_admin_dsa_keys.exp", + refreshonly => true + } + exec { "open-handle-web-port": command => "firewall-cmd --permanent --add-port=8000/tcp", path => [ '/bin', '/usr/bin', '/usr/local/bin' ] diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/modules/sysconfig/manifests/params.pp --- a/dev/provisioning/modules/sysconfig/manifests/params.pp Wed Apr 13 13:38:40 2016 +0200 +++ b/dev/provisioning/modules/sysconfig/manifests/params.pp Fri Apr 22 11:20:17 2016 +0200 @@ -17,6 +17,7 @@ $hdl_web_port = hiera('sysconfig::params::hdl_web_port', '8000') $hdl_key_pswd = hiera('sysconfig::params::hdl_key_pswd', 'corpus') $hdl_prefix = hiera('sysconfig::params::hdl_prefix', '12345') + $hdl_test_prefix = hiera('sysconfig::params::hdl_test_prefix', '12345.1') $hdl_prefix_admin = hiera('sysconfig::params::hdl_prefix_admin', 'CORPUS_ADMIN') $hdl_db_name = hiera('sysconfig::params::hdl_db_name', 'handle') diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/modules/sysconfig/templates/handle/handle_config.dct.erb --- a/dev/provisioning/modules/sysconfig/templates/handle/handle_config.dct.erb Wed Apr 13 13:38:40 2016 +0200 +++ b/dev/provisioning/modules/sysconfig/templates/handle/handle_config.dct.erb Fri Apr 22 11:20:17 2016 +0200 @@ -36,7 +36,9 @@ "server_config" = { "server_admins" = ( "300:0.NA/<%= @hdl_prefix %>" - ) + "300:0.NA/<%= @hdl_test_prefix %>" + "300:0.NA/<%= @hdl_test_prefix %>_DSA" + ) "replication_admins" = ( "300:0.NA/<%= @hdl_prefix %>" @@ -60,6 +62,7 @@ "auto_homed_prefixes" = ( "0.NA/<%= @hdl_prefix %>" + "0.NA/<%= @hdl_test_prefix %>" ) } diff -r dd6b3adde73b -r 338bcc78d431 dev/provisioning/modules/sysconfig/templates/handle/handle_data.sql.sh.erb --- a/dev/provisioning/modules/sysconfig/templates/handle/handle_data.sql.sh.erb Wed Apr 13 13:38:40 2016 +0200 +++ b/dev/provisioning/modules/sysconfig/templates/handle/handle_data.sql.sh.erb Fri Apr 22 11:20:17 2016 +0200 @@ -1,6 +1,8 @@ #!/usr/bin/env sh handle_admin_pubkey=$(hexdump -ve '1/1 "%.2x"' /var/lib/handle/corpusadmpub.bin); +handle_admin_pubkey_dsa=$(hexdump -ve '1/1 "%.2x"' /var/lib/handle/corpusadmdsapub.bin); + cat < /tmp/handle/handle_data.sql -- MySQL dump 10.16 Distrib 10.1.13-MariaDB, for osx10.11 (x86_64) @@ -25,8 +27,17 @@ LOCK TABLES \`handles\` WRITE; /*!40000 ALTER TABLE \`handles\` DISABLE KEYS */; + INSERT INTO \`handles\` VALUES ('<%= @hdl_prefix %>/<%= @hdl_prefix_admin %>',200,'HS_VLIST','300:0.NA/<%= @hdl_prefix %>; 300:<%= @hdl_prefix %>/<%= @hdl_prefix_admin %>;',0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); INSERT INTO \`handles\` VALUES ('<%= @hdl_prefix %>/<%= @hdl_prefix_admin %>',300,'HS_PUBKEY',0x$handle_admin_pubkey,0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); + +INSERT INTO \`handles\` VALUES ('<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>',200,'HS_VLIST','300:0.NA/<%= @hdl_test_prefix %>; 300:<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>; 300:<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>_DSA',0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); +INSERT INTO \`handles\` VALUES ('<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>',300,'HS_PUBKEY',0x$handle_admin_pubkey,0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); + + +INSERT INTO \`handles\` VALUES ('<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>',200,'HS_VLIST','300:0.NA/<%= @hdl_test_prefix %>; 300:<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>; 300:<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>_DSA',0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); +INSERT INTO \`handles\` VALUES ('<%= @hdl_test_prefix %>/<%= @hdl_prefix_admin %>_DSA',300,'HS_PUBKEY',0x$handle_admin_pubkey_dsa,0,86400,<%= scope.function_time([]) %>,'',1,1,1,0); + /*!40000 ALTER TABLE \`handles\` ENABLE KEYS */; UNLOCK TABLES; @@ -37,6 +48,7 @@ LOCK TABLES \`nas\` WRITE; /*!40000 ALTER TABLE \`nas\` DISABLE KEYS */; INSERT INTO \`nas\` VALUES ('0.NA/<%= @hdl_prefix %>'); +INSERT INTO \`nas\` VALUES ('0.NA/<%= @hdl_test_prefix %>'); /*!40000 ALTER TABLE \`nas\` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff -r dd6b3adde73b -r 338bcc78d431 server/src/.env.example --- a/server/src/.env.example Wed Apr 13 13:38:40 2016 +0200 +++ b/server/src/.env.example Fri Apr 22 11:20:17 2016 +0200 @@ -34,3 +34,28 @@ ELASTICSEARCH_INDEX='corpus' ELASTICSEARCH_SHARDS=1 ELASTICSEARCH_REPLICAS=1 + +HANDLE_HOST=172.16.1.6 +HANDLE_PORT=8000 +HANDLE_PREFIX=12345.100 + +HANDLE_CERT_OR_PKEY="" +HANDLE_PASSWORD=NULL + +HANDLE_TEST_PREFIX=12345.101 + + +HANDLE_TEST_CERT="" +HANDLE_TEST_CERT_PASSWORD=NULL +HANDLE_TEST_CERT_ADMIN_HANDLE="" + +HANDLE_TEST_RSA_KEY="" +HANDLE_TEST_RSA_PASSWORD=NULL +HANDLE_TEST_RSA_ADMIN_HANDLE="" + + +HANDLE_TEST_DSA_KEY="" +HANDLE_TEST_DSA_PASSWORD=NULL +HANDLE_TEST_DSA_ADMIN_HANDLE="" + + diff -r dd6b3adde73b -r 338bcc78d431 server/src/app/Console/Commands/ManageHandle.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/app/Console/Commands/ManageHandle.php Fri Apr 22 11:20:17 2016 +0200 @@ -0,0 +1,116 @@ +documentRepository = $documentRepository; + parent::__construct(); + } + + private function registerHandle($doc) { + + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $stepSize = $this->option('step-size'); + + $passwordKey = $this->option('password'); + if($this->option('ask-password')) { + $password = $this->secret('Private key password?'); + } + + $privateKey = $this->option('key'); + + $privateKeyRes = openssl_pkey_get_private($privateKey, $password); + + + // create handle client + $this->handleClient = new HandleClient($privateKeyRes); + + $this->info('Adding documents handles...'); + + $lastPage = $this->documentRepository->paginateAll($stepSize, 'page')->lastPage(); + $total = $this->documentRepository->getCount(); + + $progressBar = $this->output->createProgressBar($total); + $progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%% - %message%'); + + for ($page=1;$page<=$lastPage;$page++) + { + $docs = $this->documentRepository->paginateAll($stepSize, 'page', $page); + foreach ($docs as $doc){ + $this->registerHandle($doc); + $progressBar->setMessage($doc->getId()); + $progressBar->advance(); + } + } + $progressBar->finish(); + $this->info('Adding handles completed'); + + $this->info('Removing extra handles...'); + + $lastPage = -1; + $page = 0; + $lastPage = 0; + + while($lastPage<0 || $page <= $lastPage) { + $handle_res = $this->handleClient->paginateAll($stepSize, 'page', $page++); + foreach($handle_res as $handle) { + if(is_null($this->documentRepository->get($handle))) { + $this->handleClient->deleteHandle($handle); + } + $progressBar->setMessage($handle); + $progressBar->advance(); + } + } + + $this->info('Removing extra handles completed'); + + + // query ids + // loop on ids + // PUT handle + // query handle + // if not in rdf ids delete + + // delete handle session + } +} diff -r dd6b3adde73b -r 338bcc78d431 server/src/app/Libraries/Handle/HandleClient.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/app/Libraries/Handle/HandleClient.php Fri Apr 22 11:20:17 2016 +0200 @@ -0,0 +1,279 @@ +session = null; + $this->cert = null; + $this->adminId = $adminId; + $this->privateKeyRes = null; + $this->privateKeyOrCert = $privateKeyOrCert; + $this->pkpass = $pkpass; + $this->handleHost = $handleHost; + $this->handlePort = $handlePort; + $this->httpClient = $httpClient; + $this->guzzleOptions = ['verify' => false,]; + } + + public function __destruct () { + $this->close(); + } + + public function close() { + $this->deleteSession(); + $this->freeResources(); + } + + private function getBaseUrl() { + return "https://$this->handleHost:$this->handlePort/api/"; + } + + private function getSessionAuthHeader() { + return "Handle sessionId=$this->session"; + } + + private function generateClientNonce() { + return openssl_random_pseudo_bytes(16); + } + + private function getPrivateKeyRes() { + if(is_null($this->privateKeyRes)) { + $this->privateKeyRes = openssl_pkey_get_private($this->privateKeyOrCert, $this->pkpass); + } + return $this->privateKeyRes; + } + + private function freeResources() { + if(!empty($this->privateKeyRes)) { + $privateKeyRes = $this->privateKeyRes; + $this->privateKeyRes = null; + openssl_free_key($privateKeyRes); + } + } + + private function signBytesDsa($str) { + + openssl_sign($str, $signature, $this->getPrivateKeyRes(), OPENSSL_ALGO_DSS1); + + return $signature; + + } + + private function signBytesRsa($str) { + + $rsa = new RSA(); + $rsa->setHash('sha256'); + if(!empty($this->pkpass)) { + $rsa->setPassword($this->pkpass); + } + $keyContent = $this->privateKeyOrCert; + if(is_file($keyContent)) { + $keyContent = file_get_contents($keyContent); + } + $rsa->loadKey($keyContent); + $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); + + return $rsa->sign($str); + + } + + + + private function createAuthorisationHeaderFromJson($jsonresp) { + # Unpick number once (nonce) and session id from server response (this is the challenge) + $serverNonce = base64_decode($jsonresp['nonce']); + $this->sessionId = $jsonresp['sessionId']; + + # Generate a client number once (cnonce) + $clientNonce = $this->generateClientNonce(); + $clientNonceStr = base64_encode($clientNonce); + + # Our response has to be the signature of server nonce + client nonce + $combinedNonce = $serverNonce . $clientNonce; + if($this->getPrivateKeyRes() === false) { + throw new \Exception("HandleClient: can not read private res"); + } + $keyDetails = openssl_pkey_get_details($this->getPrivateKeyRes()); + if($keyDetails === false) { + throw new \Exception("HandleClient: can not read private key"); + } + if($keyDetails['type']===OPENSSL_KEYTYPE_RSA) { + $signature = $this->signBytesRsa($combinedNonce); + $signAlg = 'SHA256'; + } elseif ($keyDetails['type']===OPENSSL_KEYTYPE_DSA) { + $signature = $this->signBytesDsa($combinedNonce); + $signAlg = 'SHA1'; + } else { + throw new \Exception("HandleClient: $keyDetails[type] Format unknown"); + } + $signatureStr = base64_encode($signature); + + $this->freeResources(); + # Build the authorisation header to send with the request + # Use SHA1 for DSA keys; SHA256 can be used for RSA keys + return $this->buildComplexAuthorizationString($signatureStr, $signAlg, $clientNonceStr); + + } + + private function buildComplexAuthorizationString($signatureString, $signAlg, $clientNonceString) { + return "Handle " . + "version=\"0\", " . + "sessionId=\"$this->sessionId\", " . + "cnonce=\"$clientNonceString\", " . + "id=\"$this->adminId\", " . + "type=\"HS_PUBKEY\", " . + "alg=\"$signAlg\", " . + "signature=\"$signatureString\""; + } + + public function initSession() { + + if(!empty($this->session) || !empty($this->cert)) { + return; + } + + $headers = key_exists('headers', $this->guzzleOptions)?$this->guzzleOptions['headers']:[]; + $headers = array_merge($headers, [ + 'Content-Type' => 'application/json;charset=UTF-8', + ]); + + $certContent = $this->privateKeyOrCert; + if(is_file($certContent)) { + $certContent = file_get_contents($certContent); + } + if(openssl_x509_parse($certContent) !== false) { + if(!empty($this->pkpass)) { + $this->cert = [$this->privateKeyOrCert, $this->pkpass]; + } else { + $this->cert = $this->privateKeyOrCert; + } + $headers['Authorization'] = "Handle clientCert=\"true\""; + } else { + $url = $this->getBaseUrl()."sessions/"; + $challengeRes = $this->httpClient->post($url, ['verify' => false]); + + $jsonResp = json_decode($challengeRes->getBody(), true); + $pkheaders = [ + 'Content-Type' => 'application/json;charset=UTF-8', + 'Authorization' => $this->createAuthorisationHeaderFromJson($jsonResp) + ]; + # Send the request again with a valid correctly signed Authorization header + $sessionResp = $this->httpClient->put($url.'this', ['headers' => $pkheaders, 'verify' => false]); + Log::debug('Create session with auth: '.$sessionResp->getStatusCode().' : '.$sessionResp->getReasonPhrase()); + + $jsonResp = json_decode($sessionResp->getBody(), true); + + $this->session = $jsonResp['authenticated']?$jsonResp['sessionId']:""; + $headers['Authorization'] = "Handle version=\"0\", sessionId=\"$this->session\""; + + } + + $this->guzzleOptions = array_merge($this->guzzleOptions, ['headers' => $headers, 'cert' => $this->cert]); + + } + + // will call a async method. Apart logging we do not really care in the result + public function deleteSession() { + if(empty($this->session)) { + return; + } + $headers = [ + 'Content-Type' => 'application/json;charset=UTF-8', + 'Authorization' => $this->getSessionAuthHeader() + ]; + $url = $this->getBaseUrl()."sessions/this"; + // Do not really care of the response... + $this->httpClient->deleteAsync($url, ['headers' => $headers, 'verify' => false]); + $this->session = null; + + } + + /** + * Paginate all handle as a paginator. + * + * @param int $perPage + * @param string $pageName + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + */ + public function paginateAll($prefix, $perPage = 15, $pageName = 'page', $page = null) { + + $this->initSession(); + + $url = $this->getBaseUrl()."handles"; + + $params = [ + 'prefix' => $prefix, + 'page' => is_null($page)?0:$page-1, + 'pageSize' => $perPage + ]; + + $paginateRes = $this->httpClient->get($url, array_merge($this->guzzleOptions, ['query' => $params])); + + + $paginateJson = json_decode($paginateRes->getBody(), true); + + $total = (int)$paginateJson['totalCount']; + + $results = $paginateJson['handles']; + + return new LengthAwarePaginator($results, $total, $perPage, $page, [ + 'path' => Paginator::resolveCurrentPath(), + 'pageName' => $pageName, + ]); + + } + + public function deleteHandle($handle) { + $this->initSession(); + + $delUrl = $this->getBaseUrl()."handles/$handle"; + $delRes = $this->httpClient->delete($delUrl, $this->guzzleOptions); + + Log::debug('Delete Handle: '.$delRes->getStatusCode().': '.$delRes->getReasonPhrase()); + } + + public function createHandleUrlRecord($handle, $url) { + $this->initSession(); + $currentDate = gmstrftime('%Y-%m-%dT%H:%M:%SZ'); + $handleRecord = [ + 'values' => [ + ['index' => 1, 'ttl' => 86400, 'type' => 'URL', 'timestamp' => $currentDate, 'data' => ['value'=> $url, 'format'=> 'string']], + ['index' => 100, 'ttl' => 86400, 'type' => 'HS_ADMIN', 'timestamp' => $currentDate, 'data' => [ + 'value' => ['index' => 200, 'handle' => $this->adminId], + 'permissions' => '011111110011', + 'format' => 'admin' + ] + ] + ], + 'handle' => $handle, + ]; + + $submitUrl = $this->getBaseUrl()."handles/$handle"; + + $submitRes = $this->httpClient->put($submitUrl, array_merge($this->guzzleOptions, ['json' => $handleRecord, ])); + + Log::debug('Create Handle Url: '.$submitRes->getStatusCode().' : '.$submitRes->getReasonPhrase()); + } + +} diff -r dd6b3adde73b -r 338bcc78d431 server/src/composer.json --- a/server/src/composer.json Wed Apr 13 13:38:40 2016 +0200 +++ b/server/src/composer.json Fri Apr 22 11:20:17 2016 +0200 @@ -4,17 +4,24 @@ "keywords": ["framework", "laravel"], "license": "MIT", "type": "project", + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/phpseclib/phpseclib" + } + ], "require": { "php": ">=5.5.9", "laravel/framework": "5.2.*", "easyrdf/easyrdf": "dev-master", "ml/json-ld": "*", "caseyamcl/phpoaipmh": "~2.4", - "guzzlehttp/guzzle": "~6.1", + "guzzlehttp/guzzle": ">=6.1", "laravelcollective/html": "5.2.*", "shift31/laravel-elasticsearch": "~1.0", "asm89/stack-cors": "dev-master as 0.2.2", - "barryvdh/laravel-cors": "^0.7.3" + "barryvdh/laravel-cors": "^0.7.3", + "phpseclib/phpseclib": "^2.0" }, "require-dev": { "fzaninotto/faker": "~1.4", diff -r dd6b3adde73b -r 338bcc78d431 server/src/composer.lock --- a/server/src/composer.lock Wed Apr 13 13:38:40 2016 +0200 +++ b/server/src/composer.lock Fri Apr 22 11:20:17 2016 +0200 @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0f48e638389cfd8e79cc427ecc70d47d", - "content-hash": "ba1a992f1f0e32f5b520c06aee48327a", + "hash": "bd77aa7395e26dda4693aaf9a7655ec8", + "content-hash": "7a38fd5e8db2e507da6db17d237e62ff", "packages": [ { "name": "asm89/stack-cors", @@ -641,16 +641,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.2.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" + "reference": "31382fef2889136415751badebbd1cb022a4ed72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72", + "reference": "31382fef2889136415751badebbd1cb022a4ed72", "shasum": "" }, "require": { @@ -695,7 +695,7 @@ "stream", "uri" ], - "time": "2016-02-18 21:54:00" + "time": "2016-04-13 19:56:01" }, { "name": "jakub-onderka/php-console-color", @@ -1205,16 +1205,16 @@ }, { "name": "monolog/monolog", - "version": "1.18.2", + "version": "1.19.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09" + "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/064b38c16790249488e7a8b987acf1c9d7383c09", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf", + "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf", "shasum": "" }, "require": { @@ -1279,7 +1279,7 @@ "logging", "psr-3" ], - "time": "2016-04-02 13:12:58" + "time": "2016-04-12 18:29:35" }, { "name": "mtdowling/cron-expression", @@ -1472,6 +1472,98 @@ "time": "2016-03-18 20:34:03" }, { + "name": "phpseclib/phpseclib", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "ba6fb78f727cd09f2a649113b95468019e490585" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ba6fb78f727cd09f2a649113b95468019e490585", + "reference": "ba6fb78f727cd09f2a649113b95468019e490585", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "~4.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.1", + "issues": "https://github.com/phpseclib/phpseclib/issues" + }, + "time": "2016-01-18 17:07:21" + }, + { "name": "pimple/pimple", "version": "v3.0.2", "source": { @@ -2813,12 +2905,12 @@ "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "f0e9aeb13f6231cc5a16aa78b421d543aae06e71" + "reference": "60dcf1a0fe131a5c14350af07f7bc4ace02efbef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/f0e9aeb13f6231cc5a16aa78b421d543aae06e71", - "reference": "f0e9aeb13f6231cc5a16aa78b421d543aae06e71", + "url": "https://api.github.com/repos/padraic/mockery/zipball/60dcf1a0fe131a5c14350af07f7bc4ace02efbef", + "reference": "60dcf1a0fe131a5c14350af07f7bc4ace02efbef", "shasum": "" }, "require": { @@ -2870,7 +2962,7 @@ "test double", "testing" ], - "time": "2016-04-12 09:56:12" + "time": "2016-04-15 13:15:13" }, { "name": "myclabs/deep-copy", @@ -3380,16 +3472,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.3.1", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "34a3acb401ae79deb37bc6e5f5ec3d325b369b4c" + "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34a3acb401ae79deb37bc6e5f5ec3d325b369b4c", - "reference": "34a3acb401ae79deb37bc6e5f5ec3d325b369b4c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2c6da3536035617bae3fe3db37283c9e0eb63ab3", + "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3", "shasum": "" }, "require": { @@ -3451,7 +3543,7 @@ "testing", "xunit" ], - "time": "2016-04-07 07:04:34" + "time": "2016-04-12 16:20:08" }, { "name": "phpunit/phpunit-mock-objects", diff -r dd6b3adde73b -r 338bcc78d431 server/src/config/corpusparole.php --- a/server/src/config/corpusparole.php Wed Apr 13 13:38:40 2016 +0200 +++ b/server/src/config/corpusparole.php Fri Apr 22 11:20:17 2016 +0200 @@ -137,5 +137,8 @@ ], "contentSecurityPolicyHeader" => "Content-Security-Policy-Report-Only", "exportApplicationGlobal" => true - ] + ], + + 'handle_host' => env('HANDLE_HOST'), + 'handle_port' => env('HANDLE_PORT'), ]; diff -r dd6b3adde73b -r 338bcc78d431 server/src/tests/Libraries/Handle/HandleClientIntegrationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/tests/Libraries/Handle/HandleClientIntegrationTest.php Fri Apr 22 11:20:17 2016 +0200 @@ -0,0 +1,222 @@ +handleHost = env('HANDLE_HOST', null); + $this->handlePort = env('HANDLE_PORT', 8000); + + if(empty($this->handleHost)) { + $this->markTestSkipped('Handle host empty'); + } + + $this->testPrefix = env('HANDLE_TEST_PREFIX', null); + if(empty($this->testPrefix)) { + $this->markTestSkipped('Handle test prefix not defined'); + } + + $certPem = env('HANDLE_TEST_CERT', null); + $this->certPemPassword = env('HANDLE_TEST_CERT_PASSWORD', null); + $this->certAdminHandle = env('HANDLE_TEST_CERT_ADMIN_HANDLE', null); + if(empty($certPem) || empty($this->certAdminHandle)) { + $this->markTestSkipped('Handle test certificate or user is empty'); + } + + $dsaPem = env('HANDLE_TEST_DSA_KEY', null); + $this->dsaPemPassword = env('HANDLE_TEST_DSA_PASSWORD', null); + $this->dsaAdminHandle = env('HANDLE_TEST_DSA_ADMIN_HANDLE', null); + if(empty($dsaPem) || empty($this->dsaAdminHandle)) { + $this->markTestSkipped('Handle dsa key or user not set'); + } + $this->dsaAdminRawHandle = str_replace("300:", "", $this->dsaAdminHandle); + + $rsaPem = env('HANDLE_TEST_RSA_KEY', null); + $this->rsaPemPassword = env('HANDLE_TEST_RSA_PASSWORD', null); + $this->rsaAdminHandle = env('HANDLE_TEST_RSA_ADMIN_HANDLE', null); + if(empty($rsaPem) || empty($this->rsaAdminHandle)) { + $this->markTestSkipped('Handle rsa key or user not set'); + } + $this->rsaAdminRawHandle = str_replace("300:", "", $this->rsaAdminHandle); + + $this->filesToDelete = []; + + if(is_file($certPem)) { + $this->certTmpPath = $certPem; + } else { + $this->certTmpPath = tempnam("/tmp", "CERT_TEST"); + array_push($this->filesToDelete,$this->certTmpPath); + file_put_contents($this->certTmpPath, $certPem); + } + + if(is_file($dsaPem)) { + $this->dsaTmpPath = $dsaPem; + } else { + $this->dsaTmpPath = tempnam("/tmp", "DSA_TEST"); + array_push($this->filesToDelete,$this->dsaTmpPath); + file_put_contents($this->dsaTmpPath, $dsaPem); + } + + if(is_file($rsaPem)) { + $this->rsaTmpPath = $rsaPem; + } else { + $this->rsaTmpPath = tempnam("/tmp", "RSA_TEST"); + array_push($this->filesToDelete,$this->rsaTmpPath); + file_put_contents($this->rsaTmpPath, $rsaPem); + } + + // Create a middleware that echoes parts of the request. + // $tapMiddleware = Middleware::tap(function ($request) { + // echo "\n+++++++++++++++++\nREQ HEADERS : ".print_r($request->getHeaders(), true)."\n+++++++++++++++++++\n"; + // echo "\n------------------\nREQ BODY : ".$request->getBody()."\n-------------------\n"; + // }); + + // $stack = HandlerStack::create(); + // $stack->push(Middleware::mapResponse(function ($response) { + // echo "\n+++++++++++++++++\nRESP HEADERS : ".print_r($response->getHeaders(), true)."\n+++++++++++++++++++\n"; + // echo "\n------------------\nRESP BODY : ".$response->getBody()."\n-------------------\n"; + // return $response; + // })); + + // $this->httpClient = new Client(['debug' => true, 'handler' => $tapMiddleware($stack)]); + $this->httpClient = new Client(); + + } + + public function tearDown() { + foreach($this->filesToDelete as $ftd) { + unlink($ftd); + } + + //$this->httpClient->delete("repositories/$this->sesameRepository"); + parent::tearDown(); + } + + + /** + * Test Pagination with DSA key. + * + * @return void + */ + public function testPaginateDSA() + { + $handleClient = new HandleClient('file://'.$this->dsaTmpPath, $this->dsaPemPassword, $this->dsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient); + + $pagination = $handleClient->paginateAll($this->testPrefix); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle"); + $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1"); + + } + + + /** + * Test Pagination with RSA key. + * + * @return void + */ + public function testPaginateRSA() + { + $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient); + + $pagination = $handleClient->paginateAll($this->testPrefix); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle"); + $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1"); + + } + + /** + * Test Pagination with Client Certificate. + * + * @return void + */ + public function testPaginateCert() + { + $handleClient = new HandleClient($this->certTmpPath, $this->certPemPassword, $this->certAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient); + + $pagination = $handleClient->paginateAll($this->testPrefix); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertGreaterThanOrEqual(1, $pagination->count(), "Must have at least 1 handle"); + $this->assertGreaterThanOrEqual(1, $pagination->total(), "Total is at least 1"); + + } + + + /** + * Test Handle creation + */ + public function testCreateHandleUrl() { + + $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient); + + $pagination = $handleClient->paginateAll($this->testPrefix); + $totalPrev = $pagination->total(); + + $handle = strtoupper(uniqid("$this->testPrefix/TEST_HANDLE_CLIENT_")); + + //$handle = "$this->testPrefix/TEST_HANDLE_CLIENT_"; + + $handleClient->createHandleUrlRecord($handle, "http://www.example.com"); + + $pagination = $handleClient->paginateAll($this->testPrefix); + + $this->assertEquals($totalPrev + 1, $pagination->total(), "Must have one more handle"); + + $this->assertContains($handle, $pagination); + + $handleClient->deleteHandle($handle); + + } + + /** + * Test Handle delete + */ + public function testDeleteHandle() { + + $handleClient = new HandleClient('file://'.$this->rsaTmpPath, $this->rsaPemPassword, $this->rsaAdminHandle, $this->handleHost, $this->handlePort, $this->httpClient); + + $pagination = $handleClient->paginateAll($this->testPrefix); + $totalPrev = $pagination->total(); + + $handle = strtoupper(uniqid("$this->testPrefix/TEST_HANDLE_CLIENT_")); + + $handleClient->createHandleUrlRecord($handle, "http://www.example.com"); + $handleClient->deleteHandle($handle); + + + $pagination = $handleClient->paginateAll($this->testPrefix); + + $this->assertEquals($totalPrev, $pagination->total(), "Must have one more handle"); + + $this->assertNotContains($handle, $pagination); + + + } + +} diff -r dd6b3adde73b -r 338bcc78d431 server/src/tests/Libraries/Handle/HandleClientTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/tests/Libraries/Handle/HandleClientTest.php Fri Apr 22 11:20:17 2016 +0200 @@ -0,0 +1,414 @@ +markTestSkipped('Not ready yet'); + + $this->certTmpPath = tempnam("/tmp", "CERT_TEST"); + file_put_contents($this->certTmpPath, HandleClientTest::CERT_PEM); + + } + + public function tearDown() { + unlink($this->certTmpPath); + + parent::tearDown(); + } + + private function initClient($respArray) { + + $this->history = []; + + $mock = new MockHandler($respArray); + $handler = HandlerStack::create($mock); + + $history = Middleware::history($this->history); + + $handler->push($history); + + $this->httpClient = new Client(['handler' => $handler]); + + } + + + /** + * Test Pagination with DSA key. + * + * @return void + */ + public function testPaginateDSA() + { + $responses = [ + new Response(201, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8', + 'Vary' => "Accept-Encoding" + ], + "{\"sessionId\":\"fo79koatgsdyfjkx4c6p3l0c\",\"nonce\":\"10hYzYGE5vf0a1F9eWfk6g==\"}" + ), + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"sessionId\":\"fo79koatgsdyfjkx4c6p3l0c\",\"nonce\":\"10hYzYGE5vf0a1F9eWfk6g==\",\"authenticated\":true,\"id\":\"300:11280.101/CORPUS_ADMIN_DSA\"}" + ), + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"2\",\"page\":0,\"pageSize\":15,\"handles\":[\"11280.101/CORPUS_ADMIN\",\"11280.101/CORPUS_ADMIN_DSA\"]}" + ) + + ]; + $this->initClient($responses); + + $handleClient = new HandleClient(HandleClientTest::DSA_PEM, null, "300:11281.100/CORPUS_ADMIN_DSA", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101'); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(2, $pagination->count(), "Must have only one handle"); + $this->assertEquals(2, $pagination->total(), "Total is one"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/CORPUS_ADMIN','11280.101/CORPUS_ADMIN_DSA'], $handles, "Same handles"); + + $this->assertCount(3, $this->history, "Must have 3 transactions"); + + } + + + /** + * Test Pagination with RSA key. + * + * @return void + */ + public function testPaginateRSA() + { + $responses = [ + new Response(201, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8', + 'Vary' => "Accept-Encoding" + ], + "{\"sessionId\":\"fo79koatgsdyfjkx4c6p3l0c\",\"nonce\":\"10hYzYGE5vf0a1F9eWfk6g==\"}" + ), + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"sessionId\":\"fo79koatgsdyfjkx4c6p3l0c\",\"nonce\":\"10hYzYGE5vf0a1F9eWfk6g==\",\"authenticated\":true,\"id\":\"300:11280.101/CORPUS_ADMIN\"}" + ), + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"2\",\"page\":0,\"pageSize\":15,\"handles\":[\"11280.101/CORPUS_ADMIN\",\"11280.101/CORPUS_ADMIN_DSA\"]}" + ) + + ]; + $this->initClient($responses); + + $handleClient = new HandleClient(HandleClientTest::RSA_PEM, null, "300:11280.101/CORPUS_ADMIN", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101'); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(2, $pagination->count(), "Must have only 2 handle"); + $this->assertEquals(2, $pagination->total(), "Total is 2"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/CORPUS_ADMIN', '11280.101/CORPUS_ADMIN_DSA'], $handles, "Same handles"); + + $this->assertCount(3, $this->history, "Must have 3 transactions"); + + } + + /** + * Test Pagination with Client Certificate. + * + * @return void + */ + public function testPaginateCert() + { + + $responses = [ + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"2\",\"page\":0,\"pageSize\":15,\"handles\":[\"11280.101/CORPUS_ADMIN\",\"11280.101/CORPUS_ADMIN_DSA\"]}" + ) + ]; + + + $this->initClient($responses); + + $handleClient = new HandleClient($this->certTmpPath, null, "300:11280.101/CORPUS_ADMIN", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101'); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(2, $pagination->count(), "Must have only 2 handle"); + $this->assertEquals(2, $pagination->total(), "Total is 2"); + $this->assertFalse($pagination->hasPages(), "Do not have a page"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/CORPUS_ADMIN', '11280.101/CORPUS_ADMIN_DSA'], $handles, "Same handles"); + + $this->assertCount(1, $this->history, "Must have 1 transactions"); + + } + + + /** + * Test Pagination with Client Certificate. + * + * @return void + */ + public function testPaginateFirstPageCert() + { + + $responses = [ + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"12\",\"page\":0,\"pageSize\":5,\"handles\":[\"11280.101/TEST1\",\"11280.101/TEST2\",\"11280.101/TEST3\",\"11280.101/TEST4\",\"11280.101/TEST5\"]}" + ) + ]; + + + $this->initClient($responses); + + $handleClient = new HandleClient($this->certTmpPath, null, "300:11280.101/CORPUS_ADMIN", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101', 5); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(5, $pagination->count(), "Must have only 5 handle"); + $this->assertEquals(5, $pagination->perPage(), "Per page is 5"); + $this->assertEquals(12, $pagination->total(), "Total is 12"); + $this->assertEquals(1, $pagination->currentPage(), "Current page is 1"); + $this->assertEquals(3, $pagination->lastPage(), "Last page is 3"); + $this->assertTrue($pagination->hasMorePages(), "Must have more page"); + $this->assertTrue($pagination->hasPages(), "Have at least page"); + $this->assertEquals(1, $pagination->firstItem(), "First item is 1"); + $this->assertEquals(5, $pagination->lastItem(), "First item is 4"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/TEST1', '11280.101/TEST2', '11280.101/TEST3', '11280.101/TEST4', '11280.101/TEST5'], $handles, "Same handles"); + + + } + + /** + * Test Pagination with Client Certificate. + * + * @return void + */ + public function testPaginateNextPageCert() + { + + $responses = [ + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"12\",\"page\":1,\"pageSize\":5,\"handles\":[\"11280.101/TEST6\",\"11280.101/TEST7\",\"11280.101/TEST8\",\"11280.101/TEST9\",\"11280.101/TEST10\"]}" + ) + ]; + + + $this->initClient($responses); + + $handleClient = new HandleClient($this->certTmpPath, null, "300:11280.101/CORPUS_ADMIN", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101', 5, 'page', 2); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(5, $pagination->count(), "Must have only 5 handle"); + $this->assertEquals(5, $pagination->perPage(), "Per page is 5"); + $this->assertEquals(12, $pagination->total(), "Total is 12"); + $this->assertEquals(2, $pagination->currentPage(), "Current page is 2"); + $this->assertEquals(3, $pagination->lastPage(), "Last page is 3"); + $this->assertTrue($pagination->hasPages(), "Have at least page"); + $this->assertTrue($pagination->hasMorePages(), "Must have more page"); + $this->assertEquals(6, $pagination->firstItem(), "First item is 1"); + $this->assertEquals(10, $pagination->lastItem(), "First item is 4"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/TEST6', '11280.101/TEST7', '11280.101/TEST8', '11280.101/TEST9', '11280.101/TEST10'], $handles, "Same handles"); + + + } + + /** + * Test Pagination with Client Certificate. + * + * @return void + */ + public function testPaginateLastPageCert() + { + + $responses = [ + new Response(200, + [ 'Location' => '/api/sessions/this', + 'Content-Type' => 'application/json;charset=UTF-8' + ], + "{\"responseCode\":1,\"prefix\":\"11280.101\",\"totalCount\":\"12\",\"page\":2,\"pageSize\":5,\"handles\":[\"11280.101/TEST11\",\"11280.101/TEST12\"]}" + ) + ]; + + + $this->initClient($responses); + + $handleClient = new HandleClient($this->certTmpPath, null, "300:11280.101/CORPUS_ADMIN", "172.16.1.6", 8000, $this->httpClient); + + $pagination = $handleClient->paginateAll('11280.101', 5, 'page', 3); + + $this->assertNotNull($pagination); + + $this->assertInstanceOf("Illuminate\Pagination\LengthAwarePaginator", $pagination, "Must be a LengthAwarePaginator"); + + $this->assertEquals(2, $pagination->count(), "Must have only 2 handle"); + $this->assertEquals(5, $pagination->perPage(), "Per page is 5"); + $this->assertEquals(12, $pagination->total(), "Total is 12"); + $this->assertEquals(3, $pagination->currentPage(), "Current page is 3"); + $this->assertEquals(3, $pagination->lastPage(), "Last page is 3"); + $this->assertFalse($pagination->hasMorePages(), "Must have more page"); + $this->assertTrue($pagination->hasPages(), "Have at least page"); + $this->assertEquals(11, $pagination->firstItem(), "First item is 1"); + $this->assertEquals(12, $pagination->lastItem(), "First item is 4"); + + $handles = iterator_to_array($pagination); + $this->assertEquals(['11280.101/TEST11', '11280.101/TEST12'], $handles, "Same handles"); + + + } + + +}