Skip to content

Instantly share code, notes, and snippets.

@chanmix51
Created October 25, 2012 13:17
Show Gist options
  • Save chanmix51/3952489 to your computer and use it in GitHub Desktop.
Save chanmix51/3952489 to your computer and use it in GitHub Desktop.
REST API with Silex and Pomm
<?php // sources/application.php
use \Symfony\Component\HttpFoundation\Request;
use \Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints as Assert;
$app = require "bootstrap.php";
$app['generate_token'] = $app->protect(function(\Taf\Member\Worker $member) use ($app) { return md5($member->getEmail().date('U')); });
$check_token = function(Request $request) use ($app) {
if (!$request->headers->get('member-token')) {
return new Response('No token provided.', 401);
}
$where = \Pomm\Query\Where::create("token = ?", array($request->headers->get('member-token')))
->andWhere("created_at + ? > now()", array(sprintf("%d seconds", 1800)));
$session = $app['pomm.connection']
->getMapFor('\Taf\Member\Session')
->findWhere($where)
->current();
if (!$session) {
return new Response(sprintf("Invalid or expired token '%s'.", $request->headers->get('member-token')), 401);
}
$app['taf.session'] = $session;
};
/** POST "/workers/{email}/token"
*
* Create a new token for the given user.
* If the user does not exist, it is created.
* Set the lastlog attribute for the worker.
**/
$app->post('/workers/{email}/session', function($email) use ($app) {
$worker_map = $app['pomm.connection']->getMapFor('\Taf\Member\Worker');
$worker = $worker_map
->findWhere('email = ?', array($email))
->current();
try
{
$app['pomm.connection']->begin();
if (!$worker) {
$worker = $worker_map->createAndSaveObject(array('email' => $email));
}
$worker['session'] = $app['pomm.connection']
->getMapFor('\Taf\Member\Session')
->renew(new \Taf\Member\Session(array('token' => $app['generate_token']($worker), 'worker_id' => $worker['worker_id'])));
$app['pomm.connection']->commit();
}
catch (\Pomm\Exception\Exception $e)
{
$app['pomm.connection']->rollback();
throw new \RuntimeException(sprintf(sprintf("Error while saving session info (member = '%s', token = '%s').", $worker['email'], $worker['session']['token']), 0, $e));
}
return $app->json(array('worker' => $worker->extract()));
});
$app->get('/tasks', function() use ($app) {
$task_map = $app['pomm.connection']
->getMapFor('\Taf\Task\Task');
$tasks = $task_map
->findWhere('worker_id = ?', array($app['taf.session']->getWorkerId()), 'ORDER BY created_at DESC');
return $app->json(array('tasks' => $tasks->extract()));
})->before($check_token);
$app->post('/tasks', function() use ($app) {
$new_task = $app['request']->request->get('task');
$new_task['worker_id'] = $app['taf.session']->getWorkerId();
$errors = $app['validator']->validateValue($new_task, new Assert\Collection(array(
'fields' => array(
'title' => new Assert\MaxLength(100),
'content' => new Assert\NotBlank(),
'worker_id' => new Assert\Type('integer')
),
)));
if (count($errors) == 0)
{
$task = $app['pomm.connection']
->getMapFor('\Taf\Task\Task')
->createAndSaveObject((array) $new_task);
return $app->json(array('task' => $task->extract()), 201);
}
return new Response(sprintf("Invalid or missing parameters. === %s ===", print_r($errors, true)), 400);
})->before($check_token);
$app->delete('/tasks/{id}', function($id) use ($app) {
$task = $app['pomm.connection']
->getMapFor('\Taf\Task\Task')
->deleteByPk(array('task_id' => $id));
if (!$task)
{
return new Response(sprintf("No such task id '%d'.", $id), 404);
}
return $app->json(array('task' => $task->extract()));
})->before($check_token);
$app->put('/tasks/{id}', function($id) use ($app) {
$update_task = $app['request']->request->get('task');
$errors = $app['validator']->validateValue($update_task, new Assert\Collection(array(
'fields' => array(
'title' => new Assert\MaxLength(array('limit' => 100)),
'time_spent' => new Assert\Min(array('limit' => 0)),
),
'allowMissingFields' => true)
));
if (count($errors) == 0)
{
$task = $app['pomm.connection']
->getMapFor('\Taf\Task\Task')
->updateByPk(array('task_id' => $id), $update_task);
if (!$task)
{
return new Response(sprintf("No such task id '%d'.", $id), 404);
}
return $app->json(array('task' => $task->extract()));
}
return new Response(sprintf("Bad parameters. == %s ==.", print_r($errors, true)), 400);
})->before($check_token);
$app->get('/tasks/{id}', function($id) use ($app) {
$task = $app['pomm.connection']
->getMapFor('\Taf\Task\Task')
->findByPk(array('task_id' => $id));
if ($task)
{
return $app->json(array('task' => $task->extract()));
}
return new Response(sprintf("No such task id='%d'.", $id), 404);
})->before($check_token);
$app->delete('/token', function() use ($app)
{
$app['pomm.connection']
->getMapFor('\Taf\Member\Session')
->deleteOne($app['taf.session'])
;
return new Response(null, 202);
})->before($check_token);
return $app;
<?php #sources/bootstrap.php
// This script sets up the application DI with services.
define('PROJECT_DIR', dirname(__DIR__));
require PROJECT_DIR.'/sources/config/environment.php';
// autoloader
$loader = require PROJECT_DIR.'/vendor/autoload.php';
$loader->add('Taf', PROJECT_DIR.'/sources/model');
$loader->add('Validation', PROJECT_DIR.'/sources');
$app = new Silex\Application();
// configuration parameters
if (!file_exists(PROJECT_DIR.'/sources/config/config.php')) {
throw new \RunTimeException("No config.php found in config.");
}
require PROJECT_DIR.'/sources/config/config.php';
// extensions registration
use Silex\Provider;
$app->register(new Provider\ValidatorServiceProvider());
$app->register(new Provider\UrlGeneratorServiceProvider());
$app->register(new Provider\SessionServiceProvider());
$app->register(new Provider\TwigServiceProvider(), array(
'twig.path' => array(PROJECT_DIR.'/sources/twig'),
));
$app->register(new \Pomm\Silex\PommServiceProvider(), array(
'pomm.databases' => $app['config.pomm.dsn'][ENV]
));
// Service container customization.
$app['loader'] = $loader;
$app['pomm.connection'] = $app['pomm']
->getDatabase()
->registerTypeForConverter('public.email_address', 'String')
->createConnection(new \Pomm\Identity\IdentityMapperSmart());
// set DEBUG mode or not
if (preg_match('/^dev/', ENV))
{
$app['debug'] = true;
$app['pomm.logger'] = $app->share(function() { return new Pomm\Tools\Logger(); });
$app['pomm.connection']
->registerFilter(new Pomm\FilterChain\LoggerFilter($app['pomm.logger']));
}
return $app;
<?php
namespace Taf\Member;
use Taf\Member\Base\SessionMap as BaseSessionMap;
use Taf\Member\Session;
use \Pomm\Exception\Exception;
use \Pomm\Query\Where;
use \Pomm\Object\BaseObject;
class SessionMap extends BaseSessionMap
{
public function renew(BaseObject &$object)
{
$sql = <<<SQL
WITH
deleted_session AS (DELETE FROM %s WHERE worker_id = ?)
INSERT INTO %s (%s) VALUES (%s) RETURNING %s
SQL;
$values = $this->convertToPg($object->getFields());
$sql = sprintf($sql,
$this->getTableName(),
$this->getTableName(),
join(', ', array_keys($values)),
join(', ', $values),
$this->formatFieldsWithAlias('getSelectFields')
);
$object = $this->query($sql, array($object['worker_id']))->current();
return $object;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment