diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..004e6ff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+# OS
+.DS_Store
+
+# Composer
+/vendor
\ No newline at end of file
diff --git a/app/commands/.gitkeep b/app/commands/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/config/api.php b/app/config/api.php
new file mode 100644
index 0000000..769efa2
--- /dev/null
+++ b/app/config/api.php
@@ -0,0 +1,5 @@
+ 100,
+);
\ No newline at end of file
diff --git a/app/config/app.php b/app/config/app.php
new file mode 100644
index 0000000..249b7be
--- /dev/null
+++ b/app/config/app.php
@@ -0,0 +1,177 @@
+ true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Timezone
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the default timezone for your application, which
+ | will be used by the PHP date and date-time functions. We have gone
+ | ahead and set this to a sensible default for you out of the box.
+ |
+ */
+
+ 'timezone' => 'UTC',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Locale Configuration
+ |--------------------------------------------------------------------------
+ |
+ | The application locale determines the default locale that will be used
+ | by the translation service provider. You are free to set this value
+ | to any of the locales which will be supported by the application.
+ |
+ */
+
+ 'locale' => 'en',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Fallback Locale
+ |--------------------------------------------------------------------------
+ |
+ | The fallback locale determines the locale to use when the current one
+ | is not available. You may change the value to correspond to any of
+ | the language folders that are provided through your application.
+ |
+ */
+
+ 'fallback_locale' => 'en',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Encryption Key
+ |--------------------------------------------------------------------------
+ |
+ | This key is used by the Illuminate encrypter service and should be set
+ | to a random, long string, otherwise these encrypted values will not
+ | be safe. Make sure to change it before deploying any application!
+ |
+ */
+
+ 'key' => '1S@4nE2hUeHKQI01XWJEGBygKYcA09GT',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Autoloaded Service Providers
+ |--------------------------------------------------------------------------
+ |
+ | The service providers listed here will be automatically loaded on the
+ | request to your application. Feel free to add your own services to
+ | this array to grant expanded functionality to your applications.
+ |
+ */
+
+ 'providers' => array(
+
+ 'Illuminate\Foundation\Providers\ArtisanServiceProvider',
+ 'Illuminate\Auth\AuthServiceProvider',
+ 'Illuminate\Cache\CacheServiceProvider',
+ 'Illuminate\Foundation\Providers\CommandCreatorServiceProvider',
+ 'Illuminate\Session\CommandsServiceProvider',
+ 'Illuminate\Foundation\Providers\ComposerServiceProvider',
+ 'Illuminate\Routing\ControllerServiceProvider',
+ 'Illuminate\Cookie\CookieServiceProvider',
+ 'Illuminate\Database\DatabaseServiceProvider',
+ 'Illuminate\Encryption\EncryptionServiceProvider',
+ 'Illuminate\Filesystem\FilesystemServiceProvider',
+ 'Illuminate\Hashing\HashServiceProvider',
+ 'Illuminate\Foundation\Providers\KeyGeneratorServiceProvider',
+ 'Illuminate\Log\LogServiceProvider',
+ 'Illuminate\Mail\MailServiceProvider',
+ 'Illuminate\Database\MigrationServiceProvider',
+ 'Illuminate\Pagination\PaginationServiceProvider',
+ 'Illuminate\Foundation\Providers\PublisherServiceProvider',
+ 'Illuminate\Queue\QueueServiceProvider',
+ 'Illuminate\Redis\RedisServiceProvider',
+ 'Illuminate\Auth\Reminders\ReminderServiceProvider',
+ 'Illuminate\Database\SeedServiceProvider',
+ 'Illuminate\Foundation\Providers\ServerServiceProvider',
+ 'Illuminate\Session\SessionServiceProvider',
+ 'Illuminate\Foundation\Providers\TinkerServiceProvider',
+ 'Illuminate\Translation\TranslationServiceProvider',
+ 'Illuminate\Validation\ValidationServiceProvider',
+ 'Illuminate\View\ViewServiceProvider',
+ 'Illuminate\Workbench\WorkbenchServiceProvider',
+
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Service Provider Manifest
+ |--------------------------------------------------------------------------
+ |
+ | The service provider manifest is used by Laravel to lazy load service
+ | providers which are not needed for each request, as well to keep a
+ | list of all of the services. Here, you may set its storage spot.
+ |
+ */
+
+ 'manifest' => __DIR__.'/../storage/meta',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Class Aliases
+ |--------------------------------------------------------------------------
+ |
+ | This array of class aliases will be registered when this application
+ | is started. However, feel free to register as many as you wish as
+ | the aliases are "lazy" loaded so they don't hinder performance.
+ |
+ */
+
+ 'aliases' => array(
+
+ 'App' => 'Illuminate\Support\Facades\App',
+ 'Artisan' => 'Illuminate\Support\Facades\Artisan',
+ 'Auth' => 'Illuminate\Support\Facades\Auth',
+ 'Blade' => 'Illuminate\Support\Facades\Blade',
+ 'Cache' => 'Illuminate\Support\Facades\Cache',
+ 'ClassLoader' => 'Illuminate\Support\ClassLoader',
+ 'Config' => 'Illuminate\Support\Facades\Config',
+ 'Controller' => 'Illuminate\Routing\Controllers\Controller',
+ 'Cookie' => 'Illuminate\Support\Facades\Cookie',
+ 'Crypt' => 'Illuminate\Support\Facades\Crypt',
+ 'DB' => 'Illuminate\Support\Facades\DB',
+ 'Eloquent' => 'Illuminate\Database\Eloquent\Model',
+ 'Event' => 'Illuminate\Support\Facades\Event',
+ 'File' => 'Illuminate\Support\Facades\File',
+ 'Hash' => 'Illuminate\Support\Facades\Hash',
+ 'Input' => 'Illuminate\Support\Facades\Input',
+ 'Lang' => 'Illuminate\Support\Facades\Lang',
+ 'Log' => 'Illuminate\Support\Facades\Log',
+ 'Mail' => 'Illuminate\Support\Facades\Mail',
+ 'Paginator' => 'Illuminate\Support\Facades\Paginator',
+ 'Password' => 'Illuminate\Support\Facades\Password',
+ 'Queue' => 'Illuminate\Support\Facades\Queue',
+ 'Redirect' => 'Illuminate\Support\Facades\Redirect',
+ 'Redis' => 'Illuminate\Support\Facades\Redis',
+ 'Request' => 'Illuminate\Support\Facades\Request',
+ 'Response' => 'Illuminate\Support\Facades\Response',
+ 'Route' => 'Illuminate\Support\Facades\Route',
+ 'Schema' => 'Illuminate\Support\Facades\Schema',
+ 'Seeder' => 'Illuminate\Database\Seeder',
+ 'Session' => 'Illuminate\Support\Facades\Session',
+ 'URL' => 'Illuminate\Support\Facades\URL',
+ 'Validator' => 'Illuminate\Support\Facades\Validator',
+ 'View' => 'Illuminate\Support\Facades\View',
+
+ ),
+
+);
diff --git a/app/config/auth.php b/app/config/auth.php
new file mode 100644
index 0000000..62ea9c3
--- /dev/null
+++ b/app/config/auth.php
@@ -0,0 +1,63 @@
+ 'eloquent',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Authentication Model
+ |--------------------------------------------------------------------------
+ |
+ | When using the "Eloquent" authentication driver, we need to know which
+ | Eloquent model should be used to retrieve your users. Of course, it
+ | is often just the "User" model but you may use whatever you like.
+ |
+ */
+
+ 'model' => 'User',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Authentication Table
+ |--------------------------------------------------------------------------
+ |
+ | When using the "Database" authentication driver, we need to know which
+ | table should be used to retrieve your users. We have chosen a basic
+ | default value but you may easily change it to any table you like.
+ |
+ */
+
+ 'table' => 'users',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Password Reminder Settings
+ |--------------------------------------------------------------------------
+ |
+ | Here you may set the settings for password reminders, including a view
+ | that should be used as your password reminder e-mail. You will also
+ | be able to set the name of the table that holds the reset tokens.
+ |
+ */
+
+ 'reminder' => array(
+
+ 'email' => 'emails.auth.reminder', 'table' => 'password_reminders',
+
+ ),
+
+);
\ No newline at end of file
diff --git a/app/config/cache.php b/app/config/cache.php
new file mode 100644
index 0000000..f55ca14
--- /dev/null
+++ b/app/config/cache.php
@@ -0,0 +1,89 @@
+ 'file',
+
+ /*
+ |--------------------------------------------------------------------------
+ | File Cache Location
+ |--------------------------------------------------------------------------
+ |
+ | When using the "file" cache driver, we need a location where the cache
+ | files may be stored. A sensible default has been specified, but you
+ | are free to change it to any other place on disk that you desire.
+ |
+ */
+
+ 'path' => __DIR__.'/../storage/cache',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Database Cache Connection
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" cache driver you may specify the connection
+ | that should be used to store the cached items. When this option is
+ | null the default database connection will be utilized for cache.
+ |
+ */
+
+ 'connection' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Database Cache Table
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" cache driver we need to know the table that
+ | should be used to store the cached items. A default table name has
+ | been provided but you're free to change it however you deem fit.
+ |
+ */
+
+ 'table' => 'cache',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Memcached Servers
+ |--------------------------------------------------------------------------
+ |
+ | Now you may specify an array of your Memcached servers that should be
+ | used when utilizing the Memcached cache driver. All of the servers
+ | should contain a value for "host", "port", and "weight" options.
+ |
+ */
+
+ 'memcached' => array(
+
+ array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100),
+
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Key Prefix
+ |--------------------------------------------------------------------------
+ |
+ | When utilizing a RAM based store such as APC or Memcached, there might
+ | be other applications utilizing the same cache. So, we'll specify a
+ | value to get prefixed to all our keys so we can avoid collisions.
+ |
+ */
+
+ 'prefix' => 'laravel',
+
+);
diff --git a/app/config/database.php b/app/config/database.php
new file mode 100644
index 0000000..d811e9a
--- /dev/null
+++ b/app/config/database.php
@@ -0,0 +1,122 @@
+ PDO::FETCH_CLASS,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Database Connection Name
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify which of the database connections below you wish
+ | to use as your default connection for all database work. Of course
+ | you may use many connections at once using the Database library.
+ |
+ */
+
+ 'default' => 'mysql',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Database Connections
+ |--------------------------------------------------------------------------
+ |
+ | Here are each of the database connections setup for your application.
+ | Of course, examples of configuring each database platform that is
+ | supported by Laravel is shown below to make development simple.
+ |
+ |
+ | All database work in Laravel is done through the PHP PDO facilities
+ | so make sure you have the driver for your particular database of
+ | choice installed on your machine before you begin development.
+ |
+ */
+
+ 'connections' => array(
+
+ 'sqlite' => array(
+ 'driver' => 'sqlite',
+ 'database' => __DIR__.'/../database/production.sqlite',
+ 'prefix' => '',
+ ),
+
+ 'mysql' => array(
+ 'driver' => 'mysql',
+ 'host' => 'localhost',
+ 'database' => 'database',
+ 'username' => 'root',
+ 'password' => '',
+ 'charset' => 'utf8',
+ 'collation' => 'utf8_unicode_ci',
+ 'prefix' => '',
+ ),
+
+ 'pgsql' => array(
+ 'driver' => 'pgsql',
+ 'host' => 'localhost',
+ 'database' => 'database',
+ 'username' => 'root',
+ 'password' => '',
+ 'charset' => 'utf8',
+ 'prefix' => '',
+ 'schema' => 'public',
+ ),
+
+ 'sqlsrv' => array(
+ 'driver' => 'sqlsrv',
+ 'host' => 'localhost',
+ 'database' => 'database',
+ 'username' => 'root',
+ 'password' => '',
+ 'prefix' => '',
+ ),
+
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Migration Repository Table
+ |--------------------------------------------------------------------------
+ |
+ | This table keeps track of all the migrations that have already run for
+ | your application. Using this information, we can determine which of
+ | the migrations on disk have not actually be run in the databases.
+ |
+ */
+
+ 'migrations' => 'migrations',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Redis Databases
+ |--------------------------------------------------------------------------
+ |
+ | Redis is an open source, fast, and advanced key-value store that also
+ | provides a richer set of commands than a typical key-value systems
+ | such as APC or Memcached. Laravel makes it easy to dig right in.
+ |
+ */
+
+ 'redis' => array(
+
+ 'default' => array(
+ 'host' => '127.0.0.1',
+ 'port' => 6379,
+ 'database' => 0,
+ ),
+
+ ),
+
+);
\ No newline at end of file
diff --git a/app/config/local/.gitignore b/app/config/local/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/app/config/local/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/app/config/mail.php b/app/config/mail.php
new file mode 100644
index 0000000..e793d88
--- /dev/null
+++ b/app/config/mail.php
@@ -0,0 +1,83 @@
+ 'smtp.postmarkapp.com',
+
+ /*
+ |--------------------------------------------------------------------------
+ | SMTP Host Port
+ |--------------------------------------------------------------------------
+ |
+ | This is the SMTP port used by your application to delivery e-mails to
+ | users of your application. Like the host we have set this value to
+ | stay compatible with the Postmark e-mail application by default.
+ |
+ */
+
+ 'port' => 2525,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Global "From" Address
+ |--------------------------------------------------------------------------
+ |
+ | You may wish for all e-mails sent by your application to be sent from
+ | the same address. Here, you may specify a name and address that is
+ | used globally for all e-mails that are sent by your application.
+ |
+ */
+
+ 'from' => array('address' => null, 'name' => null),
+
+ /*
+ |--------------------------------------------------------------------------
+ | E-Mail Encryption Protocol
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the encryption protocol that should be used when
+ | the application send e-mail messages. A sensible default using the
+ | transport layer security protocol should provide great security.
+ |
+ */
+
+ 'encryption' => 'tls',
+
+ /*
+ |--------------------------------------------------------------------------
+ | SMTP Server Username
+ |--------------------------------------------------------------------------
+ |
+ | If your SMTP server requires a username for authentication, you should
+ | set it here. This will get used to authenticate with your server on
+ | connection. You may also set the "password" value below this one.
+ |
+ */
+
+ 'username' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | SMTP Server Password
+ |--------------------------------------------------------------------------
+ |
+ | Here you may set the password required by your SMTP server to send out
+ | messages from your application. This will be given to the server on
+ | connection so that the application will be able to send messages.
+ |
+ */
+
+ 'password' => null,
+
+);
diff --git a/app/config/packages/.gitkeep b/app/config/packages/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/config/queue.php b/app/config/queue.php
new file mode 100644
index 0000000..5dc5cb0
--- /dev/null
+++ b/app/config/queue.php
@@ -0,0 +1,45 @@
+ 'sync',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Queue Connections
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the connection information for each server that
+ | is used by your application. A default configuration has been added
+ | for each back-end shipped with Laravel. You are free to add more.
+ |
+ */
+
+ 'connections' => array(
+
+ 'sync' => array(
+ 'driver' => 'sync',
+ ),
+
+ 'beanstalkd' => array(
+ 'driver' => 'beanstalkd',
+ 'host' => 'localhost',
+ 'queue' => 'default',
+ ),
+
+ ),
+
+);
\ No newline at end of file
diff --git a/app/config/session.php b/app/config/session.php
new file mode 100644
index 0000000..95beffa
--- /dev/null
+++ b/app/config/session.php
@@ -0,0 +1,99 @@
+ 'array',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Lifetime
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the number of minutes that you wish the session
+ | to be allowed to remain idle for it is expired. If you want them
+ | to immediately expire when the browser closes, set it to zero.
+ |
+ */
+
+ 'lifetime' => 120,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session File Location
+ |--------------------------------------------------------------------------
+ |
+ | When using the "file" session driver, we need a location where session
+ | files may be stored. A default has been set for you but a different
+ | location may be specified. This is only needed for file sessions.
+ |
+ */
+
+ 'path' => __DIR__.'/../storage/sessions',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Connection
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" session driver, you may specify the database
+ | connection that should be used to manage your sessions. This should
+ | correspond to a connection in your "database" configuration file.
+ |
+ */
+
+ 'connection' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Table
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" session driver, you may specify the table we
+ | should use to manage the sessions. Of course, a sensible default is
+ | provided for you; however, you are free to change this as needed.
+ |
+ */
+
+ 'table' => 'sessions',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Sweeping Lottery
+ |--------------------------------------------------------------------------
+ |
+ | Some session drivers must manually sweep their storage location to get
+ | rid of old sessions from storage. Here are the chances that it will
+ | happen on a given request. By default, the odds are 2 out of 100.
+ |
+ */
+
+ 'lottery' => array(2, 100),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Name
+ |--------------------------------------------------------------------------
+ |
+ | Here you may change the name of the cookie used to identify a session
+ | instance by ID. The name specified here will get used every time a
+ | new session cookie is created by the framework for every driver.
+ |
+ */
+
+ 'cookie' => 'laravel_session',
+
+);
diff --git a/app/config/testing/cache.php b/app/config/testing/cache.php
new file mode 100644
index 0000000..16d3ae2
--- /dev/null
+++ b/app/config/testing/cache.php
@@ -0,0 +1,20 @@
+ 'array',
+
+);
\ No newline at end of file
diff --git a/app/config/testing/session.php b/app/config/testing/session.php
new file mode 100644
index 0000000..338aeba
--- /dev/null
+++ b/app/config/testing/session.php
@@ -0,0 +1,21 @@
+ 'array',
+
+);
\ No newline at end of file
diff --git a/app/config/view.php b/app/config/view.php
new file mode 100644
index 0000000..eba10a4
--- /dev/null
+++ b/app/config/view.php
@@ -0,0 +1,31 @@
+ array(__DIR__.'/../views'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Pagination View
+ |--------------------------------------------------------------------------
+ |
+ | This view will be used to render the pagination link output, and can
+ | be easily customized here to show any view you like. A clean view
+ | compatible with Twitter's Bootstrap is given to you by default.
+ |
+ */
+
+ 'pagination' => 'pagination::slider',
+
+);
diff --git a/app/controllers/.gitkeep b/app/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/controllers/BaseController.php b/app/controllers/BaseController.php
new file mode 100644
index 0000000..097e161
--- /dev/null
+++ b/app/controllers/BaseController.php
@@ -0,0 +1,18 @@
+layout))
+ {
+ $this->layout = View::make($this->layout);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/database/migrations/.gitkeep b/app/database/migrations/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/database/migrations/2013_01_27_195248_create_users.php b/app/database/migrations/2013_01_27_195248_create_users.php
new file mode 100644
index 0000000..970e13c
--- /dev/null
+++ b/app/database/migrations/2013_01_27_195248_create_users.php
@@ -0,0 +1,34 @@
+increments('id');
+ $table->string('username', 50)->unique();
+ $table->string('password', 60);
+ $table->string('api_key', 32)->unique();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('users');
+ }
+
+}
\ No newline at end of file
diff --git a/app/database/migrations/2013_01_31_141600_create_lists.php b/app/database/migrations/2013_01_31_141600_create_lists.php
new file mode 100644
index 0000000..873dcb3
--- /dev/null
+++ b/app/database/migrations/2013_01_31_141600_create_lists.php
@@ -0,0 +1,35 @@
+increments('id');
+ $table->integer('user_id')->unsigned();
+ $table->string('name');
+ $table->timestamps();
+
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('lists');
+ }
+
+}
\ No newline at end of file
diff --git a/app/database/migrations/2013_01_31_141613_create_tasks.php b/app/database/migrations/2013_01_31_141613_create_tasks.php
new file mode 100644
index 0000000..82ff8e7
--- /dev/null
+++ b/app/database/migrations/2013_01_31_141613_create_tasks.php
@@ -0,0 +1,36 @@
+increments('id');
+ $table->integer('list_id')->unsigned();
+ $table->string('description');
+ $table->boolean('completed');
+ $table->timestamps();
+
+ $table->foreign('list_id')->references('id')->on('lists')->onDelete('cascade')->onUpdate('cascade');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('tasks');
+ }
+
+}
\ No newline at end of file
diff --git a/app/database/production.sqlite b/app/database/production.sqlite
new file mode 100644
index 0000000..e69de29
diff --git a/app/database/seeds/.gitkeep b/app/database/seeds/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php
new file mode 100644
index 0000000..45f529c
--- /dev/null
+++ b/app/database/seeds/DatabaseSeeder.php
@@ -0,0 +1,25 @@
+call('UserTableSeeder');
+ }
+}
+
+class UserTableSeeder extends Seeder
+{
+ public function run()
+ {
+ User::create(array(
+ 'username' => 'admin',
+ 'password' => 'admin',
+ ));
+ }
+}
\ No newline at end of file
diff --git a/app/errors.php b/app/errors.php
new file mode 100644
index 0000000..a1e2cba
--- /dev/null
+++ b/app/errors.php
@@ -0,0 +1,67 @@
+getHeaders();
+
+ switch ($code)
+ {
+ case 401:
+ $default_message = 'Invalid API key';
+ $headers['WWW-Authenticate'] = 'Basic realm="REST API"';
+ break;
+
+ case 403:
+ $default_message = 'Insufficient privileges to perform this action';
+ break;
+
+ case 404:
+ $default_message = 'The requested resource was not found';
+ break;
+
+ default:
+ $default_message = 'An unexpected error occurred';
+ }
+
+ return Response::json(array(
+ 'error' => $e->getMessage() ?: $default_message,
+ ), $code, $headers);
+});
+
+// ErrorMessageException handler
+App::error(function(ErrorMessageException $e)
+{
+ return Response::json(array(
+ 'errors' => $e->getMessages()->all(),
+ ), 400);
+});
+
+// NotFoundException handler
+App::error(function(NotFoundException $e)
+{
+ $default_message = 'The requested resource was not found';
+
+ return Response::json(array(
+ 'error' => $e->getMessage() ?: $default_message,
+ ), 404);
+});
+
+// PermissionException handler
+App::error(function(PermissionException $e)
+{
+ $default_message = 'Insufficient privileges to perform this action';
+
+ return Response::json(array(
+ 'error' => $e->getMessage() ?: $default_message,
+ ), 403);
+});
\ No newline at end of file
diff --git a/app/events.php b/app/events.php
new file mode 100644
index 0000000..7f59772
--- /dev/null
+++ b/app/events.php
@@ -0,0 +1,10 @@
+api_key = User::createApiKey();
+});
\ No newline at end of file
diff --git a/app/exceptions/ErrorMessageException.php b/app/exceptions/ErrorMessageException.php
new file mode 100644
index 0000000..e814994
--- /dev/null
+++ b/app/exceptions/ErrorMessageException.php
@@ -0,0 +1,46 @@
+messages = $messages->getMessageBag();
+ $this->messages->setFormat(':message');
+
+ parent::__construct('', $code, $previous);
+ }
+
+ /**
+ * Return error messages.
+ *
+ * @return Illuminate\Support\MessageBag
+ */
+ public function getMessages()
+ {
+ return $this->messages;
+ }
+}
\ No newline at end of file
diff --git a/app/exceptions/NotFoundException.php b/app/exceptions/NotFoundException.php
new file mode 100644
index 0000000..464fb86
--- /dev/null
+++ b/app/exceptions/NotFoundException.php
@@ -0,0 +1,3 @@
+first();
+
+ if (!$user)
+ {
+ App::abort(401);
+ }
+
+ Auth::login($user);
+});
+
+Route::filter('api.limit', function()
+{
+ $key = sprintf('api:%s', Auth::user()->api_key);
+
+ // Create the key if it doesn't exist
+ apc_add($key, 0, 60*60);
+
+ // Increment by 1
+ $count = apc_inc($key);
+
+ // Fail if hourly requests exceeded
+ if ($count > Config::get('api.requests_per_hour'))
+ {
+ App::abort(403, 'Hourly request limit exceeded');
+ }
+});
\ No newline at end of file
diff --git a/app/lang/en/pagination.php b/app/lang/en/pagination.php
new file mode 100644
index 0000000..eb9be3b
--- /dev/null
+++ b/app/lang/en/pagination.php
@@ -0,0 +1,20 @@
+ '« Previous',
+
+ 'next' => 'Next »',
+
+);
\ No newline at end of file
diff --git a/app/lang/en/reminders.php b/app/lang/en/reminders.php
new file mode 100644
index 0000000..4a9f176
--- /dev/null
+++ b/app/lang/en/reminders.php
@@ -0,0 +1,22 @@
+ "Passwords must be six characters and match the confirmation.",
+
+ "user" => "We can't find a user with that e-mail address.",
+
+ "token" => "This password reset token is invalid.",
+
+);
\ No newline at end of file
diff --git a/app/lang/en/validation.php b/app/lang/en/validation.php
new file mode 100644
index 0000000..a67a114
--- /dev/null
+++ b/app/lang/en/validation.php
@@ -0,0 +1,91 @@
+ "The :attribute must be accepted.",
+ "active_url" => "The :attribute is not a valid URL.",
+ "after" => "The :attribute must be a date after :date.",
+ "alpha" => "The :attribute may only contain letters.",
+ "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
+ "alpha_num" => "The :attribute may only contain letters and numbers.",
+ "before" => "The :attribute must be a date before :date.",
+ "between" => array(
+ "numeric" => "The :attribute must be between :min - :max.",
+ "file" => "The :attribute must be between :min - :max kilobytes.",
+ "string" => "The :attribute must be between :min - :max characters.",
+ ),
+ "confirmed" => "The :attribute confirmation does not match.",
+ "date" => "The :attribute is not a valid date.",
+ "date_format" => "The :attribute does not match the format :format.",
+ "different" => "The :attribute and :other must be different.",
+ "digits" => "The :attribute must be :digits digits.",
+ "digits_between" => "The :attribute must be between :min and :max digits.",
+ "email" => "The :attribute format is invalid.",
+ "exists" => "The selected :attribute is invalid.",
+ "image" => "The :attribute must be an image.",
+ "in" => "The selected :attribute is invalid.",
+ "integer" => "The :attribute must be an integer.",
+ "ip" => "The :attribute must be a valid IP address.",
+ "match" => "The :attribute format is invalid.",
+ "max" => array(
+ "numeric" => "The :attribute must be less than :max.",
+ "file" => "The :attribute must be less than :max kilobytes.",
+ "string" => "The :attribute must be less than :max characters.",
+ ),
+ "mimes" => "The :attribute must be a file of type: :values.",
+ "min" => array(
+ "numeric" => "The :attribute must be at least :min.",
+ "file" => "The :attribute must be at least :min kilobytes.",
+ "string" => "The :attribute must be at least :min characters.",
+ ),
+ "notin" => "The selected :attribute is invalid.",
+ "numeric" => "The :attribute must be a number.",
+ "required" => "The :attribute field is required.",
+ "required_with" => "The :attribute field is required when :values is present.",
+ "same" => "The :attribute and :other must match.",
+ "size" => array(
+ "numeric" => "The :attribute must be :size.",
+ "file" => "The :attribute must be :size kilobytes.",
+ "string" => "The :attribute must be :size characters.",
+ ),
+ "unique" => "The :attribute has already been taken.",
+ "url" => "The :attribute format is invalid.",
+
+ /*
+ |--------------------------------------------------------------------------
+ | Custom Validation Language Lines
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify custom validation messages for attributes using the
+ | convention "attribute.rule" to name the lines. This makes it quick to
+ | specify a specific custom language line for a given attribute rule.
+ |
+ */
+
+ 'custom' => array(),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Custom Validation Attributes
+ |--------------------------------------------------------------------------
+ |
+ | The following language lines are used to swap attribute place-holders
+ | with something more reader friendly such as E-Mail Address instead
+ | of "email". This simply helps us make messages a little cleaner.
+ |
+ */
+
+ 'attributes' => array(),
+
+);
\ No newline at end of file
diff --git a/app/models/Task.php b/app/models/Task.php
new file mode 100644
index 0000000..566f172
--- /dev/null
+++ b/app/models/Task.php
@@ -0,0 +1,99 @@
+belongsTo('TaskList', 'list_id');
+ }
+
+ /**
+ * Completed mutator.
+ *
+ * @param mixed $completed
+ * @return void
+ */
+ protected function setCompletedAttribute($completed)
+ {
+ $value = 0;
+
+ $completed = strtolower($completed);
+
+ if (in_array($completed, array('y', 'yes', '1', 'true', 't')))
+ {
+ $value = 1;
+ }
+
+ $this->attributes['completed'] = $value;
+ }
+
+ /**
+ * Completed accessor.
+ *
+ * @return bool
+ */
+ protected function getCompletedAttribute($completed)
+ {
+ return (bool) $completed;
+ }
+
+ /**
+ * Validate the model's attributes.
+ *
+ * @return void
+ */
+ public function validate()
+ {
+ $val = Validator::make($this->attributes, array(
+ 'description' => 'required',
+ ));
+
+ if ($val->fails())
+ {
+ throw new ValidationException($val);
+ }
+ }
+
+ /**
+ * Convert the model instance to an array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $data = parent::toArray();
+
+ $data['id'] = (int) $this->id;
+ $data['completed'] = $this->completed;
+ $data['created_at'] = $this->fromDateTime($this->created_at);
+ $data['updated_at'] = $this->fromDateTime($this->updated_at);
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/app/models/TaskList.php b/app/models/TaskList.php
new file mode 100644
index 0000000..5310cc7
--- /dev/null
+++ b/app/models/TaskList.php
@@ -0,0 +1,118 @@
+belongsTo('User');
+ }
+
+ /**
+ * Tasks relationship.
+ *
+ * @return Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function tasks()
+ {
+ return $this->hasMany('Task', 'list_id');
+ }
+
+ /**
+ * Find a list by ID, and verify its ownership by the given user
+ *
+ * @param Illuminate\Auth\UserInterface|int $owner
+ * @param int $id
+ * @return Illuminate\Database\Eloquent\Model
+ */
+ public static function findByOwnerAndId($owner, $id)
+ {
+ if (!is_numeric($owner) && !($owner instanceof UserInterface))
+ {
+ throw new InvalidArgumentException('Owner must be either a numeric ID or an instance of UserInterface');
+ }
+
+ $list = static::find($id);
+
+ if (!$list)
+ {
+ throw new NotFoundException('List was not found');
+ }
+
+ $owner_id = ($owner instanceof UserInterface) ? (int) $owner->id : (int) $owner;
+
+ if ((int) $list->user_id !== $owner_id)
+ {
+ throw new PermissionException('Insufficient access privileges for this list');
+ }
+
+ return $list;
+ }
+
+ /**
+ * Validate the model's attributes.
+ *
+ * @return void
+ */
+ public function validate()
+ {
+ $val = Validator::make($this->attributes, array(
+ 'name' => 'required',
+ ));
+
+ if ($val->fails())
+ {
+ throw new ValidationException($val);
+ }
+ }
+
+ /**
+ * Convert the model instance to an array.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $data = parent::toArray();
+
+ $data['id'] = (int) $this->id;
+ $data['created_at'] = $this->fromDateTime($this->created_at);
+ $data['updated_at'] = $this->fromDateTime($this->updated_at);
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/app/models/User.php b/app/models/User.php
new file mode 100644
index 0000000..4bbb417
--- /dev/null
+++ b/app/models/User.php
@@ -0,0 +1,72 @@
+hasMany('TaskList');
+ }
+
+ /**
+ * Get the unique identifier for the user.
+ *
+ * @return mixed
+ */
+ public function getAuthIdentifier()
+ {
+ return $this->getKey();
+ }
+
+ /**
+ * Get the password for the user.
+ *
+ * @return string
+ */
+ public function getAuthPassword()
+ {
+ return $this->password;
+ }
+
+ /**
+ * Password mutator.
+ *
+ * @param string $password
+ * @return void
+ */
+ public function setPasswordAttribute($password)
+ {
+ $this->attributes['password'] = Hash::make($password);
+ }
+
+ /**
+ * Generate a random, unique API key.
+ *
+ * @return string
+ */
+ public static function createApiKey()
+ {
+ return Str::secureRandom(32);
+ }
+}
\ No newline at end of file
diff --git a/app/routes.php b/app/routes.php
new file mode 100644
index 0000000..055781f
--- /dev/null
+++ b/app/routes.php
@@ -0,0 +1,150 @@
+ 'v1', 'before' => 'api.auth|api.limit'), function()
+{
+ // Get all lists
+ Route::get('lists', function()
+ {
+ $lists = Auth::user()->tasklists;
+
+ return Response::json($lists->toArray());
+ });
+
+ // Create new list
+ Route::post('lists', function()
+ {
+ $list = new TaskList(Input::get());
+ $list->validate();
+ $list->user_id = Auth::user()->id;
+
+ if (!$list->save())
+ {
+ App::abort(500, 'List was not saved');
+ }
+
+ return Response::json($list->toArray(), 201);
+ });
+
+ // Get list by ID
+ Route::get('lists/{id}', function($id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $id);
+
+ return Response::json($list->toArray());
+ })->where('id', '\d+');
+
+ // Update list by ID
+ Route::put('lists/{id}', function($id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $id);
+ $list->fill(Input::get());
+ $list->validate();
+
+ if (!$list->save())
+ {
+ App::abort(500, 'List was not updated');
+ }
+
+ return Response::json($list->toArray());
+ })->where('id', '\d+');
+
+ // Delete list by ID
+ Route::delete('lists/{id}', function($id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $id);
+ $list->delete();
+
+ return Response::json(null, 204);
+ })->where('id', '\d+');
+
+ // Get tasks for list
+ Route::get('lists/{id}/tasks', function($id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $id);
+
+ return Response::json($list->tasks->toArray());
+ })->where('id', '\d+');
+
+ // Create task
+ Route::post('lists/{id}/tasks', function($id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $id);
+
+ $task = new Task(Input::get());
+ $task->validate();
+ $task->list_id = $id;
+
+ if (!$task->save())
+ {
+ App::abort(500, 'Task was not saved');
+ }
+
+ return Response::json($task->toArray(), 201);
+ })->where('id', '\d+');
+
+ // Get task by ID
+ Route::get('lists/{list_id}/tasks/{id}', function($list_id, $id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $list_id);
+
+ $task = $list->tasks()->find($id);
+
+ if (!$task)
+ {
+ App::abort(404);
+ }
+
+ return Response::json($task->toArray());
+ })->where('list_id', '\d+')->where('id', '\d+');
+
+ // Update task
+ Route::put('lists/{list_id}/tasks/{id}', function($list_id, $id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $list_id);
+
+ $task = $list->tasks()->find($id);
+
+ if (!$task)
+ {
+ App::abort(404);
+ }
+
+ $task->fill(Input::get());
+ $task->validate();
+
+ if (!$task->save())
+ {
+ App::abort(500, 'Task was not updated');
+ }
+
+ return Response::json($task->toArray());
+ })->where('list_id', '\d+')->where('id', '\d+');
+
+ // Delete task
+ Route::delete('lists/{list_id}/tasks/{id}', function($list_id, $id)
+ {
+ $list = TaskList::findByOwnerAndId(Auth::user(), $list_id);
+
+ $task = $list->tasks()->find($id);
+
+ if (!$task)
+ {
+ App::abort(404);
+ }
+
+ $task->delete();
+
+ return Response::json(null, 204);
+ })->where('list_id', '\d+')->where('id', '\d+');
+});
\ No newline at end of file
diff --git a/app/start/artisan.php b/app/start/artisan.php
new file mode 100644
index 0000000..1df850b
--- /dev/null
+++ b/app/start/artisan.php
@@ -0,0 +1,13 @@
+boot();
+
+/*
+|--------------------------------------------------------------------------
+| Load The Artisan Console Application
+|--------------------------------------------------------------------------
+|
+| We'll need to run the script to load and return the Artisan console
+| application. We keep this in its own script so that we will load
+| the console application independent of running commands which
+| will allow us to fire commands from Routes when we want to.
+|
+*/
+
+$artisan = Illuminate\Console\Application::start($app);
+
+/*
+|--------------------------------------------------------------------------
+| Run The Artisan Application
+|--------------------------------------------------------------------------
+|
+| When we run the console application, the current CLI command will be
+| executed in this console and the response sent back to a terminal
+| or another output device for the developers. Here goes nothing!
+|
+*/
+
+$artisan->run();
diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php
new file mode 100644
index 0000000..461a1a8
--- /dev/null
+++ b/bootstrap/autoload.php
@@ -0,0 +1,44 @@
+ __DIR__.'/../app',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Public Path
+ |--------------------------------------------------------------------------
+ |
+ | The public path contains the assets for your web application, such as
+ | your JavaScript and CSS files, and also contains the primary entry
+ | point for web requests into these applications from the outside.
+ |
+ */
+
+ 'public' => __DIR__.'/../public',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Base Path
+ |--------------------------------------------------------------------------
+ |
+ | The base path is the root of the Laravel installation. Most likely you
+ | will not need to change this value. But, if for some wild reason it
+ | is necessary you will do so here, just proceed with some caution.
+ |
+ */
+
+ 'base' => __DIR__.'/..',
+
+);
diff --git a/bootstrap/start.php b/bootstrap/start.php
new file mode 100644
index 0000000..7e5462e
--- /dev/null
+++ b/bootstrap/start.php
@@ -0,0 +1,70 @@
+detectEnvironment(array(
+
+ 'local' => array('localhost', '*.dev', '*.app'),
+
+));
+
+/*
+|--------------------------------------------------------------------------
+| Bind Paths
+|--------------------------------------------------------------------------
+|
+| Here we are binding the paths configured in paths.php to the app. You
+| should not be changing these here. If you need to change these you
+| may do so within the paths.php file and they will be bound here.
+|
+*/
+
+$app->bindInstallPaths(require __DIR__.'/paths.php');
+
+/*
+|--------------------------------------------------------------------------
+| Load The Application
+|--------------------------------------------------------------------------
+|
+| Here we will load the Illuminate application. We'll keep this is in a
+| separate location so we can isolate the creation of an application
+| from the actual running of the application with a given request.
+|
+*/
+
+require $app->getBootstrapFile();
+
+/*
+|--------------------------------------------------------------------------
+| Return The Application
+|--------------------------------------------------------------------------
+|
+| This script returns the application instance. The instance is given to
+| the calling script so we can separate the building of the instances
+| from the actual running of the application and sending responses.
+|
+*/
+
+return $app;
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..024d065
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,17 @@
+{
+ "require": {
+ "laravel/framework": "4.0.*"
+ },
+ "autoload": {
+ "classmap": [
+ "app/commands",
+ "app/controllers",
+ "app/exceptions",
+ "app/models",
+ "app/database/migrations",
+ "app/database/seeds",
+ "app/tests/TestCase.php"
+ ]
+ },
+ "minimum-stability": "dev"
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..e21c716
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,926 @@
+{
+ "hash": "2a9c37e837664e054f147503d358abb1",
+ "packages": [
+ {
+ "name": "ircmaxell/password-compat",
+ "version": "1.0.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ircmaxell/password_compat.git",
+ "reference": "v1.0.0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/ircmaxell/password_compat/archive/v1.0.0.zip",
+ "reference": "v1.0.0",
+ "shasum": ""
+ },
+ "time": "2013-01-14 16:49:31",
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/password.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Anthony Ferrara",
+ "email": "ircmaxell@php.net",
+ "homepage": "http://blog.ircmaxell.com"
+ }
+ ],
+ "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash",
+ "homepage": "https://github.com/ircmaxell/password_compat",
+ "keywords": [
+ "hashing",
+ "password"
+ ]
+ },
+ {
+ "name": "laravel/framework",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/framework.git",
+ "reference": "5d0e6ecc135421b5672b63c583a508fc71af55c7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/5d0e6ecc135421b5672b63c583a508fc71af55c7",
+ "reference": "5d0e6ecc135421b5672b63c583a508fc71af55c7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mcrypt": "*",
+ "ircmaxell/password-compat": "1.0.*",
+ "monolog/monolog": "1.3.*",
+ "patchwork/utf8": "1.0.*",
+ "php": ">=5.3.0",
+ "swiftmailer/swiftmailer": "4.3.*",
+ "symfony/browser-kit": "2.2.*",
+ "symfony/console": "2.2.*",
+ "symfony/css-selector": "2.2.*",
+ "symfony/dom-crawler": "2.2.*",
+ "symfony/event-dispatcher": "2.2.*",
+ "symfony/finder": "2.2.*",
+ "symfony/http-foundation": "2.2.*",
+ "symfony/http-kernel": "2.2.*",
+ "symfony/process": "2.2.*",
+ "symfony/routing": "2.2.*",
+ "symfony/translation": "2.2.*"
+ },
+ "replace": {
+ "illuminate/auth": "self.version",
+ "illuminate/cache": "self.version",
+ "illuminate/config": "self.version",
+ "illuminate/console": "self.version",
+ "illuminate/container": "self.version",
+ "illuminate/cookie": "self.version",
+ "illuminate/database": "self.version",
+ "illuminate/encryption": "self.version",
+ "illuminate/events": "self.version",
+ "illuminate/exception": "self.version",
+ "illuminate/filesystem": "self.version",
+ "illuminate/foundation": "self.version",
+ "illuminate/hashing": "self.version",
+ "illuminate/http": "self.version",
+ "illuminate/log": "self.version",
+ "illuminate/mail": "self.version",
+ "illuminate/pagination": "self.version",
+ "illuminate/queue": "self.version",
+ "illuminate/redis": "self.version",
+ "illuminate/routing": "self.version",
+ "illuminate/session": "self.version",
+ "illuminate/support": "self.version",
+ "illuminate/translation": "self.version",
+ "illuminate/validation": "self.version",
+ "illuminate/view": "self.version",
+ "illuminate/workbench": "self.version"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "2.1.*",
+ "mockery/mockery": "0.7.2"
+ },
+ "time": "2013-02-15 16:15:55",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/Illuminate/Queue/Pheanstalk"
+ ],
+ "files": [
+ "src/Illuminate/Support/helpers.php"
+ ],
+ "psr-0": {
+ "Illuminate": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylorotwell@gmail.com"
+ }
+ ],
+ "description": "The Laravel Framework.",
+ "keywords": [
+ "framework",
+ "laravel"
+ ]
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog",
+ "reference": "1.3.1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/Seldaek/monolog/archive/1.3.1.zip",
+ "reference": "1.3.1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/log": ">=1.0,<2.0"
+ },
+ "require-dev": {
+ "doctrine/couchdb": "dev-master",
+ "mlehner/gelf-php": "1.0.*",
+ "raven/raven": "0.3.*"
+ },
+ "suggest": {
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-mongo": "Allow sending log messages to a MongoDB server",
+ "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "raven/raven": "Allow sending log messages to a Sentry server"
+ },
+ "time": "2013-01-11 10:23:20",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Monolog": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be",
+ "role": "Developer"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "http://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "patchwork/utf8",
+ "version": "v1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nicolas-grekas/Patchwork-UTF8.git",
+ "reference": "v1.0.4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/nicolas-grekas/Patchwork-UTF8/archive/v1.0.4.zip",
+ "reference": "v1.0.4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "time": "2012-12-13 08:48:39",
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootup.utf8.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "(Apache-2.0 or GPL-2.0)"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "UTF-8 strings handling for PHP 5.3: portable, performant and extended",
+ "homepage": "https://github.com/nicolas-grekas/Patchwork-UTF8",
+ "keywords": [
+ "i18n",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ]
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log",
+ "reference": "1.0.0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/php-fig/log/archive/1.0.0.zip",
+ "reference": "1.0.0",
+ "shasum": ""
+ },
+ "time": "2012-12-21 11:40:51",
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Psr\\Log\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ]
+ },
+ {
+ "name": "swiftmailer/swiftmailer",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "git://github.com/swiftmailer/swiftmailer.git",
+ "reference": "b6bfc8f7f8ae5dac7883885ee323dc3b53ab7d21"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/b6bfc8f7f8ae5dac7883885ee323dc3b53ab7d21",
+ "reference": "b6bfc8f7f8ae5dac7883885ee323dc3b53ab7d21",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.4"
+ },
+ "time": "2013-02-04 10:09:01",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.3-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "lib/swift_required.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Chris Corbyn"
+ }
+ ],
+ "description": "Swiftmailer, free feature-rich PHP mailer",
+ "homepage": "http://swiftmailer.org",
+ "keywords": [
+ "mail",
+ "mailer"
+ ]
+ },
+ {
+ "name": "symfony/browser-kit",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/BrowserKit",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/BrowserKit",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/BrowserKit/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "symfony/dom-crawler": ">=2.0,<3.0"
+ },
+ "require-dev": {
+ "symfony/css-selector": ">=2.0,<3.0",
+ "symfony/process": ">=2.0,<3.0"
+ },
+ "suggest": {
+ "symfony/process": "2.2.*"
+ },
+ "time": "2013-02-08 16:10:53",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\BrowserKit\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony BrowserKit Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/console",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/Console",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Console",
+ "reference": "v2.2.0-RC1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Console/zipball/v2.2.0-RC1",
+ "reference": "v2.2.0-RC1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2013-01-24 15:55:08",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Console\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/css-selector",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/CssSelector",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/CssSelector",
+ "reference": "v2.2.0-BETA2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/CssSelector/zipball/v2.2.0-BETA2",
+ "reference": "v2.2.0-BETA2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2013-01-17 15:25:59",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\CssSelector\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony CssSelector Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/dom-crawler",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/DomCrawler",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/DomCrawler",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/css-selector": ">=2.0,<3.0"
+ },
+ "suggest": {
+ "symfony/css-selector": "2.2.*"
+ },
+ "time": "2013-02-08 16:10:52",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\DomCrawler\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony DomCrawler Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/EventDispatcher",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/EventDispatcher",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/dependency-injection": ">=2.0,<3.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "2.2.*",
+ "symfony/http-kernel": "2.2.*"
+ },
+ "time": "2013-02-11 11:26:43",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/Finder",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Finder",
+ "reference": "v2.2.0-RC1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.2.0-RC1",
+ "reference": "v2.2.0-RC1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2013-02-04 12:41:13",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Finder\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/HttpFoundation",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/HttpFoundation",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2013-02-11 12:46:49",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "classmap": [
+ "Symfony/Component/HttpFoundation/Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpFoundation Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/HttpKernel",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/HttpKernel",
+ "reference": "cec254f40ea9baaa2b90de7ca6de236de76823eb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/cec254f40ea9baaa2b90de7ca6de236de76823eb",
+ "reference": "cec254f40ea9baaa2b90de7ca6de236de76823eb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "psr/log": ">=1.0,<2.0",
+ "symfony/event-dispatcher": ">=2.1,<3.0",
+ "symfony/http-foundation": ">=2.2,<2.3-dev"
+ },
+ "require-dev": {
+ "symfony/browser-kit": "2.2.*",
+ "symfony/class-loader": ">=2.1,<3.0",
+ "symfony/config": ">=2.0,<3.0",
+ "symfony/console": "2.2.*",
+ "symfony/dependency-injection": ">=2.0,<3.0",
+ "symfony/finder": ">=2.0,<3.0",
+ "symfony/process": ">=2.0,<3.0",
+ "symfony/routing": ">=2.2,<2.3-dev",
+ "symfony/stopwatch": ">=2.2,<2.3-dev"
+ },
+ "suggest": {
+ "symfony/browser-kit": "2.2.*",
+ "symfony/class-loader": "2.2.*",
+ "symfony/config": "2.2.*",
+ "symfony/console": "2.2.*",
+ "symfony/dependency-injection": "2.2.*",
+ "symfony/finder": "2.2.*"
+ },
+ "time": "2013-02-13 01:35:51",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpKernel Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/process",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/Process",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Process",
+ "reference": "v2.2.0-RC1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Process/zipball/v2.2.0-RC1",
+ "reference": "v2.2.0-RC1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "time": "2013-01-31 18:27:04",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Process\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Process Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/routing",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/Routing",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Routing",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "doctrine/common": ">=2.2,<3.0",
+ "psr/log": ">=1.0,<2.0",
+ "symfony/config": ">=2.2,<2.3-dev",
+ "symfony/yaml": ">=2.0,<3.0"
+ },
+ "suggest": {
+ "doctrine/common": "~2.2",
+ "symfony/config": "2.2.*",
+ "symfony/yaml": "2.2.*"
+ },
+ "time": "2013-02-11 11:24:47",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Routing\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Routing Component",
+ "homepage": "http://symfony.com"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "2.2.x-dev",
+ "target-dir": "Symfony/Component/Translation",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Translation",
+ "reference": "v2.2.0-RC2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.2.0-RC2",
+ "reference": "v2.2.0-RC2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/config": ">=2.0,<2.3-dev",
+ "symfony/yaml": ">=2.2,<3.0"
+ },
+ "suggest": {
+ "symfony/config": "2.2.*",
+ "symfony/yaml": "2.2.*"
+ },
+ "time": "2013-02-08 16:10:57",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.2-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Translation\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Translation Component",
+ "homepage": "http://symfony.com"
+ }
+ ],
+ "packages-dev": null,
+ "aliases": [
+
+ ],
+ "minimum-stability": "dev",
+ "stability-flags": [
+
+ ]
+}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..c42dc4f
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ ./app/tests/
+
+
+
\ No newline at end of file
diff --git a/public/.htaccess b/public/.htaccess
new file mode 100644
index 0000000..0e85365
--- /dev/null
+++ b/public/.htaccess
@@ -0,0 +1,8 @@
+php_value magic_quotes_gpc Off
+
+
+ Options -MultiViews
+ RewriteEngine On
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.php [L]
+
\ No newline at end of file
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/index.php b/public/index.php
new file mode 100644
index 0000000..030db7d
--- /dev/null
+++ b/public/index.php
@@ -0,0 +1,51 @@
+
+ */
+
+define('LARAVEL_START', microtime(true));
+
+/*
+|--------------------------------------------------------------------------
+| Register The Auto Loader
+|--------------------------------------------------------------------------
+|
+| Composer provides a convenient, automatically generated class loader
+| for our application. We just need to utilize it! We'll require it
+| into the script here so that we do not have to worry about the
+| loading of any our classes "manually". Feels great to relax.
+|
+*/
+
+require __DIR__.'/../bootstrap/autoload.php';
+
+/*
+|--------------------------------------------------------------------------
+| Turn On The Lights
+|--------------------------------------------------------------------------
+|
+| We need to illuminate PHP development, so let's turn on the lights.
+| This bootstrap the framework and gets it ready for use, then it
+| will load up this application so that we can run it and send
+| the responses back to the browser and delight these users.
+|
+*/
+
+$app = require_once __DIR__.'/../bootstrap/start.php';
+
+/*
+|--------------------------------------------------------------------------
+| Run The Application
+|--------------------------------------------------------------------------
+|
+| Once we have the application, we can simply call the run method,
+| which will execute the request and send the response back to
+| the client's browser allowing them to enjoy the creative
+| and wonderful applications we have created for them.
+|
+*/
+
+$app->run();
diff --git a/public/packages/.gitkeep b/public/packages/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..c30190d
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,86 @@
+# Laracon 2013 Demo API
+
+## Setup Instructions
+
+1. Make sure you have [Composer](http://getcomposer.org/) installed. I recommend [installing it globally](http://getcomposer.org/doc/00-intro.md#globally).
+2. Clone or download this repository.
+3. In a terminal, `cd` into this project's directory and run `composer install`.
+4. Create a new MySQL database.
+5. Update the `mysql` connection options in `app/config/database.php`.
+6. Run `php artisan migrate` in the terminal.
+7. Run `php artisan db:seed` in the terminal.
+8. Start hitting the API in whatever tool you choose. [Postman](https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?utm_source=chrome-ntp-launcher) is a nice Chrome extension, and [HTTPie](https://github.com/jkbr/httpie) is a good command line option.
+
+## API Documentation
+
+### Authentication
+
+The API uses Basic HTTP authentication for all requests. You must pass a valid API key as a username, and the password can literally be anything.
+
+If you were going to connect via cURL, you would do this:
+
+`curl -u "youruserapikeygoeshere:whatever" http://localapidomain.dev/v1/lists`
+
+Note that we sent **whatever** as the password. This can be anything… it doesn't matter. However, since authentication is based on the API key only, you shouldn't share it with anyone.
+
+### Response Formats
+
+All responses are in JSON format.
+
+### Response Codes
+
+* **200:** The request was successful.
+* **201:** The resource was successfully created.
+* **204:** The request was successful, but we did not send any content back.
+* **400:** The request failed due to an application error, such as a validation error.
+* **401:** An API key was either not sent or invalid.
+* **403:** The resource does not belong to the authenticated user and is forbidden.
+* **404:** The resource was not found.
+* **500:** A server error occurred.
+
+## API Endpoints
+
+### GET /v1/lists
+
+Retrieve an array of the authenticated user's tasklists.
+
+### POST /v1/lists
+
+Create a new tasklist. Returns status code **201** on success. Accepts the following parameters:
+
+* **name** – The name of the tasklist.
+
+### GET /v1/lists/{id}
+
+Retrieve the tasklist with the given ID.
+
+### PUT /v1/lists/{id}
+
+Update the tasklist with the given ID. Accepts the same parameters as **POST /v1/lists**.
+
+### DELETE /v1/lists/{id}
+
+Delete the tasklist (and all associated tasks) with the given ID. Returns status code **204** on success.
+
+### GET /v1/lists/{id}/tasks
+
+Retrieve tasks for the tasklist with the given ID.
+
+### POST /v1/lists/{id}/tasks
+
+Create a new task for the tasklist with the given ID. Returns status code **201** on success. Accepts the following parameters:
+
+* **description** – The description of the task.
+* **completed** – Whether or not the task is completed. A value of **yes**, **y**, **1**, **true**, or **t** will set the task as completed. Anything else will set the task as not completed.
+
+### GET /v1/lists/{id}/tasks/{taskid}
+
+Retrieve the task with the given ID.
+
+### PUT /v1/lists/{id}/tasks/{taskid}
+
+Update the task with the given ID. Accepts the same parameters as **POST /v1/lists/{id}/tasks**.
+
+### DELETE /v1/lists/{id}/tasks/{taskid}
+
+Delete the task with the given ID. Returns status code **204** on success.
\ No newline at end of file
diff --git a/server.php b/server.php
new file mode 100644
index 0000000..5f187f3
--- /dev/null
+++ b/server.php
@@ -0,0 +1,19 @@
+instance('path', $appPath = __DIR__.'/app');
+
+$app->instance('path.base', __DIR__);
+
+/*
+|--------------------------------------------------------------------------
+| Detect The Application Environment
+|--------------------------------------------------------------------------
+|
+| Laravel takes a dead simple approach to your application environments
+| so you can just specify a machine name or HTTP host that matches a
+| given environment, then we will automatically detect it for you.
+|
+*/
+
+$env = $app->detectEnvironment(array(
+
+ 'local' => array('localhost', '*.dev', '*.app'),
+
+));
+
+/*
+|--------------------------------------------------------------------------
+| Load The Application
+|--------------------------------------------------------------------------
+|
+| Here we will load the Illuminate application. We'll keep this is in a
+| separate location so we can isolate the creation of an application
+| from the actual running of the application with a given request.
+|
+*/
+
+require $app->getBootstrapFile();
+
+/*
+|--------------------------------------------------------------------------
+| Return The Application
+|--------------------------------------------------------------------------
+|
+| This script returns the application instance. The instance is given to
+| the calling script so we can separate the building of the instances
+| from the actual running of the application and sending responses.
+|
+*/
+
+return $app;
\ No newline at end of file