diff --git a/app/AppKernel.php b/app/AppKernel.php index e5a36ae..d57c12f 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -32,6 +32,10 @@ public function registerBundles() new AntiMattr\GoogleBundle\GoogleBundle(), new Aga\DateConverterBundle\DateConverterBundle(), new Eko\FeedBundle\EkoFeedBundle(), + new FOS\OAuthServerBundle\FOSOAuthServerBundle(), + new FOS\RestBundle\FOSRestBundle(), + new JMS\SerializerBundle\JMSSerializerBundle($this), + new Cobase\ApiBundle\CobaseApiBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { diff --git a/app/DoctrineMigrations/Version20130805150654.php b/app/DoctrineMigrations/Version20130805150654.php new file mode 100644 index 0000000..a3efd20 --- /dev/null +++ b/app/DoctrineMigrations/Version20130805150654.php @@ -0,0 +1,43 @@ +abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'."); + + $this->addSql("CREATE TABLE AccessToken (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_B39617F55F37A13B (token), INDEX IDX_B39617F519EB6921 (client_id), INDEX IDX_B39617F5A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB"); + $this->addSql("CREATE TABLE Client (id INT AUTO_INCREMENT NOT NULL, random_id VARCHAR(255) NOT NULL, redirect_uris LONGTEXT NOT NULL COMMENT '(DC2Type:array)', secret VARCHAR(255) NOT NULL, allowed_grant_types LONGTEXT NOT NULL COMMENT '(DC2Type:array)', name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB"); + $this->addSql("CREATE TABLE RefreshToken (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_7142379E5F37A13B (token), INDEX IDX_7142379E19EB6921 (client_id), INDEX IDX_7142379EA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB"); + $this->addSql("CREATE TABLE AuthCode (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, user_id INT DEFAULT NULL, token VARCHAR(255) NOT NULL, redirect_uri LONGTEXT NOT NULL, expires_at INT DEFAULT NULL, scope VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_F1D7D1775F37A13B (token), INDEX IDX_F1D7D17719EB6921 (client_id), INDEX IDX_F1D7D177A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB"); + $this->addSql("ALTER TABLE AccessToken ADD CONSTRAINT FK_B39617F519EB6921 FOREIGN KEY (client_id) REFERENCES Client (id)"); + $this->addSql("ALTER TABLE AccessToken ADD CONSTRAINT FK_B39617F5A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)"); + $this->addSql("ALTER TABLE RefreshToken ADD CONSTRAINT FK_7142379E19EB6921 FOREIGN KEY (client_id) REFERENCES Client (id)"); + $this->addSql("ALTER TABLE RefreshToken ADD CONSTRAINT FK_7142379EA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)"); + $this->addSql("ALTER TABLE AuthCode ADD CONSTRAINT FK_F1D7D17719EB6921 FOREIGN KEY (client_id) REFERENCES Client (id)"); + $this->addSql("ALTER TABLE AuthCode ADD CONSTRAINT FK_F1D7D177A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)"); + } + + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'."); + + $this->addSql("ALTER TABLE AccessToken DROP FOREIGN KEY FK_B39617F519EB6921"); + $this->addSql("ALTER TABLE RefreshToken DROP FOREIGN KEY FK_7142379E19EB6921"); + $this->addSql("ALTER TABLE AuthCode DROP FOREIGN KEY FK_F1D7D17719EB6921"); + $this->addSql("DROP TABLE AccessToken"); + $this->addSql("DROP TABLE Client"); + $this->addSql("DROP TABLE RefreshToken"); + $this->addSql("DROP TABLE AuthCode"); + } +} diff --git a/app/config/config.yml b/app/config/config.yml index b08185c..9487276 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -110,3 +110,23 @@ eko_feed: description: 'Latest posts' link: 'cobase.featurice.com' encoding: 'utf-8' + +fos_oauth_server: + db_driver: orm # Driver availables: orm, mongodb, or propel + client_class: Cobase\ApiBundle\Entity\Client + access_token_class: Cobase\ApiBundle\Entity\AccessToken + refresh_token_class: Cobase\ApiBundle\Entity\RefreshToken + auth_code_class: Cobase\ApiBundle\Entity\AuthCode + service: + user_provider: fos_user.user_manager + +sensio_framework_extra: + view: + annotations: false + +fos_rest: + param_fetcher_listener: true + body_listener: true + format_listener: true + view: + view_response_listener: 'force' \ No newline at end of file diff --git a/app/config/routing.yml b/app/config/routing.yml index cd7be2d..e73685c 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -1,7 +1,12 @@ -# Internal routing configuration to handle ESI -#_internal: -# resource: "@FrameworkBundle/Resources/config/routing/internal.xml" -# prefix: /_internal +fos_oauth_server_token: + resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" + +fos_oauth_server_authorize: + resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" + +CobaseApiBundle: + resource: "@CobaseApiBundle/Resources/config/routing.yml" + prefix: /api/v1 CobaseAppBundle: resource: "@CobaseAppBundle/Resources/config/routing.yml" @@ -12,3 +17,8 @@ _user_bundle: fos_js_routing: resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml" + +# Internal routing configuration to handle ESI +#_internal: +# resource: "@FrameworkBundle/Resources/config/routing/internal.xml" +# prefix: /_internal \ No newline at end of file diff --git a/app/config/security.yml b/app/config/security.yml index d3aa9a6..976bdd2 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -11,6 +11,25 @@ security: FOS\UserBundle\Model\UserInterface: sha512 firewalls: + oauth_authorize: + pattern: ^/api/oauth/v2/auth + form_login: + provider: fos_userbundle + csrf_provider: form.csrf_provider + check_path: /api/oauth/v2/auth_login_check + login_path: /api/oauth/v2/auth_login + logout: true + anonymous: true + + oauth_token: + pattern: ^/api/oauth/v2/token + security: false + + api: + pattern: ^/api + fos_oauth: true + stateless: true + main: pattern: ^/ form_login: @@ -26,22 +45,26 @@ security: - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting$, role: IS_AUTHENTICATED_ANONYMOUSLY } - + - { path: ^/profile, role: ROLE_USER } - + - { path: ^/post/new, role: ROLE_USER } - { path: ^/post/create, role: ROLE_USER } - { path: ^/post/move, role: ROLE_USER } - { path: ^/post/modify, role: ROLE_USER } - { path: ^/post/delete, role: ROLE_USER } - + - { path: ^/group/new, role: ROLE_USER } - { path: ^/group/create, role: ROLE_USER } - { path: ^/group/modify, role: ROLE_USER } - { path: ^/group/delete, role: ROLE_USER } - { path: ^/group/subscribe, role: ROLE_USER } - { path: ^/group/unsubscribe, role: ROLE_USER } - + + # for the api + - { path: ^/api/oauth/v2/auth_login$, role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: ^/api, role: IS_AUTHENTICATED_FULLY } + role_hierarchy: ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: ROLE_ADMIN \ No newline at end of file + ROLE_SUPER_ADMIN: ROLE_ADMIN diff --git a/composer.json b/composer.json index 330c942..3ac4391 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,10 @@ "antimattr/google-bundle": "dev-master", "artur-gajewski/date-converter-bundle": "1.0.*@dev", "gedmo/doctrine-extensions": "dev-wip-v2.4.0", - "eko/feedbundle": "dev-master" + "eko/feedbundle": "dev-master", + "friendsofsymfony/oauth-server-bundle": "dev-master", + "friendsofsymfony/rest-bundle": "dev-master", + "jms/serializer-bundle": "dev-master" }, "scripts": { "post-install-cmd": [ diff --git a/composer.lock b/composer.lock index 773c16a..f800e1e 100644 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "134d9f0d5f9467842efda12cb04f4fb7", + "hash": "a2e8b839edb02194f35b52ce022b7232", "packages": [ { "name": "antimattr/google-bundle", @@ -104,12 +104,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "40db0c96985aab2822edbc4848b3bd2429e02670" + "reference": "v1.1.2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/40db0c96985aab2822edbc4848b3bd2429e02670", - "reference": "40db0c96985aab2822edbc4848b3bd2429e02670", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/v1.1.2", + "reference": "v1.1.2", "shasum": "" }, "require": { @@ -156,7 +156,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -740,7 +740,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", + "homepage": "http://jmsyst.com", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -871,12 +871,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/doctrine2.git", - "reference": "f634ba343cb0b8524490ba0700f0d19fe85459da" + "reference": "fc7719d5fae069dad3915cc5330dcfb421439170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/f634ba343cb0b8524490ba0700f0d19fe85459da", - "reference": "f634ba343cb0b8524490ba0700f0d19fe85459da", + "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/fc7719d5fae069dad3915cc5330dcfb421439170", + "reference": "fc7719d5fae069dad3915cc5330dcfb421439170", "shasum": "" }, "require": { @@ -938,7 +938,7 @@ "database", "orm" ], - "time": "2013-08-25 14:23:20" + "time": "2013-08-29 03:15:55" }, { "name": "eko/feedbundle", @@ -1042,12 +1042,12 @@ "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSJsRoutingBundle.git", - "reference": "b93f01e8f81918bd86fc673afaaf26e5fc51b3ae" + "reference": "1.2.0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSJsRoutingBundle/zipball/b93f01e8f81918bd86fc673afaaf26e5fc51b3ae", - "reference": "b93f01e8f81918bd86fc673afaaf26e5fc51b3ae", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSJsRoutingBundle/zipball/1.2.0", + "reference": "1.2.0", "shasum": "" }, "require": { @@ -1089,6 +1089,247 @@ ], "time": "2013-07-15 09:21:37" }, + { + "name": "friendsofsymfony/oauth-server-bundle", + "version": "dev-master", + "target-dir": "FOS/OAuthServerBundle", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/FOSOAuthServerBundle.git", + "reference": "e48ceba7a7678dc62854aab84c8b98c0f33b46aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSOAuthServerBundle/zipball/e48ceba7a7678dc62854aab84c8b98c0f33b46aa", + "reference": "e48ceba7a7678dc62854aab84c8b98c0f33b46aa", + "shasum": "" + }, + "require": { + "friendsofsymfony/oauth2-php": "~1.0.4", + "php": ">=5.3.3", + "symfony/framework-bundle": "~2.1", + "symfony/security-bundle": "~2.1" + }, + "require-dev": { + "doctrine/doctrine-bundle": "~1.0", + "doctrine/mongodb-odm": "1.0.*@dev", + "doctrine/orm": ">=2.2,<2.5-dev", + "symfony/class-loader": "~2.1", + "symfony/yaml": "~2.1", + "willdurand/propel-typehintable-behavior": "1.0.*" + }, + "suggest": { + "doctrine/doctrine-bundle": "*", + "doctrine/mongodb-odm-bundle": "*", + "propel/propel-bundle": "If you want to use Propel with Symfony2, then you will have to install the PropelBundle", + "willdurand/propel-typehintable-behavior": "The Typehintable behavior is useful to add type hints on generated methods, to be compliant with interfaces" + }, + "type": "symfony-bundle", + "autoload": { + "psr-0": { + "FOS\\OAuthServerBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnaud Le Blanc", + "email": "arnaud.lb@gmail.com" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/contributors" + } + ], + "description": "Symfony2 OAuth Server Bundle", + "homepage": "http://friendsofsymfony.github.com", + "keywords": [ + "oauth", + "oauth2", + "server" + ], + "time": "2013-08-28 21:44:28" + }, + { + "name": "friendsofsymfony/oauth2-php", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/oauth2-php.git", + "reference": "e1037bfc98df15a5c46ff745a91de13c7f48f66a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/oauth2-php/zipball/e1037bfc98df15a5c46ff745a91de13c7f48f66a", + "reference": "e1037bfc98df15a5c46ff745a91de13c7f48f66a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/http-foundation": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "OAuth2": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Arnaud Le Blanc", + "email": "arnaud.lb@gmail.com" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/FriendsOfSymfony/oauth2-php/contributors" + } + ], + "description": "OAuth2 library", + "homepage": "https://github.com/FriendsOfSymfony/oauth2-php", + "keywords": [ + "oauth", + "oauth2" + ], + "time": "2013-07-24 06:48:28" + }, + { + "name": "friendsofsymfony/rest", + "version": "0.8.0", + "target-dir": "FOS/Rest", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/FOSRest.git", + "reference": "0.8.0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRest/zipball/0.8.0", + "reference": "0.8.0", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/http-foundation": ">=2.0,<3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "FOS\\Rest": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lukas Kahwe Smith", + "email": "smith@pooteeweet.org" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/FriendsOfSymfony/FOSRest/contributors" + } + ], + "description": "This library provides various tools to develop RESTful API's", + "homepage": "http://friendsofsymfony.github.com", + "keywords": [ + "rest" + ], + "time": "2013-03-02 20:35:05" + }, + { + "name": "friendsofsymfony/rest-bundle", + "version": "dev-master", + "target-dir": "FOS/RestBundle", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", + "reference": "bd985308564efec63bf22ad9d5effcc866f02231" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/bd985308564efec63bf22ad9d5effcc866f02231", + "reference": "bd985308564efec63bf22ad9d5effcc866f02231", + "shasum": "" + }, + "require": { + "doctrine/inflector": "1.0.*", + "friendsofsymfony/rest": ">=0.7.0,<0.9.0-dev", + "php": ">=5.3.2", + "symfony/framework-bundle": "~2.1", + "willdurand/negotiation": "1.0.*" + }, + "conflict": { + "jms/serializer": "<0.12", + "jms/serializer-bundle": "<0.11" + }, + "require-dev": { + "jms/serializer-bundle": "0.12.*", + "sensio/framework-extra-bundle": "~2.1", + "symfony/form": "~2.1", + "symfony/security": "~2.1", + "symfony/yaml": "~2.1" + }, + "suggest": { + "jms/serializer-bundle": "Add support for advanced serialization capabilities, recommended, requires 0.12.*", + "sensio/framework-extra-bundle": "Add support for route annotations and the view response listener", + "symfony/serializer": "Add support for basic serialization capabilities, requires >=2.0,<2.3-dev" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "FOS\\RestBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lukas Kahwe Smith", + "email": "smith@pooteeweet.org" + }, + { + "name": "FriendsOfSymfony Community", + "homepage": "https://github.com/friendsofsymfony/FOSRestBundle/contributors" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "This Bundle provides various tools to rapidly develop RESTful API's with Symfony2", + "homepage": "http://friendsofsymfony.github.com", + "keywords": [ + "rest" + ], + "time": "2013-08-26 21:35:25" + }, { "name": "friendsofsymfony/user-bundle", "version": "dev-master", @@ -1096,12 +1337,12 @@ "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSUserBundle.git", - "reference": "3b8643c573b93ab2a5d2c0cab893cb0fedcac757" + "reference": "e536e8b87db29854cacc214dff5d41fbcf188674" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/3b8643c573b93ab2a5d2c0cab893cb0fedcac757", - "reference": "3b8643c573b93ab2a5d2c0cab893cb0fedcac757", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSUserBundle/zipball/e536e8b87db29854cacc214dff5d41fbcf188674", + "reference": "e536e8b87db29854cacc214dff5d41fbcf188674", "shasum": "" }, "require": { @@ -1156,7 +1397,7 @@ "keywords": [ "User management" ], - "time": "2013-08-27 13:19:17" + "time": "2013-08-28 08:24:11" }, { "name": "gedmo/doctrine-extensions", @@ -1608,6 +1849,143 @@ ], "time": "2013-08-06 07:00:17" }, + { + "name": "jms/serializer", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/serializer.git", + "reference": "89a43cbe84e079bcd81d82889b03ded9abda2f47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/89a43cbe84e079bcd81d82889b03ded9abda2f47", + "reference": "89a43cbe84e079bcd81d82889b03ded9abda2f47", + "shasum": "" + }, + "require": { + "doctrine/annotations": "1.*", + "jms/metadata": "~1.1", + "jms/parser-lib": "1.*", + "php": ">=5.3.2", + "phpcollection/phpcollection": ">=0.1,<0.3-dev" + }, + "require-dev": { + "doctrine/orm": ">=2.1,<2.4-dev", + "symfony/filesystem": "2.*", + "symfony/form": ">=2.1,<2.2-dev", + "symfony/translation": ">=2.0,<2.2-dev", + "symfony/validator": ">=2.0,<2.2-dev", + "symfony/yaml": "2.*", + "twig/twig": ">=1.8,<2.0-dev" + }, + "suggest": { + "symfony/yaml": "Required if you'd like to serialize data to YAML format." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.14-dev" + } + }, + "autoload": { + "psr-0": { + "JMS\\Serializer": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "http://jmsyst.com", + "role": "Developer of wrapped JMSSerializerBundle" + } + ], + "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", + "homepage": "http://jmsyst.com/libs/serializer", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "time": "2013-08-17 18:17:07" + }, + { + "name": "jms/serializer-bundle", + "version": "dev-master", + "target-dir": "JMS/SerializerBundle", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/JMSSerializerBundle.git", + "reference": "f2fd06c6906cc0f98037f2e6250def2e9e593144" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/JMSSerializerBundle/zipball/f2fd06c6906cc0f98037f2e6250def2e9e593144", + "reference": "f2fd06c6906cc0f98037f2e6250def2e9e593144", + "shasum": "" + }, + "require": { + "jms/serializer": "~0.11", + "php": ">=5.3.2", + "symfony/framework-bundle": "~2.1" + }, + "require-dev": { + "doctrine/doctrine-bundle": "*", + "doctrine/orm": "*", + "symfony/browser-kit": "*", + "symfony/class-loader": "*", + "symfony/css-selector": "*", + "symfony/finder": "*", + "symfony/form": "*", + "symfony/process": "*", + "symfony/twig-bundle": "*", + "symfony/validator": "*", + "symfony/yaml": "*" + }, + "suggest": { + "jms/di-extra-bundle": "Required to get lazy loading (de)serialization visitors, ~1.3" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "0.13-dev" + } + }, + "autoload": { + "psr-0": { + "JMS\\SerializerBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "http://jmsyst.com", + "role": "Developer of wrapped JMSSerializerBundle" + } + ], + "description": "Allows you to easily serialize, and deserialize data of any complexity", + "homepage": "http://jmsyst.com/bundles/JMSSerializerBundle", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "time": "2013-08-21 06:47:26" + }, { "name": "kriswallsmith/assetic", "version": "1.1.x-dev", @@ -1846,6 +2224,56 @@ ], "time": "2013-03-26 06:23:17" }, + { + "name": "phpcollection/phpcollection", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-collection.git", + "reference": "5c8ec0d1091c95b973b59a3bf0eb19c5de72d8d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/5c8ec0d1091c95b973b59a3bf0eb19c5de72d8d1", + "reference": "5c8ec0d1091c95b973b59a3bf0eb19c5de72d8d1", + "shasum": "" + }, + "require": { + "phpoption/phpoption": "1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + }, + "autoload": { + "psr-0": { + "PhpCollection": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "http://jmsyst.com", + "role": "Developer of wrapped JMSSerializerBundle" + } + ], + "description": "General-Purpose Collection Library for PHP", + "keywords": [ + "collection", + "list", + "map", + "sequence", + "set" + ], + "time": "2013-08-22 09:46:14" + }, { "name": "phpoption/phpoption", "version": "dev-master", @@ -1880,7 +2308,7 @@ ], "authors": [ { - "name": "Johannes M. Schmitt", + "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", "homepage": "http://jmsyst.com", "role": "Developer of wrapped JMSSerializerBundle" @@ -1900,13 +2328,13 @@ "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "url": "https://github.com/php-fig/log", + "reference": "1.0.0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://github.com/php-fig/log/archive/1.0.0.zip", + "reference": "1.0.0", "shasum": "" }, "type": "library", @@ -2080,12 +2508,12 @@ "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "619aceb969f1e8759edc28fb22f9b64b3bddbc1e" + "reference": "v5.0.1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/619aceb969f1e8759edc28fb22f9b64b3bddbc1e", - "reference": "619aceb969f1e8759edc28fb22f9b64b3bddbc1e", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/v5.0.1", + "reference": "v5.0.1", "shasum": "" }, "require": { @@ -2144,13 +2572,13 @@ "symfony/framework-bundle": "~2.1" }, "require-dev": { - "symfony/class-loader": "~2.1", - "symfony/console": "~2.1", - "symfony/css-selector": "~2.1", - "symfony/dom-crawler": "~2.1", - "symfony/form": "~2.1", - "symfony/twig-bundle": "~2.1", - "symfony/yaml": "~2.1" + "symfony/class-loader": ">=2.1,<3.0", + "symfony/console": ">=2.1,<3.0", + "symfony/css-selector": ">=2.1,<3.0", + "symfony/dom-crawler": ">=2.1,<3.0", + "symfony/form": ">=2.1,<3.0", + "symfony/twig-bundle": ">=2.1,<3.0", + "symfony/yaml": ">=2.1,<3.0" }, "suggest": { "symfony/twig-bundle": "~2.1" @@ -2188,20 +2616,21 @@ }, { "name": "symfony/icu", - "version": "1.0.x-dev", + "version": "1.2.x-dev", "target-dir": "Symfony/Component/Icu", "source": { "type": "git", "url": "https://github.com/symfony/Icu.git", - "reference": "0b790dfb98904df2bcd44b2e14a69b1ccd679ef7" + "reference": "45c8d35427304b1e14a13a03426055f501ba5f61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Icu/zipball/0b790dfb98904df2bcd44b2e14a69b1ccd679ef7", - "reference": "0b790dfb98904df2bcd44b2e14a69b1ccd679ef7", + "url": "https://api.github.com/repos/symfony/Icu/zipball/45c8d35427304b1e14a13a03426055f501ba5f61", + "reference": "45c8d35427304b1e14a13a03426055f501ba5f61", "shasum": "" }, "require": { + "lib-icu": ">=4.4", "php": ">=5.3.3", "symfony/intl": "~2.3" }, @@ -2231,7 +2660,7 @@ "icu", "intl" ], - "time": "2013-08-06 12:58:06" + "time": "2013-08-06 12:55:36" }, { "name": "symfony/monolog-bundle", @@ -2352,12 +2781,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/symfony.git", - "reference": "196227bd83f2b1593756903be9de5f94e8b07681" + "reference": "c0a256d9664d459a1708b0bdb10825ec2253da0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/symfony/zipball/196227bd83f2b1593756903be9de5f94e8b07681", - "reference": "196227bd83f2b1593756903be9de5f94e8b07681", + "url": "https://api.github.com/repos/symfony/symfony/zipball/c0a256d9664d459a1708b0bdb10825ec2253da0b", + "reference": "c0a256d9664d459a1708b0bdb10825ec2253da0b", "shasum": "" }, "require": { @@ -2452,7 +2881,7 @@ "keywords": [ "framework" ], - "time": "2013-08-27 13:39:19" + "time": "2013-08-29 06:53:29" }, { "name": "twig/extensions", @@ -2550,6 +2979,56 @@ ], "time": "2013-08-28 06:01:53" }, + { + "name": "willdurand/negotiation", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/willdurand/Negotiation.git", + "reference": "a25b58fd5d6cabcd515bc83661788582b0bcf3f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/Negotiation/zipball/a25b58fd5d6cabcd515bc83661788582b0bcf3f8", + "reference": "a25b58fd5d6cabcd515bc83661788582b0bcf3f8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Negotiation": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "william.durand1@gmail.com", + "homepage": "http://www.willdurand.fr" + } + ], + "description": "Content Negotiation tools for PHP provided as a standalone library.", + "homepage": "http://williamdurand.fr/Negotiation/", + "keywords": [ + "accept", + "content", + "format", + "header", + "negotiation" + ], + "time": "2013-08-06 14:47:08" + }, { "name": "xi/fixtures", "version": "dev-master", @@ -2981,7 +3460,10 @@ "antimattr/google-bundle": 20, "artur-gajewski/date-converter-bundle": 20, "gedmo/doctrine-extensions": 20, - "eko/feedbundle": 20 + "eko/feedbundle": 20, + "friendsofsymfony/oauth-server-bundle": 20, + "friendsofsymfony/rest-bundle": 20, + "jms/serializer-bundle": 20 }, "platform": { "php": ">=5.3.3" diff --git a/src/Cobase/ApiBundle/CobaseApiBundle.php b/src/Cobase/ApiBundle/CobaseApiBundle.php new file mode 100644 index 0000000..606da48 --- /dev/null +++ b/src/Cobase/ApiBundle/CobaseApiBundle.php @@ -0,0 +1,13 @@ +setName('cobase:oauth-server:client:create') + ->setDescription('Creates a new client') + ->addArgument('name', InputArgument::REQUIRED, 'Sets the client name', null) + ->addOption('redirect-uri', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets redirect uri for client. Use this option multiple times to set multiple redirect URIs.', null) + ->addOption('grant-type', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Sets allowed grant type for client. Use this option multiple times to set multiple grant types..', null) + ->setHelp(<<%command.name%command creates a new client. + + php %command.full_name% [--redirect-uri=...] [--grant-type=...] name + +EOT + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $clientManager = $this->getContainer()->get('fos_oauth_server.client_manager.default'); + $client = $clientManager->createClient(); + $client->setName($input->getArgument('name')); + $client->setRedirectUris($input->getOption('redirect-uri')); + $client->setAllowedGrantTypes($input->getOption('grant-type')); + $clientManager->updateClient($client); + $output->writeln(sprintf('Added a new client with name %s and public id %s.', $client->getName(), $client->getPublicId())); + } +} diff --git a/src/Cobase/ApiBundle/Controller/ApiController.php b/src/Cobase/ApiBundle/Controller/ApiController.php new file mode 100644 index 0000000..8100998 --- /dev/null +++ b/src/Cobase/ApiBundle/Controller/ApiController.php @@ -0,0 +1,13 @@ +render('CobaseApiBundle:Api:index.html.twig', array()); + } +} diff --git a/src/Cobase/ApiBundle/Controller/PostController.php b/src/Cobase/ApiBundle/Controller/PostController.php new file mode 100644 index 0000000..6743049 --- /dev/null +++ b/src/Cobase/ApiBundle/Controller/PostController.php @@ -0,0 +1,40 @@ +getDoctrine()->getRepository('CobaseAppBundle:Post')->findAll(); + $view = $this->view($data, 200) + ->setTemplate("CobaseApiBundle:Post:getPosts.json.twig") + ->setTemplateVar('posts') + ; + + return $this->handleView($view); + } + + public function getPostAction($id) + { + $post = $this->getDoctrine()->getRepository('CobaseAppBundle:Post')->findOneById($id); + + if (!$post instanceof Post) { + throw new NotFoundHttpException('Post not found'); + } + + return array('post' => $post); + } +} \ No newline at end of file diff --git a/src/Cobase/ApiBundle/Controller/SecurityController.php b/src/Cobase/ApiBundle/Controller/SecurityController.php new file mode 100644 index 0000000..7177cb8 --- /dev/null +++ b/src/Cobase/ApiBundle/Controller/SecurityController.php @@ -0,0 +1,63 @@ +getSession(); + + // get the error if any (works with forward and redirect -- see below) + if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { + $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); + } elseif (null !== $session && $session->has(SecurityContext::AUTHENTICATION_ERROR)) { + $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); + $session->remove(SecurityContext::AUTHENTICATION_ERROR); + } else { + $error = ''; + } + + if ($error) { + // TODO: this is a potential security risk (see http://trac.symfony-project.org/ticket/9523) + $error = $error->getMessage(); + } + // last username entered by the user + $lastUsername = (null === $session) ? '' : $session->get(SecurityContext::LAST_USERNAME); + + $csrfToken = $this->container->has('form.csrf_provider') + ? $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate') + : null; + + return $this->renderLogin(array( + 'last_username' => $lastUsername, + 'error' => $error, + 'csrf_token' => $csrfToken, + )); + } + + /** + * Renders the login template with the given parameters. Overwrite this function in + * an extended controller to provide additional data for the login template. + * + * @param array $data + * + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function renderLogin(array $data) + { + $template = sprintf('CobaseOauthBundle:Security:login.html.%s', $this->container->getParameter('fos_user.template.engine')); + + return $this->container->get('templating')->renderResponse($template, $data); + } + + public function loginCheckAction(Request $request) + { + throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.'); + } +} diff --git a/src/Cobase/ApiBundle/DependencyInjection/CobaseApiExtension.php b/src/Cobase/ApiBundle/DependencyInjection/CobaseApiExtension.php new file mode 100644 index 0000000..e02056d --- /dev/null +++ b/src/Cobase/ApiBundle/DependencyInjection/CobaseApiExtension.php @@ -0,0 +1,28 @@ +processConfiguration($configuration, $configs); + + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + } +} diff --git a/src/Cobase/ApiBundle/DependencyInjection/Configuration.php b/src/Cobase/ApiBundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000..367f6f4 --- /dev/null +++ b/src/Cobase/ApiBundle/DependencyInjection/Configuration.php @@ -0,0 +1,29 @@ +root('cobase_api'); + + // Here you should define the parameters that are allowed to + // configure your bundle. See the documentation linked above for + // more information on that topic. + + return $treeBuilder; + } +} diff --git a/src/Cobase/ApiBundle/Entity/AccessToken.php b/src/Cobase/ApiBundle/Entity/AccessToken.php new file mode 100644 index 0000000..bbfe9a5 --- /dev/null +++ b/src/Cobase/ApiBundle/Entity/AccessToken.php @@ -0,0 +1,30 @@ +name; + } + + public function setName($name) + { + $this->name = $name; + } +} \ No newline at end of file diff --git a/src/Cobase/ApiBundle/Entity/RefreshToken.php b/src/Cobase/ApiBundle/Entity/RefreshToken.php new file mode 100644 index 0000000..18d438f --- /dev/null +++ b/src/Cobase/ApiBundle/Entity/RefreshToken.php @@ -0,0 +1,30 @@ + +
+ +

{{ site_title }}

+ +
+
+

The application "{{ client.name }}" would like to connect to your account

+
+
+
+ {{ form_row(form.client_id) }} + {{ form_row(form.response_type) }} + {{ form_row(form.redirect_uri) }} + {{ form_row(form.state) }} + {{ form_row(form.scope) }} + {{ form_rest(form) }} + + +
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/src/Cobase/ApiBundle/Resources/views/Post/getPosts.json.twig b/src/Cobase/ApiBundle/Resources/views/Post/getPosts.json.twig new file mode 100644 index 0000000..d9b241c --- /dev/null +++ b/src/Cobase/ApiBundle/Resources/views/Post/getPosts.json.twig @@ -0,0 +1,3 @@ +{% for post in posts %} + {{ post.content|json_encode }} +{% endfor %} \ No newline at end of file diff --git a/src/Cobase/ApiBundle/Resources/views/Security/login.html.twig b/src/Cobase/ApiBundle/Resources/views/Security/login.html.twig new file mode 100644 index 0000000..dc489c6 --- /dev/null +++ b/src/Cobase/ApiBundle/Resources/views/Security/login.html.twig @@ -0,0 +1,40 @@ +{% extends '::blank.html.twig' %} + +{% block content %} +
+
+ +

{{ site_title }}

+ +
+
+

Login

+
+
+ {% if error %} +
{{ error|trans }}
+ {% endif %} +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+
+{% endblock content %} + + + diff --git a/src/Cobase/ApiBundle/Tests/Controller/DefaultControllerTest.php b/src/Cobase/ApiBundle/Tests/Controller/DefaultControllerTest.php new file mode 100644 index 0000000..0660f64 --- /dev/null +++ b/src/Cobase/ApiBundle/Tests/Controller/DefaultControllerTest.php @@ -0,0 +1,17 @@ +request('GET', '/hello/Fabien'); + + $this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0); + } +} diff --git a/src/Cobase/AppBundle/Entity/Post.php b/src/Cobase/AppBundle/Entity/Post.php index 51a1776..df7bb74 100644 --- a/src/Cobase/AppBundle/Entity/Post.php +++ b/src/Cobase/AppBundle/Entity/Post.php @@ -14,11 +14,16 @@ use Symfony\Component\Validator\Constraints as Assert; use Gedmo\Mapping\Annotation as Gedmo; +use JMS\Serializer\Annotation\ExclusionPolicy; +use JMS\Serializer\Annotation\Expose; + /** * @ORM\Entity(repositoryClass="Cobase\AppBundle\Repository\PostRepository") * @ORM\Table(name="posts") * @ORM\HasLifecycleCallbacks() * @Gedmo\SoftDeleteable(fieldName="deleted") + * + * @ExclusionPolicy("all") */ class Post implements Likeable, RoutedItemInterface { @@ -33,11 +38,15 @@ class Post implements Likeable, RoutedItemInterface * @var User * @ORM\ManyToOne(targetEntity="Cobase\UserBundle\Entity\User", inversedBy="posts") * @ORM\JoinColumn(name="user_id", referencedColumnName="id") + * + * @Expose */ protected $user; /** * @ORM\Column(type="string", length=1250) + * + * @Expose */ protected $content; @@ -45,28 +54,38 @@ class Post implements Likeable, RoutedItemInterface * @var Group * @ORM\ManyToOne(targetEntity="Group", inversedBy="posts") * @ORM\JoinColumn(name="group_id", referencedColumnName="id") + * + * @Expose */ protected $group; /** * @var \DateTime * @ORM\Column(type="datetime") + * + * @Expose */ protected $created; /** * @var \DateTime * @ORM\Column(type="datetime") + * + * @Expose */ protected $updated; /** * @ORM\Column(type="datetime", nullable=true) + * + * @Expose */ protected $deleted; /** * @var ArrayCollection + * + * @Expose */ protected $likes;