rewritten API models
This commit is contained in:
parent
0ae62f31f1
commit
09c8310bb6
14 changed files with 615 additions and 370 deletions
|
@ -1,247 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* handles the data for api.php
|
|
||||||
*/
|
|
||||||
class Datahandler {
|
|
||||||
// (string) folder to store data in relative to position of api.php
|
|
||||||
// webserver has to have write access to this folder
|
|
||||||
// must end with a slash
|
|
||||||
// (int) length of ids used to identify data
|
|
||||||
const ID_LENGTH = 10;
|
|
||||||
|
|
||||||
// (string) characters used to generate a new id
|
|
||||||
const ID_CHARACTERS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
// check if data folder exists and is writeable
|
|
||||||
// if data folder does not exist, try to create it
|
|
||||||
if (!is_writeable(DATA_FOLDER)) {
|
|
||||||
|
|
||||||
// check if data folder exists
|
|
||||||
if (!file_exists(DATA_FOLDER)) {
|
|
||||||
|
|
||||||
// try to create data folder
|
|
||||||
if(mkdir(DATA_FOLDER)) {
|
|
||||||
|
|
||||||
// put empty index.html in data folder to prevent directory listing
|
|
||||||
file_put_contents(DATA_FOLDER . "index.html", '');
|
|
||||||
|
|
||||||
// check if newly created data folder is writeable
|
|
||||||
if (!is_writeable(DATA_FOLDER)) {
|
|
||||||
throw new Exception("data folder created but is not writeable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Exception("data folder does not exists and can not be created");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Exception("data folder already exists but is not writeable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deletePoll($poll_id) {
|
|
||||||
$folder = DATA_FOLDER . "/" . $poll_id;
|
|
||||||
$user_folder = $folder . "/user";
|
|
||||||
|
|
||||||
// delete user folder
|
|
||||||
if (is_dir($user_folder)) {
|
|
||||||
$dir = opendir($user_folder);
|
|
||||||
while(false !== ($file = readdir($dir))) {
|
|
||||||
if($file === '.' || $file === '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
unlink($user_folder . '/' . $file);
|
|
||||||
}
|
|
||||||
closedir($dir);
|
|
||||||
rmdir($user_folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink($folder . '/poll_data');
|
|
||||||
|
|
||||||
rmdir($folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* read poll data
|
|
||||||
* return false, if there is no data with this id or if data could not be read
|
|
||||||
*/
|
|
||||||
public function get($poll_id) {
|
|
||||||
// file with absolut path
|
|
||||||
$folder = DATA_FOLDER . "/" . $poll_id;
|
|
||||||
$poll_file = $folder . "/poll_data";
|
|
||||||
|
|
||||||
// check if file exists and is readable
|
|
||||||
if (!is_readable($poll_file)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$poll_data_json = file_get_contents($poll_file);
|
|
||||||
|
|
||||||
$poll_data = json_decode($poll_data_json);
|
|
||||||
|
|
||||||
// check expiration date
|
|
||||||
if (
|
|
||||||
!empty($poll_data->poll->serverExpirationDate) &&
|
|
||||||
self::isExpired($poll_data->poll->serverExpirationDate)
|
|
||||||
) {
|
|
||||||
$this->deletePoll($poll_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set id to poll
|
|
||||||
$poll_data->poll->id = $poll_id;
|
|
||||||
|
|
||||||
$poll_data->poll->users = array();
|
|
||||||
|
|
||||||
// check for existing user
|
|
||||||
$user_folder = $folder . "/user";
|
|
||||||
if (is_dir($user_folder)) {
|
|
||||||
// read all existing user data and embedded it into poll
|
|
||||||
$files = scandir($user_folder);
|
|
||||||
|
|
||||||
// natural sorting of files array to have it in creation order
|
|
||||||
natsort($files);
|
|
||||||
|
|
||||||
// iterate over all files in folder
|
|
||||||
foreach ($files as $file) {
|
|
||||||
// embedding full user data
|
|
||||||
// read file and extend poll_data;
|
|
||||||
$user_data_json = file_get_contents($user_folder . "/" . $file);
|
|
||||||
|
|
||||||
if ($user_data_json) {
|
|
||||||
$user_data = json_decode($user_data_json);
|
|
||||||
|
|
||||||
// extend id to user object
|
|
||||||
$user_data->user->id = $poll_id . '_' . $file;
|
|
||||||
|
|
||||||
// embedd user into poll
|
|
||||||
$poll_data->poll->users[] = $user_data->user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not include properties prefixed by server in response
|
|
||||||
foreach ($poll_data->poll as $key => $value) {
|
|
||||||
if(strpos($key, "server") === 0) {
|
|
||||||
unset($poll_data->poll->$key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_encode($poll_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* generates a new Id
|
|
||||||
*/
|
|
||||||
protected function generateNewId()
|
|
||||||
{
|
|
||||||
// generate random string
|
|
||||||
$randomString = '';
|
|
||||||
for ($i = 0; $i < self::ID_LENGTH; $i++) {
|
|
||||||
$characters = self::ID_CHARACTERS;
|
|
||||||
$randomString .= $characters[rand(0, strlen($characters) - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if id is already used, generate new one if necessary
|
|
||||||
if (file_exists(DATA_FOLDER."/".$randomString)) {
|
|
||||||
$randomString = $this->generateNewId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $randomString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get next user id for given poll
|
|
||||||
*/
|
|
||||||
protected function getNextUserId($poll_id)
|
|
||||||
{
|
|
||||||
$user_folder = DATA_FOLDER . "/" . $poll_id . "/user";
|
|
||||||
|
|
||||||
// check if user folder exists
|
|
||||||
if (!file_exists($user_folder)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all files in user folder
|
|
||||||
$files = scandir($user_folder);
|
|
||||||
|
|
||||||
// get highest existing id
|
|
||||||
$highest_id = 0;
|
|
||||||
foreach ($files as $f) {
|
|
||||||
if ((int) $f > $highest_id) {
|
|
||||||
$highest_id = (int) $f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $highest_id + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function isExpired ($expirationDateString) {
|
|
||||||
return
|
|
||||||
( $expirationDate = DateTime::createFromFormat('Y-m-d\TH:i:s.uO', $expirationDateString) ) &&
|
|
||||||
$expirationDate < new DateTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* store poll data
|
|
||||||
* returns new id or false on error
|
|
||||||
*/
|
|
||||||
public function writePoll ($data) {
|
|
||||||
// get a new id
|
|
||||||
$new_id = $this->generateNewId();
|
|
||||||
|
|
||||||
$folder = DATA_FOLDER."/".$new_id;
|
|
||||||
$file = $folder . "/poll_data";
|
|
||||||
|
|
||||||
// create folder for new poll
|
|
||||||
if (!mkdir($folder)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write poll data
|
|
||||||
if (file_put_contents($file, $data, LOCK_EX) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* stores user data belonging to poll
|
|
||||||
* returns new id or false on error
|
|
||||||
*/
|
|
||||||
public function writeUser ($poll_id, $data) {
|
|
||||||
// get a new id
|
|
||||||
$new_id = $this->getNextUserId($poll_id);
|
|
||||||
|
|
||||||
// check if poll exists
|
|
||||||
if (!is_dir(DATA_FOLDER."/".$poll_id)) {
|
|
||||||
throw new Exception("poll does not exists");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$folder = DATA_FOLDER."/".$poll_id."/user";
|
|
||||||
$file = $folder . "/" . $new_id;
|
|
||||||
|
|
||||||
// check if user folder allready exists
|
|
||||||
if (!file_exists($folder)) {
|
|
||||||
|
|
||||||
// user folder does not exists, try to create it
|
|
||||||
if (!mkdir($folder)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write user data
|
|
||||||
if (file_put_contents($file, $data, LOCK_EX) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $new_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
236
api/classes/model.php
Normal file
236
api/classes/model.php
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Model {
|
||||||
|
const ENCRYPTED_PROPERTIES = [];
|
||||||
|
const PLAIN_PROPERTIES = [];
|
||||||
|
const SERVER_PROPERTIES = [];
|
||||||
|
|
||||||
|
protected $data;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
if(!defined('DATA_FOLDER')) {
|
||||||
|
throw new Exception('DATA_FOLDER is not defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_writable(DATA_FOLDER)) {
|
||||||
|
throw new Exception('DATA_FOLDER (' . DATA_FOLDER . ') is not writeable');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data = new stdClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function convertFromStorage($string) {
|
||||||
|
return json_decode($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function convertToStorage($dataObj) {
|
||||||
|
$obj = clone($dataObj);
|
||||||
|
unset($obj->id);
|
||||||
|
return json_encode($obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get new object
|
||||||
|
*/
|
||||||
|
public static function create($data) {
|
||||||
|
if (!is_object($data)) {
|
||||||
|
throw new Exception('data must be an object');
|
||||||
|
}
|
||||||
|
|
||||||
|
$properties = array_merge(
|
||||||
|
static::ENCRYPTED_PROPERTIES,
|
||||||
|
static::PLAIN_PROPERTIES,
|
||||||
|
static::SERVER_PROPERTIES
|
||||||
|
);
|
||||||
|
|
||||||
|
// check if all properties exist on data object
|
||||||
|
foreach ($properties as $property) {
|
||||||
|
if (!property_exists($data, $property)) {
|
||||||
|
throw new Exception('property ' . $property . ' does not exist on data object');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that encrypted properties are valid AES
|
||||||
|
foreach (static::ENCRYPTED_PROPERTIES as $encryptedProperty) {
|
||||||
|
if (!self::isValidSJCL($data->$encryptedProperty)) {
|
||||||
|
throw new Exception('property ' . $property . ' is not valid AES');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$modelName = get_called_class();
|
||||||
|
$model = new $modelName;
|
||||||
|
|
||||||
|
foreach ($properties as $property) {
|
||||||
|
$model->set($property, $data->$property);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function export() {
|
||||||
|
$data = new stdClass();
|
||||||
|
$publicProperties = array_merge(
|
||||||
|
static::ENCRYPTED_PROPERTIES,
|
||||||
|
static::PLAIN_PROPERTIES,
|
||||||
|
array('id')
|
||||||
|
);
|
||||||
|
foreach($publicProperties as $publicProperty) {
|
||||||
|
$data->$publicProperty = $this->get($publicProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method_exists($this, 'includeRelationships')) {
|
||||||
|
$this->includeRelationships($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function get($property) {
|
||||||
|
if(property_exists($this->data, $property)) {
|
||||||
|
return $this->data->$property;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDir() {
|
||||||
|
throw new Exception ('getDir must be implemented by model');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPath() {
|
||||||
|
throw new Exception ('getPath must be implemented by model');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if a json string is a proper SJCL encrypted message.
|
||||||
|
* False if format is incorrect.
|
||||||
|
*
|
||||||
|
* Taken from: https://github.com/sebsauvage/ZeroBin/blob/8cae64d6eab99fb0d31868df77846285c0958ed0/index.php#L76-L109
|
||||||
|
* Copyright (c) 2012 Sébastien SAUVAGE (sebsauvage.net)
|
||||||
|
* License: https://github.com/sebsauvage/ZeroBin/blob/8cae64d6eab99fb0d31868df77846285c0958ed0/README.md
|
||||||
|
*/
|
||||||
|
private static function isValidSJCL($jsonstring) {
|
||||||
|
$accepted_keys=array('iv','v','iter','ks','ts','mode','adata','cipher','salt','ct');
|
||||||
|
|
||||||
|
// Make sure content is valid json
|
||||||
|
$decoded = json_decode($jsonstring);
|
||||||
|
if ($decoded==null) return false;
|
||||||
|
$decoded = (array)$decoded;
|
||||||
|
|
||||||
|
// Make sure required fields are present
|
||||||
|
foreach($accepted_keys as $k)
|
||||||
|
{
|
||||||
|
if (!array_key_exists($k,$decoded)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure some fields are base64 data
|
||||||
|
if (base64_decode($decoded['iv'],$strict=true)==null) { return false; }
|
||||||
|
if (base64_decode($decoded['salt'],$strict=true)==null) { return false; }
|
||||||
|
if (base64_decode($decoded['cipher'],$strict=true)==null) { return false; }
|
||||||
|
|
||||||
|
// Make sure no additionnal keys were added.
|
||||||
|
if (count(array_intersect(array_keys($decoded),$accepted_keys))!=10) { return false; }
|
||||||
|
|
||||||
|
// Reject data if entropy is too low
|
||||||
|
$ct = base64_decode($decoded['ct'], $strict=true);
|
||||||
|
if (strlen($ct) > strlen(gzdeflate($ct))) return false;
|
||||||
|
|
||||||
|
// Make sure some fields have a reasonable size.
|
||||||
|
if (strlen($decoded['iv'])>24) return false;
|
||||||
|
if (strlen($decoded['salt'])>14) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restore object from storage
|
||||||
|
*/
|
||||||
|
public static function restore($id) {
|
||||||
|
if (!static::isValidId($id)) {
|
||||||
|
throw new Exception($id . ' is not a valid id');
|
||||||
|
}
|
||||||
|
|
||||||
|
$modelName = get_called_class();
|
||||||
|
$model = new $modelName;
|
||||||
|
|
||||||
|
$model->set('id', $id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$storageObject = file_get_contents(
|
||||||
|
$model->getPath()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($storageObject === false) {
|
||||||
|
// no poll with this id
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
// no poll with this id
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = self::convertFromStorage($storageObject);
|
||||||
|
|
||||||
|
$properties = array_merge(
|
||||||
|
static::ENCRYPTED_PROPERTIES,
|
||||||
|
static::PLAIN_PROPERTIES,
|
||||||
|
static::SERVER_PROPERTIES
|
||||||
|
);
|
||||||
|
foreach ($properties as $property) {
|
||||||
|
$model->set($property, $data->$property);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save object to storage
|
||||||
|
* gives back new id
|
||||||
|
*/
|
||||||
|
public function save() {
|
||||||
|
// create dir for data if it does not exists
|
||||||
|
$counter = 0;
|
||||||
|
while (true) {
|
||||||
|
$this->set('id', $this->generateNewId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!is_dir($this->getDir())) {
|
||||||
|
if (mkdir($this->getDir()) === false) {
|
||||||
|
throw new Exception('could not create the directory for data object');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_writable($this->getDir())) {
|
||||||
|
throw new Exception('dir is not writeable');
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
if(
|
||||||
|
file_put_contents(
|
||||||
|
$this->getPath(),
|
||||||
|
self::convertToStorage($this->data),
|
||||||
|
LOCK_EX
|
||||||
|
) === false
|
||||||
|
) {
|
||||||
|
throw new Exception('write failed...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
if ($counter > 5) {
|
||||||
|
throw new Exception('write failed more than five times', 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$counter++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// successfully run
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set($key, $value) {
|
||||||
|
$this->data->$key = $value;
|
||||||
|
}
|
||||||
|
}
|
76
api/classes/poll.php
Normal file
76
api/classes/poll.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'model.php';
|
||||||
|
require_once 'user.php';
|
||||||
|
|
||||||
|
class Poll extends model {
|
||||||
|
const ENCRYPTED_PROPERTIES = [
|
||||||
|
'anonymousUser',
|
||||||
|
'answers',
|
||||||
|
'answerType',
|
||||||
|
'creationDate',
|
||||||
|
'description',
|
||||||
|
'expirationDate',
|
||||||
|
'forceAnswer',
|
||||||
|
'isDateTime',
|
||||||
|
'options',
|
||||||
|
'pollType',
|
||||||
|
'timezone',
|
||||||
|
'title'
|
||||||
|
];
|
||||||
|
|
||||||
|
const ID_LENGTH = 10;
|
||||||
|
const ID_CHARACTERS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
|
||||||
|
const PLAIN_PROPERTIES = [
|
||||||
|
'version'
|
||||||
|
];
|
||||||
|
|
||||||
|
const SERVER_PROPERTIES = [
|
||||||
|
'serverExpirationDate'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected function generateNewId() {
|
||||||
|
$characters = self::ID_CHARACTERS;
|
||||||
|
$randomString = '';
|
||||||
|
for ($i = 0; $i < self::ID_LENGTH; $i++) {
|
||||||
|
$randomString .= $characters[rand(0, strlen($characters) - 1)];
|
||||||
|
}
|
||||||
|
return $randomString;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDir() {
|
||||||
|
return DATA_FOLDER . $this->get('id') . '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPath() {
|
||||||
|
return $this->getDir() . 'poll_data';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getUsers() {
|
||||||
|
$users = [];
|
||||||
|
|
||||||
|
$userDir = DATA_FOLDER . $this->get('id') . '/users/';
|
||||||
|
if (is_dir($userDir)) {
|
||||||
|
$dir = opendir($userDir);
|
||||||
|
while(false !== ($file = readdir($dir))) {
|
||||||
|
if($file === '.' || $file === '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$users[] = User::restore($this->get('id') . '_' . $file)->export();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function includeRelationships(&$data) {
|
||||||
|
$data->users = $this->getUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isValidId($id) {
|
||||||
|
$idCharacters = str_split($id);
|
||||||
|
return count(array_diff($idCharacters, str_split(self::ID_CHARACTERS))) === 0;
|
||||||
|
}
|
||||||
|
}
|
67
api/classes/user.php
Normal file
67
api/classes/user.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'model.php';
|
||||||
|
require_once 'poll.php';
|
||||||
|
|
||||||
|
class User extends Model {
|
||||||
|
const ENCRYPTED_PROPERTIES = [
|
||||||
|
'creationDate',
|
||||||
|
'name',
|
||||||
|
'selections'
|
||||||
|
];
|
||||||
|
|
||||||
|
const PLAIN_PROPERTIES = [
|
||||||
|
'poll',
|
||||||
|
'version'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected function generateNewId() {
|
||||||
|
$userDir = $this->getDir();
|
||||||
|
|
||||||
|
// check if user folder exists
|
||||||
|
if (!file_exists($userDir)) {
|
||||||
|
return $this->get('poll') . '_0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all files in user folder
|
||||||
|
$files = scandir($userDir);
|
||||||
|
|
||||||
|
// get highest existing id
|
||||||
|
$highestId = 0;
|
||||||
|
foreach ($files as $f) {
|
||||||
|
if ((int) $f > $highestId) {
|
||||||
|
$highestId = (int) $f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->get('poll') .
|
||||||
|
'_' .
|
||||||
|
(string) $highestId + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDir() {
|
||||||
|
if ($this->get('poll') !== null) {
|
||||||
|
$pollId = $this->get('poll');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$pollId = explode('_', $this->get('id'))[0];
|
||||||
|
}
|
||||||
|
return DATA_FOLDER . $pollId . '/users/';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPath() {
|
||||||
|
return $this->getDir() . explode('_', $this->get('id'))[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function includeRelationships(&$data) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isValidId($id) {
|
||||||
|
$parts = explode('_', $id);
|
||||||
|
|
||||||
|
return count($parts) === 2 &&
|
||||||
|
Poll::isValidId($parts[0]) &&
|
||||||
|
intval($parts[1]) == $parts[1];
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,13 +12,16 @@ else {
|
||||||
}
|
}
|
||||||
|
|
||||||
require 'vendor/autoload.php';
|
require 'vendor/autoload.php';
|
||||||
require 'classes/datahandler.php';
|
require_once 'classes/poll.php';
|
||||||
|
require_once 'classes/user.php';
|
||||||
|
|
||||||
function pollIdIsValid($pollId) {
|
function pollIdIsValid($pollId) {
|
||||||
return preg_match('/[^A-Za-z0-9]/', $pollId) === 0;
|
return preg_match('/[^A-Za-z0-9]/', $pollId) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$app = new \Slim\Slim();
|
$app = new \Slim\Slim(array(
|
||||||
|
'debug' => false
|
||||||
|
));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* default response headers
|
* default response headers
|
||||||
|
@ -27,68 +30,68 @@ $app->response->headers->set('Content-Type', 'application/json; charset=utf-8');
|
||||||
// prevent Internet Explorer from caching AJAX requests
|
// prevent Internet Explorer from caching AJAX requests
|
||||||
$app->expires('-1');
|
$app->expires('-1');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* api endpoints
|
||||||
|
*/
|
||||||
$app->get('/polls/:id', function ($pollId) use ($app) {
|
$app->get('/polls/:id', function ($pollId) use ($app) {
|
||||||
if(!pollIdIsValid($pollId)) {
|
$poll = Poll::restore($pollId);
|
||||||
$app->halt(400, 'requested id must only contain letters and numbers');
|
|
||||||
}
|
|
||||||
|
|
||||||
$datahandler = new Datahandler();
|
if (!$poll) {
|
||||||
$data = $datahandler->get($pollId);
|
$app->halt(404);
|
||||||
|
|
||||||
if ($data === false) {
|
|
||||||
// there was no data with this id or it could not be readen
|
|
||||||
$app->response->setStatus(404);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$app->response->setBody($data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$app->post('/polls', function() use ($app) {
|
|
||||||
$datahandler = new Datahandler();
|
|
||||||
$pollCreatedId = $datahandler->writePoll(
|
|
||||||
$app->request->getBody()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$pollCreatedId) {
|
|
||||||
$app->halt(500, 'saving poll failed');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$app->response->setBody(
|
$app->response->setBody(
|
||||||
$datahandler->get($pollCreatedId)
|
json_encode(
|
||||||
|
array(
|
||||||
|
'poll' => $poll->export()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$app->post('/polls', function() use ($app) {
|
||||||
|
$poll = Poll::create(
|
||||||
|
json_decode(
|
||||||
|
$app->request->getBody()
|
||||||
|
)->poll
|
||||||
|
);
|
||||||
|
$poll->save();
|
||||||
|
|
||||||
|
$app->response->setBody(
|
||||||
|
json_encode(
|
||||||
|
array(
|
||||||
|
'poll' => $poll->export()
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$app->post('/users', function() use ($app) {
|
$app->post('/users', function() use ($app) {
|
||||||
$datahandler = new Datahandler();
|
$user = User::create(
|
||||||
|
json_decode(
|
||||||
// get poll id
|
|
||||||
$dataObject = json_decode(
|
|
||||||
$app->request->getBody()
|
$app->request->getBody()
|
||||||
|
)->user
|
||||||
);
|
);
|
||||||
$pollId = $dataObject->user->poll;
|
$user->save();
|
||||||
if (!pollIdIsValid($pollId)) {
|
|
||||||
$app->halt(400, 'poll id must only contain letters and numbers');
|
|
||||||
}
|
|
||||||
|
|
||||||
// write user
|
|
||||||
$userCreatedId = $datahandler->writeUser($pollId, $app->request->getBody());
|
|
||||||
|
|
||||||
if ($userCreatedId === false) {
|
|
||||||
$app->halt(500, 'saving user failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
// add user id to user object
|
|
||||||
$dataObject->user->id = $pollId . '_' . $userCreatedId;
|
|
||||||
|
|
||||||
$app->response->setBody(
|
$app->response->setBody(
|
||||||
json_encode($dataObject)
|
json_encode(
|
||||||
|
array(
|
||||||
|
'user' => $user->export()
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$app->notFound(function () use ($app) {
|
/*
|
||||||
// die("verdammte schieße...");
|
* error handling
|
||||||
$app->halt(404, "verdammte scheiße\n" . $app->request->getResourceUri() . "\n");
|
*/
|
||||||
|
$app->error(function() use ($app) {
|
||||||
|
$app->halt(500);
|
||||||
|
});
|
||||||
|
|
||||||
|
$app->notFound(function() use ($app) {
|
||||||
|
$app->halt(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
$app->run();
|
$app->run();
|
||||||
|
|
|
@ -1,2 +1,32 @@
|
||||||
<?php
|
<?php
|
||||||
// This is global bootstrap for autoloading
|
// clear tmp dir
|
||||||
|
|
||||||
|
define('TEST_DATA_DIR', 'tests/_tmp/data/');
|
||||||
|
|
||||||
|
function deleteDirRecursively($dir) {
|
||||||
|
$handle = opendir($dir);
|
||||||
|
while(false !== ($entry = readdir($handle))) {
|
||||||
|
if($entry === '.' || $entry === '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_dir($dir . '/' . $entry)) {
|
||||||
|
$function = __FUNCTION__;
|
||||||
|
$function($dir .'/' . $entry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unlink($dir . '/' . $entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmdir($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_dir('tests/_tmp')) {
|
||||||
|
mkdir('tests/_tmp');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_dir(TEST_DATA_DIR)) {
|
||||||
|
deleteDirRecursively(TEST_DATA_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(TEST_DATA_DIR);
|
||||||
|
|
|
@ -1,28 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
$pollData = [
|
|
||||||
"poll" => [
|
$pollJson = '{"poll":{"title":"{\"iv\":\"szAOrvhM+bODnldJJP0pGw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"KwMkE7bneP0MX6hQEnM=\"}","description":"{\"iv\":\"aohDHKaO7c7Fl5vIueBkcA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"+ygmsnYAsEBLZRUV\"}","pollType":"{\"iv\":\"suOomfYe6kKBxjln091tCw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"7iDQ2y571OBiJNxdaUY0PjqlgQ==\"}","answerType":"{\"iv\":\"z1V+GmSWJxSng0bXxnYNRA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"ZDf5sBxR6rO+DdO/yFmk\"}","answers":"{\"iv\":\"WRdAwEa0DF+E83ginLYtPw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"Oaer31ct2PXkmXkzJ1EXRPM3LMf6vGfzMZqjODwey4f7EhqSCUhYov+N7AZKCAAXYVS4WR84kKizxXBK2PQBSFrlB3Bll74ED9ZzRJSJD00otMG9BbgUR90aFws+1jMBP5vpti9+POsii85zLbDPkNg/Th/C4Ufv5YWwg/4ZV0bFMyOgfdjtOWaG5YAMTGUIkz9U9+VCesYJQaTb497qTD/Wmtz8J/2pUxdL5/b5xkdh2DJ4/N5q0Kz/CEbaoKwbexnQDlSr3ldlIhs7UmBjC9gkpgG2l9fu6a0VZFBE8hvzYrw=\"}","options":"{\"iv\":\"79HYzanMnjtgvBMowUWHaA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"HuFz0AFCpupdmXYdCcAX4OiwpMs/Jm5XK/thQW0phxKd0OxKt9NZ3FE/rMAiYVqRKBqFp+KLhBnbs9ewTFW0Xrvw6paTnvpY9Ftcz1MB\"}","creationDate":"{\"iv\":\"DBKid4Yiyr61GVLigJj20w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"ORRPzySTa6vt7GQrJOGBvNZXXq4p/ANinfanE/51DbcDNw==\"}","forceAnswer":"{\"iv\":\"P5Dg5Y9fS7EFxvqzP8u20A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"90G4jQ1PbalZyyzz\"}","anonymousUser":"{\"iv\":\"SOqei2Y7QZt1PFR6IXR4qg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"WAg0oSjCiMAO+JqzIg==\"}","isDateTime":"{\"iv\":\"3y9OmTJDG0mLqU5zLoZwgQ==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"yyGaGitGrunDSpsRpw==\"}","timezone":"{\"iv\":\"l0VeY3CPUvMtoDPrw7+iCw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"qBlHlZ0nLd3mqA==\"}","expirationDate":"{\"iv\":\"Y0O4n9+Tj+4LSmLoFTaNow==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"jCz8DFIS5eLI4tsjfpr+F4lG+F27BItHPdj85o5+gaDayA==\"}","serverExpirationDate":"2015-11-22T22:05:15.065Z","version":"v0.3.0+0ae62f31"}}';
|
||||||
"encryptedTitle" => "{\"iv\":\"FUekCOJ/UOf91y9etFuh9w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"q8Iy+2AOwjcWjob1uLw=\"}",
|
|
||||||
"encryptedDescription" => null,
|
|
||||||
"encryptedPollType" => "{\"iv\":\"3iCPGIdKeMFbebcuJlmuMA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"0HDBwqya/9M7Ya/Y60R34uGGlw==\"}",
|
|
||||||
"encryptedAnswerType" => "{\"iv\":\"re8c+PWzoZndx8IxQ+JZfA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"qKY/EzZQbGqvkpABchEy\"}",
|
|
||||||
"encryptedAnswers" => "{\"iv\":\"Ln9SCj+dvBzTR8hOgoPP0g==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"lVu2owiRla6/R/lZB4SeJT3iNWcb8DqsBehaSxuROdpp6t1MIJX+TuMdiOae2jp36tsCTG2BWeEnoclbPA7ddDuWpxDA6zyM4OM+svJdYt6A3FkKPSUq8uWCJXmomkPmu9t9Cx4gWxDaluYGLGjU2BNIhm2ICTnxq94WkZsEjmM6qtUW3xmRPV+xkszOby5S4dxGZuK49TEfepWqBH6VLt4sDX3NoaU3Pyo6cyQQTLjlQ6nIIvKMrdx4Uk5/03oVTupFq+XsSNCI3fJ35YmPlc8v7qRhflXzDTr2pTOXmuP5w4I=\"}",
|
|
||||||
"encryptedOptions" => "{\"iv\":\"GDp5DyeuXMj2nLIiPXRa7w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"yxHxXBvZ9DDMVY+9fNIr6qM6gaMNHXkffxkk87a1Q9rWh0E8O0AVJpl9RYdv3/QkfYRqwjyQqA==\"}",
|
|
||||||
"encryptedCreationDate" => "{\"iv\":\"grXGp40HmdMlYd8mpRJb2A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"y9gx6YaU9f6UA/RMD+2ptWXeNQ9HdPt+nkH1bwrM1J85WA==\"}",
|
|
||||||
"encryptedForceAnswer" => "{\"iv\":\"cPQxZDytHCCBzyyGB7Zhew==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"U+Xd8Wua3XPDvbPe\"}",
|
|
||||||
"encryptedAnonymousUser" => "{\"iv\":\"Rv75z29GDIbZ/RGRs+uq0Q==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"/7sj+sLWPYOWJgvslg==\"}",
|
|
||||||
"encryptedIsDateTime" => "{\"iv\":\"noz0JF1Uzv74e27gMu55Kw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"Igefluift7+Wedo1Cw==\"}",
|
|
||||||
"encryptedTimezone" => "{\"iv\":\"/sBs7oP15FsJ7qSUSHvewA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"TqJBGIjSGIcVsQ==\"}",
|
|
||||||
"expirationDate" => "2015-11-01T17:57:03.713Z",
|
|
||||||
"version" => "v0.3.0+d26cd827"
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$I = new ApiTester($scenario);
|
$I = new ApiTester($scenario);
|
||||||
$I->wantTo('create a poll');
|
$I->wantTo('create a poll');
|
||||||
$I->sendPOST('/polls', json_encode($pollData));
|
$I->sendPOST('/polls', $pollJson);
|
||||||
$I->seeResponseCodeIs(200);
|
$I->seeResponseCodeIs(200);
|
||||||
$I->seeResponseIsJson();
|
$I->seeResponseIsJson();
|
||||||
$I->seeResponseContainsJson($pollData);
|
|
||||||
$I->seeResponseJsonMatchesJsonPath('poll.id');
|
$I->seeResponseJsonMatchesJsonPath('poll.id');
|
||||||
$pollId = $I->grabDataFromResponseByJsonPath('poll.id')[0];
|
$pollId = $I->grabDataFromResponseByJsonPath('poll.id')[0];
|
||||||
\PHPUnit_Framework_Assert::assertNotRegExp(
|
\PHPUnit_Framework_Assert::assertNotRegExp(
|
||||||
|
@ -45,3 +29,14 @@ $users = $I->grabDataFromResponseByJsonPath('poll.users')[0];
|
||||||
0,
|
0,
|
||||||
'user array should be empty'
|
'user array should be empty'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$pollData = json_decode($pollJson, true);
|
||||||
|
unset($pollData["poll"]["serverExpirationDate"]);
|
||||||
|
$I->seeResponseContainsJson(
|
||||||
|
$pollData,
|
||||||
|
'all data except serverExpirationDate is in response'
|
||||||
|
);
|
||||||
|
$I->dontSeeResponseJsonMatchesJsonPath(
|
||||||
|
'poll.serverExpirationDate',
|
||||||
|
'serverExpirationDate is not in response.'
|
||||||
|
);
|
||||||
|
|
36
api/tests/api/CreateUserCept.php
Normal file
36
api/tests/api/CreateUserCept.php
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$pollId = 'qwerQWER12';
|
||||||
|
$userJson = '{"user":{"name":"{\"iv\":\"kizIqK7FPNmRuQB7VHsMOw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"UsYMzrww3HKR8vl2TKVE\"}","selections":"{\"iv\":\"hRmiZagEhQVhw2cg6UJNrg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"2zIPGpiSC6wJHRoAMYBFPXx3qmlZg0Z/Jt/15mY+sHPLCqoAn97TKGN6KIvl/5gmgCFqLQFNo6uppCTUhljoV5y2kMtGvm0g3+NdpcejWGOeMACDPcp1mpXII87ZTfC6WrtxcWCB6UGYN8EynOdndFTGp+WVZnXCCya7YPThk/QRwoHoPWS6+TJFT9WeHV4i4kUIg2K3kdz3Op7S/c7l7KbOc8GsyjZzv0bRDnAm68/+FlJyZnvfMfU8vTxExsIsd0pBy4JBV4hg9SlCPectb5BAvBCULLDPA08prf262RUmVKJ+M3P1+5KkBQcnQwnUW/fzAQ7lqA==\"}","creationDate":"{\"iv\":\"xqdDY/A7MHLeAsoU9S/j+A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"TQOhbjveZbvdiyYpxfwNyu5pi1PLia9FApJJRmr3QoyrWA==\"}","version":"v0.3.0+0ae62f31","poll":"' . $pollId . '"}}';
|
||||||
|
|
||||||
|
$pollDir = TEST_DATA_DIR . $pollId . '/';
|
||||||
|
$usersDir = $pollDir . 'users/';
|
||||||
|
mkdir($pollDir);
|
||||||
|
|
||||||
|
$I = new ApiTester($scenario);
|
||||||
|
$I->wantTo('create a user');
|
||||||
|
$I->sendPOST('/users', $userJson);
|
||||||
|
$I->seeResponseCodeIs(200);
|
||||||
|
$I->seeResponseIsJson();
|
||||||
|
$I->seeResponseJsonMatchesJsonPath('user.id');
|
||||||
|
$userId = $I->grabDataFromResponseByJsonPath('user.id')[0];
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
count(explode('_', $userId)),
|
||||||
|
2,
|
||||||
|
'user id has two parts seperated by _'
|
||||||
|
);
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
explode('_', $userId)[0],
|
||||||
|
$pollId,
|
||||||
|
'user id starts by poll id'
|
||||||
|
);
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
(int) explode('_', $userId)[1],
|
||||||
|
explode('_', $userId)[1],
|
||||||
|
'second part contains numbers'
|
||||||
|
);
|
||||||
|
|
||||||
|
$userData = json_decode($userJson, true);
|
||||||
|
foreach($userData["user"] as $key => $value) {
|
||||||
|
$I->seeResponseContainsJson(["user" => [$key => $value]]);
|
||||||
|
}
|
6
api/tests/api/GetNotExistingPollCept.php
Normal file
6
api/tests/api/GetNotExistingPollCept.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
$I = new ApiTester($scenario);
|
||||||
|
$I->wantTo('get an not existing poll');
|
||||||
|
$I->sendGet('/polls/abcdEFGH12');
|
||||||
|
$I->seeResponseCodeIs(404);
|
||||||
|
$I->seeResponseEquals('');
|
|
@ -1,25 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
$pollId = "abcDEF0123";
|
$pollId = "abcDEF0123";
|
||||||
$pollData = [
|
$pollJson = '{"anonymousUser":"{\"iv\":\"SOqei2Y7QZt1PFR6IXR4qg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"WAg0oSjCiMAO+JqzIg==\"}","answers":"{\"iv\":\"WRdAwEa0DF+E83ginLYtPw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"Oaer31ct2PXkmXkzJ1EXRPM3LMf6vGfzMZqjODwey4f7EhqSCUhYov+N7AZKCAAXYVS4WR84kKizxXBK2PQBSFrlB3Bll74ED9ZzRJSJD00otMG9BbgUR90aFws+1jMBP5vpti9+POsii85zLbDPkNg\/Th\/C4Ufv5YWwg\/4ZV0bFMyOgfdjtOWaG5YAMTGUIkz9U9+VCesYJQaTb497qTD\/Wmtz8J\/2pUxdL5\/b5xkdh2DJ4\/N5q0Kz\/CEbaoKwbexnQDlSr3ldlIhs7UmBjC9gkpgG2l9fu6a0VZFBE8hvzYrw=\"}","answerType":"{\"iv\":\"z1V+GmSWJxSng0bXxnYNRA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"ZDf5sBxR6rO+DdO\/yFmk\"}","creationDate":"{\"iv\":\"DBKid4Yiyr61GVLigJj20w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"ORRPzySTa6vt7GQrJOGBvNZXXq4p\/ANinfanE\/51DbcDNw==\"}","description":"{\"iv\":\"aohDHKaO7c7Fl5vIueBkcA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"+ygmsnYAsEBLZRUV\"}","expirationDate":"{\"iv\":\"Y0O4n9+Tj+4LSmLoFTaNow==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"jCz8DFIS5eLI4tsjfpr+F4lG+F27BItHPdj85o5+gaDayA==\"}","forceAnswer":"{\"iv\":\"P5Dg5Y9fS7EFxvqzP8u20A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"90G4jQ1PbalZyyzz\"}","isDateTime":"{\"iv\":\"3y9OmTJDG0mLqU5zLoZwgQ==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"yyGaGitGrunDSpsRpw==\"}","options":"{\"iv\":\"79HYzanMnjtgvBMowUWHaA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"HuFz0AFCpupdmXYdCcAX4OiwpMs\/Jm5XK\/thQW0phxKd0OxKt9NZ3FE\/rMAiYVqRKBqFp+KLhBnbs9ewTFW0Xrvw6paTnvpY9Ftcz1MB\"}","pollType":"{\"iv\":\"suOomfYe6kKBxjln091tCw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"7iDQ2y571OBiJNxdaUY0PjqlgQ==\"}","timezone":"{\"iv\":\"l0VeY3CPUvMtoDPrw7+iCw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"qBlHlZ0nLd3mqA==\"}","title":"{\"iv\":\"szAOrvhM+bODnldJJP0pGw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3gtpUTAyVK4=\",\"ct\":\"KwMkE7bneP0MX6hQEnM=\"}","version":"v0.3.0+0ae62f31","serverExpirationDate":"2015-11-22T22:05:15.065Z"}';
|
||||||
"poll" => [
|
|
||||||
"encryptedTitle" => "{\"iv\":\"FUekCOJ/UOf91y9etFuh9w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"q8Iy+2AOwjcWjob1uLw=\"}",
|
|
||||||
"encryptedDescription" => null,
|
|
||||||
"encryptedPollType" => "{\"iv\":\"3iCPGIdKeMFbebcuJlmuMA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"0HDBwqya/9M7Ya/Y60R34uGGlw==\"}",
|
|
||||||
"encryptedAnswerType" => "{\"iv\":\"re8c+PWzoZndx8IxQ+JZfA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"qKY/EzZQbGqvkpABchEy\"}",
|
|
||||||
"encryptedAnswers" => "{\"iv\":\"Ln9SCj+dvBzTR8hOgoPP0g==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"lVu2owiRla6/R/lZB4SeJT3iNWcb8DqsBehaSxuROdpp6t1MIJX+TuMdiOae2jp36tsCTG2BWeEnoclbPA7ddDuWpxDA6zyM4OM+svJdYt6A3FkKPSUq8uWCJXmomkPmu9t9Cx4gWxDaluYGLGjU2BNIhm2ICTnxq94WkZsEjmM6qtUW3xmRPV+xkszOby5S4dxGZuK49TEfepWqBH6VLt4sDX3NoaU3Pyo6cyQQTLjlQ6nIIvKMrdx4Uk5/03oVTupFq+XsSNCI3fJ35YmPlc8v7qRhflXzDTr2pTOXmuP5w4I=\"}",
|
|
||||||
"encryptedOptions" => "{\"iv\":\"GDp5DyeuXMj2nLIiPXRa7w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"yxHxXBvZ9DDMVY+9fNIr6qM6gaMNHXkffxkk87a1Q9rWh0E8O0AVJpl9RYdv3/QkfYRqwjyQqA==\"}",
|
|
||||||
"encryptedCreationDate" => "{\"iv\":\"grXGp40HmdMlYd8mpRJb2A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"y9gx6YaU9f6UA/RMD+2ptWXeNQ9HdPt+nkH1bwrM1J85WA==\"}",
|
|
||||||
"encryptedForceAnswer" => "{\"iv\":\"cPQxZDytHCCBzyyGB7Zhew==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"U+Xd8Wua3XPDvbPe\"}",
|
|
||||||
"encryptedAnonymousUser" => "{\"iv\":\"Rv75z29GDIbZ/RGRs+uq0Q==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"/7sj+sLWPYOWJgvslg==\"}",
|
|
||||||
"encryptedIsDateTime" => "{\"iv\":\"noz0JF1Uzv74e27gMu55Kw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"Igefluift7+Wedo1Cw==\"}",
|
|
||||||
"encryptedTimezone" => "{\"iv\":\"/sBs7oP15FsJ7qSUSHvewA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"3GQYS4Ils60=\",\"ct\":\"TqJBGIjSGIcVsQ==\"}",
|
|
||||||
"encryptedExpirationDate" => "{\"iv\":\"Jmclqi7ZDjKZ1O9t6HgkyQ==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"CnrCEy2AX1c=\",\"ct\":\"jg0bpNknoJcB4CAumtSEjyRNy845vzbfM6QQeNx0M60ZAw==\"}",
|
|
||||||
"serverExpirationDate" => "2015-11-01T17:57:03.713Z",
|
|
||||||
"version" => "v0.3.0+d26cd827"
|
|
||||||
]
|
|
||||||
];
|
|
||||||
mkdir('tests/_tmp/data/' . $pollId);
|
mkdir('tests/_tmp/data/' . $pollId);
|
||||||
file_put_contents('tests/_tmp/data/' . $pollId . '/poll_data', json_encode($pollData));
|
file_put_contents('tests/_tmp/data/' . $pollId . '/poll_data', $pollJson);
|
||||||
|
|
||||||
$I = new ApiTester($scenario);
|
$I = new ApiTester($scenario);
|
||||||
$I->wantTo('get an existing poll');
|
$I->wantTo('get an existing poll');
|
||||||
|
@ -27,9 +10,24 @@ $I->sendGET('/polls/' . $pollId);
|
||||||
$I->seeResponseCodeIs(200);
|
$I->seeResponseCodeIs(200);
|
||||||
$I->seeResponseIsJson();
|
$I->seeResponseIsJson();
|
||||||
|
|
||||||
unset($pollData["poll"]["serverExpirationDate"]);
|
$pollData = json_decode($pollJson, true);
|
||||||
$I->seeResponseContainsJson($pollData);
|
unset($pollData["serverExpirationDate"]);
|
||||||
|
$I->seeResponseContainsJson(
|
||||||
|
array(
|
||||||
|
'poll' => $pollData
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$I->seeResponseContainsJson(["poll" => ["id" => $pollId]]);
|
$I->seeResponseContainsJson(["poll" => ["id" => $pollId]]);
|
||||||
|
|
||||||
$I->dontSeeResponseJsonMatchesJsonPath('poll.serverExpirationDate');
|
$I->dontSeeResponseJsonMatchesJsonPath('poll.serverExpirationDate');
|
||||||
|
$I->seeResponseJsonMatchesJsonPath('poll.users');
|
||||||
|
$users = $I->grabDataFromResponseByJsonPath('poll.users')[0];
|
||||||
|
\PHPUnit_Framework_Assert::assertTrue(
|
||||||
|
is_array($users),
|
||||||
|
'user should be an array'
|
||||||
|
);
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
count($users),
|
||||||
|
0,
|
||||||
|
'user array should be empty'
|
||||||
|
);
|
||||||
|
|
67
api/tests/api/GetPollWithUsersCept.php
Normal file
67
api/tests/api/GetPollWithUsersCept.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$pollId = "xyzQWER1234";
|
||||||
|
$pollJson = '{"anonymousUser":"{\"iv\":\"gVHZSXyMm10Fn+kDooa7uw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"GJsQQYA7TdAa+v3Rvg==\"}","answers":"{\"iv\":\"aK1JcI3viLPIlOO45K+ePA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"Bx4SRcww+hJ46NIiVcWBUZHADADX\/XPsxXMx4XzMQZWqu6M0690D4oTflSRJoqxe0egxdfMOUxuWhmACG\/UYXSYJQjcSg+QTq6KJbaXG+SvsCMZ7iz12a\/uf9lXyiag4IbLldgL4vE3LfZO6oih\/o\/yG4hechjNdSkqUa2IvsRbXWB2aHen6a5Ch5WjqWrr4xRRrukPvf7aumilT2Cf0LswHJ2fwYNilylV0h9oegKYp+qWphm4SL8x2ogRemSCt7u7ByEOwZV0w6D9bz9RvGLTRRLJaLIm\/VlE3k7R6Hz1vyps=\"}","answerType":"{\"iv\":\"ILkAzgUfAGNUtLr7CbEJEQ==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"nMOp+QApQGgP9dwefNpi\"}","creationDate":"{\"iv\":\"6tWbieK03uXUR+E0AMbs0A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"YkkLVBkFyx4xFldZ7qnDESG0teHJmXaPMUB05p9L0xUIMg==\"}","description":"{\"iv\":\"fWvHh47So4WBNfEHXrwLiA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"5W7nauOakSoFD52V\"}","expirationDate":"{\"iv\":\"HRsMvEQaoCp8QdqBGHevnA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"LXYamNRDyhIY5xY+CLqI4GHbocc9NoHQtePKU9fHpJn9zg==\"}","forceAnswer":"{\"iv\":\"bh4iZ4pKe0GnXcM764702g==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"q5VBynWGotXRrc2P\"}","isDateTime":"{\"iv\":\"mlDCtvsJZaDlZD9kqfJHuA==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"53g42C6Am+0s25\/DsA==\"}","options":"{\"iv\":\"ZneP\/x45NGh\/DC26GI4kvg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"4MvV9SNQq2dB6b\/MdX47R0KaRSfyZOZMEVUFDv7G3\/EcDBv7Z0pgSU9JXoF8BoSOz40rYrRtTw==\"}","pollType":"{\"iv\":\"j3P6eN0ZmNMMxLTAVD6gjQ==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"opwiZHAQi+I8R5HDxLfLK59DcQ==\"}","timezone":"{\"iv\":\"HKkSqcJONggGT9QQ+jZdUg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"BANN8sJlk8JK9A==\"}","title":"{\"iv\":\"4DX7dAJt7JIBHaR1V0Ct8A==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"f1VUZf69nB94TF3\/HA==\"}","version":"v0.3.0+0ae62f31","serverExpirationDate":"2015-11-22T20:35:03.764Z"}';
|
||||||
|
$user1Json = '{"name":"{\"iv\":\"GJXPSYYmTVfEsst31BD92w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"smbuxujRLF/xNS1syTWFguE=\"}","selections":"{\"iv\":\"WXlkCM3pGyD+SyIhccmHYg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"UHs2ArTVTHfS04J3HNvwrV68xFqra0Q0qtVpLZRLPUbqgdXmn960FjEFiLa9Cnk5OcKEQtbOgWJXehHlAJFAWFpdyDE/gcCOKG62c2/hVauroeycQE16wDCjrEwor/FV9HxNjTbYxoJASjCy9ROLdOUhSlFfQfHLcvVpsTgPpnKPr7aYBgODu5XIdRI8Pf5nYF0K96KE9xn+mkg3ZjyXWSk1LBaBDpIOCrcj+8zl7tLtkgPNfh8aNVgQHC5hRrIbL9kZwD4XXEUPImRFITEy2rUWKp8Q0/jAgHCnqSzOLOFS8KrJOktDX++DjK3cB4oT5ttLvcRxRQ==\"}","creationDate":"{\"iv\":\"3/KUsITWzJNWx5fDzYC9Xg==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"llgQE2GpZDg1ZKRRlXliGlF09VsrVZ1R57EIQ21+dej5yg==\"}","version":"v0.3.0+0ae62f31","poll":"l3zyFJUWcQ"}';
|
||||||
|
$user2Json = '{"name":"{\"iv\":\"DVNTCOFfACEOrgtVNVMyww==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"eug7bstOm7T\/CCFs32o=\"}","selections":"{\"iv\":\"ubEuXoXzw4QFuzjAyvXC6w==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"PfQ4v4hkBf+S0GX7JmnIp2LO5sh\/jg9nEIPn8NeU2Gn9Rb7cqsjCLgKOQ2xkiIzCyimVBOYg0fjGCyzM\/b6ZPQnY+86teNGogEteD4fjqGHhO832FNOy7Oci0YC8VAM1x9SlQNBI9V+vFc706JbZgwA8JY46UMiGK3HU49pgbYMpdnWEmt4dGzGrLMnNbh4J1Or5JydKmrp4dXaMiiggSXhmUTgBJSRhF7dxQm16oaA1lJpCWoQBvu+WTJv34LnBXHbgg6JcAEEONaQRw1jmMeqo36tQJxSdjiVfcDWzMifWiz\/nhQMqDHkc19iOAmDBo2Rf+yrGWA==\"}","creationDate":"{\"iv\":\"Sj4pVW\/maHa8DUNFHhyUrw==\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"mhO9ROu+dr4=\",\"ct\":\"HaY9MtEzVmEg3dxtI\/pfaIrsivBJSNeC5l5iJHQrvyYQGA==\"}","version":"v0.3.0+0ae62f31","poll":"l3zyFJUWcQ"}';
|
||||||
|
|
||||||
|
$pollDir = 'tests/_tmp/data/' . $pollId . '/';
|
||||||
|
$userDir = $pollDir . 'users/';
|
||||||
|
mkdir($pollDir);
|
||||||
|
file_put_contents($pollDir . 'poll_data', $pollJson);
|
||||||
|
mkdir($userDir);
|
||||||
|
file_put_contents($userDir . '0', $user1Json);
|
||||||
|
file_put_contents($userDir . '1', $user2Json);
|
||||||
|
|
||||||
|
$I = new ApiTester($scenario);
|
||||||
|
$I->wantTo('get an existing poll');
|
||||||
|
$I->sendGET('/polls/' . $pollId);
|
||||||
|
$I->seeResponseCodeIs(200);
|
||||||
|
$I->seeResponseIsJson();
|
||||||
|
|
||||||
|
$pollData = json_decode($pollJson, true);
|
||||||
|
unset($pollData["serverExpirationDate"]);
|
||||||
|
foreach($pollData as $key => $value) {
|
||||||
|
$I->seeResponseContainsJson(
|
||||||
|
array(
|
||||||
|
'poll' => array(
|
||||||
|
$key => $value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$I->seeResponseContainsJson(["poll" => ["id" => $pollId]]);
|
||||||
|
$I->dontSeeResponseJsonMatchesJsonPath('poll.serverExpirationDate');
|
||||||
|
$I->seeResponseJsonMatchesJsonPath('poll.users');
|
||||||
|
$users = $I->grabDataFromResponseByJsonPath('poll.users')[0];
|
||||||
|
\PHPUnit_Framework_Assert::assertTrue(
|
||||||
|
is_array($users),
|
||||||
|
'user should be an array'
|
||||||
|
);
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
count($users),
|
||||||
|
2,
|
||||||
|
'user array should contain 2 users'
|
||||||
|
);
|
||||||
|
$I->seeResponseContainsJson([
|
||||||
|
"poll" => [
|
||||||
|
"users" => [
|
||||||
|
json_decode($user1Json, true),
|
||||||
|
json_decode($user2Json, true)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
$I->seeResponseJsonMatchesJsonPath('poll.users.0.id');
|
||||||
|
$I->seeResponseJsonMatchesJsonPath('poll.users.1.id');
|
||||||
|
$user1Id = $I->grabDataFromResponseByJsonPath('poll.users.0.id')[0];
|
||||||
|
$user2Id = $I->grabDataFromResponseByJsonPath('poll.users.1.id')[0];
|
||||||
|
\PHPUnit_Framework_Assert::assertTrue(
|
||||||
|
$user1Id !== $user2Id,
|
||||||
|
'user ids are unique'
|
||||||
|
);
|
||||||
|
\PHPUnit_Framework_Assert::assertEquals(
|
||||||
|
explode('_', $user1Id)[0],
|
||||||
|
$pollId,
|
||||||
|
'user id starts by poll id'
|
||||||
|
);
|
6
api/tests/api/RaiseAnErrorCept.php
Normal file
6
api/tests/api/RaiseAnErrorCept.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
$I = new ApiTester($scenario);
|
||||||
|
$I->wantTo('raise an error');
|
||||||
|
$I->sendGet('/polls/ab!cd');
|
||||||
|
$I->seeResponseCodeIs(500);
|
||||||
|
$I->seeResponseEquals('');
|
|
@ -1,31 +1 @@
|
||||||
<?php
|
<?php
|
||||||
// clear tmp dir
|
|
||||||
$tmpDataDir = 'tests/_tmp/data';
|
|
||||||
|
|
||||||
function deleteDirRecursively($dir) {
|
|
||||||
$handle = opendir($dir);
|
|
||||||
while(false !== ($entry = readdir($handle))) {
|
|
||||||
if($entry === '.' || $entry === '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_dir($dir . '/' . $entry)) {
|
|
||||||
$function = __FUNCTION__;
|
|
||||||
$function($dir .'/' . $entry);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unlink($dir . '/' . $entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rmdir($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_dir('tests/_tmp')) {
|
|
||||||
mkdir('tests/_tmp');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_dir($tmpDataDir)) {
|
|
||||||
mkdir($tmpDataDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteDirRecursively($tmpDataDir);
|
|
||||||
|
|
|
@ -6,7 +6,9 @@ export default DS.Model.extend({
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
title : DS.attr('string'),
|
title : DS.attr('string'),
|
||||||
description : DS.attr('string'),
|
description : DS.attr('string', {
|
||||||
|
defaultValue: ''
|
||||||
|
}),
|
||||||
pollType : DS.attr('string'),
|
pollType : DS.attr('string'),
|
||||||
answerType: DS.attr('string'),
|
answerType: DS.attr('string'),
|
||||||
answers : DS.attr('array'),
|
answers : DS.attr('array'),
|
||||||
|
|
Loading…
Reference in a new issue