PrivateBin/tst/JsonApiTest.php
Felix J. Ogris 9a61e8fd48 started script for storage backend migrations
todo: GCS

added GCS, no GLOBALS, two methods for saving pastes and comments

use GLOBALS for verbosity again

added getAllPastes() to all storage providers

moved to bin, added --delete options, make use of $store->getAllPastes()

added --delete-* options to help

longopts without -- *sigh*

fixed arguments

drop singleton behaviour to allow multiple backends of the same type simultaneously

remove singleton from Model, collapse loop in migrate.php

comments is not indexed

tests without data singleton

fix

exit if scandir() fails

extended meta doc
2022-11-01 16:02:17 +01:00

306 lines
11 KiB
PHP

<?php
use PrivateBin\Controller;
use PrivateBin\Data\Filesystem;
use PrivateBin\Persistence\ServerSalt;
use PrivateBin\Request;
class JsonApiTest extends PHPUnit_Framework_TestCase
{
protected $_model;
protected $_path;
public function setUp()
{
/* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
if (!is_dir($this->_path)) {
mkdir($this->_path);
}
$this->_model = new Filesystem(array('dir' => $this->_path));
ServerSalt::setStore($this->_model);
$_POST = array();
$_GET = array();
$_SERVER = array();
if ($this->_model->exists(Helper::getPasteId())) {
$this->_model->delete(Helper::getPasteId());
}
$options = parse_ini_file(CONF_SAMPLE, true);
$options['model_options']['dir'] = $this->_path;
Helper::confBackup();
Helper::createIniFile(CONF, $options);
}
public function tearDown()
{
/* Tear Down Routine */
unlink(CONF);
Helper::confRestore();
Helper::rmDir($this->_path);
}
/**
* @runInSeparateProcess
*/
public function testCreate()
{
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPasteJson();
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, $paste);
Request::setInputStream($file);
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
$_SERVER['REQUEST_URI'] = '/';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status');
$this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
$paste = $this->_model->read($response['id']);
$this->assertEquals(
hash_hmac('sha256', $response['id'], $paste['meta']['salt']),
$response['deletetoken'],
'outputs valid delete token'
);
}
/**
* @runInSeparateProcess
*/
public function testPut()
{
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPasteJson();
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, $paste);
Request::setInputStream($file);
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_GET[Helper::getPasteId()] = '';
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'PUT';
$_SERVER['REMOTE_ADDR'] = '::1';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
unlink($file);
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status');
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputted paste ID matches input');
$this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
$paste = $this->_model->read($response['id']);
$this->assertEquals(
hash_hmac('sha256', $response['id'], $paste['meta']['salt']),
$response['deletetoken'],
'outputs valid delete token'
);
}
/**
* @runInSeparateProcess
*/
public function testDelete()
{
$this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_model->read(Helper::getPasteId());
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, json_encode(array(
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
)));
Request::setInputStream($file);
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_GET[Helper::getPasteId()] = '';
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'DELETE';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
unlink($file);
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
}
/**
* @runInSeparateProcess
*/
public function testDeleteWithPost()
{
$this->_model->create(Helper::getPasteId(), Helper::getPaste());
$this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
$paste = $this->_model->read(Helper::getPasteId());
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, json_encode(array(
'pasteid' => Helper::getPasteId(),
'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
)));
Request::setInputStream($file);
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status');
$this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste successfully deleted');
}
/**
* @runInSeparateProcess
*/
public function testRead()
{
$paste = Helper::getPaste();
$this->_model->create(Helper::getPasteId(), $paste);
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_GET[Helper::getPasteId()] = '';
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs success status');
$this->assertEquals(Helper::getPasteId(), $response['id'], 'outputs data correctly');
$this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
$this->assertEquals($paste['ct'], $response['ct'], 'outputs data correctly');
$this->assertEquals($paste['meta']['created'], $response['meta']['created'], 'outputs postdate correctly');
$this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
$this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
}
/**
* @runInSeparateProcess
*/
public function testJsonLdPaste()
{
$_GET['jsonld'] = 'paste';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertEquals(str_replace(
'?jsonld=',
'/?jsonld=',
file_get_contents(PUBLIC_PATH . '/js/paste.jsonld')
), $content, 'outputs data correctly');
}
/**
* @runInSeparateProcess
*/
public function testJsonLdComment()
{
$_GET['jsonld'] = 'comment';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertEquals(str_replace(
'?jsonld=',
'/?jsonld=',
file_get_contents(PUBLIC_PATH . '/js/comment.jsonld')
), $content, 'outputs data correctly');
}
/**
* @runInSeparateProcess
*/
public function testJsonLdPasteMeta()
{
$_GET['jsonld'] = 'pastemeta';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertEquals(str_replace(
'?jsonld=',
'/?jsonld=',
file_get_contents(PUBLIC_PATH . '/js/pastemeta.jsonld')
), $content, 'outputs data correctly');
}
/**
* @runInSeparateProcess
*/
public function testJsonLdCommentMeta()
{
$_GET['jsonld'] = 'commentmeta';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertEquals(str_replace(
'?jsonld=',
'/?jsonld=',
file_get_contents(PUBLIC_PATH . '/js/commentmeta.jsonld')
), $content, 'outputs data correctly');
}
/**
* @runInSeparateProcess
*/
public function testJsonLdInvalid()
{
$_GET['jsonld'] = CONF;
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertEquals('{}', $content, 'does not output nasty data');
}
/**
* @runInSeparateProcess
*/
public function testShortenViaYourls()
{
$mock_yourls_service = $this->_path . DIRECTORY_SEPARATOR . 'yourls.json';
$options = parse_ini_file(CONF, true);
$options['main']['basepath'] = 'https://example.com/path';
$options['main']['urlshortener'] = 'https://example.com/path/shortenviayourls?link=';
$options['yourls']['apiurl'] = $mock_yourls_service;
Helper::createIniFile(CONF, $options);
// the real service answer is more complex, but we only look for the shorturl & statusCode
file_put_contents($mock_yourls_service, '{"shorturl":"https:\/\/example.com\/1","statusCode":200}');
$_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar';
$_GET['link'] = 'https://example.com/path/?foo#bar';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertContains('id="pasteurl" href="https://example.com/1"', $content, 'outputs shortened URL correctly');
}
/**
* @runInSeparateProcess
*/
public function testShortenViaYourlsFailure()
{
$_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar';
$_GET['link'] = 'https://example.com/path/?foo#bar';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$this->assertContains('Error calling YOURLS.', $content, 'outputs error correctly');
}
}