diff --git a/.gitignore b/.gitignore
index 19ccdc0..f586439 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/vendor
/bin
/tests-coverage
+.idea/
diff --git a/composer.json b/composer.json
index 562ae86..8fd7a0f 100644
--- a/composer.json
+++ b/composer.json
@@ -40,6 +40,7 @@
},
"require": {
"php": ">=5.6",
- "majora/framework-extra-bundle": "~1.1"
+ "majora/framework-extra-bundle": "~1.1",
+ "doctrine/orm": "^2.5"
}
}
diff --git a/composer.lock b/composer.lock
index 56f1411..90c5351 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "77df1d2735511f683bc3a75e7c4fd630",
- "content-hash": "f6b51a231d8fcdf71b3816016f22eb31",
+ "hash": "8d4034821426301e1da7b47a44a5b2b0",
+ "content-hash": "896abc5eeb511dd40ee5d3d0fd6cf5dc",
"packages": [
{
"name": "doctrine/annotations",
@@ -284,6 +284,77 @@
],
"time": "2015-12-25 13:18:31"
},
+ {
+ "name": "doctrine/dbal",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/dbal.git",
+ "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
+ "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/common": ">=2.4,<2.7-dev",
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*",
+ "symfony/console": "2.*"
+ },
+ "suggest": {
+ "symfony/console": "For helpful console commands such as SQL execution and import of files."
+ },
+ "bin": [
+ "bin/doctrine-dbal"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\DBAL\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ }
+ ],
+ "description": "Database Abstraction Layer",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "database",
+ "dbal",
+ "persistence",
+ "queryobject"
+ ],
+ "time": "2016-01-05 22:11:12"
+ },
{
"name": "doctrine/inflector",
"version": "v1.1.0",
@@ -351,6 +422,60 @@
],
"time": "2015-11-06 14:35:42"
},
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3,<8.0-DEV"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2015-06-14 21:17:01"
+ },
{
"name": "doctrine/lexer",
"version": "v1.0.1",
@@ -405,18 +530,94 @@
],
"time": "2014-09-09 13:34:57"
},
+ {
+ "name": "doctrine/orm",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/doctrine2.git",
+ "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/bc4ddbfb0114cb33438cc811c9a740d8aa304aab",
+ "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/cache": "~1.4",
+ "doctrine/collections": "~1.2",
+ "doctrine/common": ">=2.5-dev,<2.7-dev",
+ "doctrine/dbal": ">=2.5-dev,<2.6-dev",
+ "doctrine/instantiator": "~1.0.1",
+ "ext-pdo": "*",
+ "php": ">=5.4",
+ "symfony/console": "~2.5|~3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0",
+ "symfony/yaml": "~2.3|~3.0"
+ },
+ "suggest": {
+ "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
+ },
+ "bin": [
+ "bin/doctrine",
+ "bin/doctrine.php"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\ORM\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ }
+ ],
+ "description": "Object-Relational-Mapper for PHP",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "database",
+ "orm"
+ ],
+ "time": "2016-01-05 21:34:58"
+ },
{
"name": "majora/framework-extra-bundle",
- "version": "1.1.0",
+ "version": "v1.1.2",
"source": {
"type": "git",
"url": "https://github.com/LinkValue/MajoraFrameworkExtraBundle.git",
- "reference": "e743802939119d4882cf167de54e49db9fd41d91"
+ "reference": "4c11d71512c058f49a87c68a038be49215607691"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/LinkValue/MajoraFrameworkExtraBundle/zipball/3867ef82c8a055ab366c441cd66a90a2bd658136",
- "reference": "e743802939119d4882cf167de54e49db9fd41d91",
+ "url": "https://api.github.com/repos/LinkValue/MajoraFrameworkExtraBundle/zipball/4c11d71512c058f49a87c68a038be49215607691",
+ "reference": "4c11d71512c058f49a87c68a038be49215607691",
"shasum": ""
},
"require": {
@@ -467,20 +668,20 @@
"framework",
"symfony"
],
- "time": "2016-03-11 00:25:29"
+ "time": "2016-03-15 10:00:24"
},
{
"name": "paragonie/random_compat",
- "version": "v1.2.1",
+ "version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
- "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc"
+ "reference": "c7e26a21ba357863de030f0b9e701c7d04593774"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/f078eba3bcf140fd69b5fcc3ea5ac809abf729dc",
- "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774",
+ "reference": "c7e26a21ba357863de030f0b9e701c7d04593774",
"shasum": ""
},
"require": {
@@ -515,7 +716,7 @@
"pseudorandom",
"random"
],
- "time": "2016-02-29 17:25:04"
+ "time": "2016-03-18 20:34:03"
},
{
"name": "psr/log",
@@ -841,16 +1042,16 @@
},
{
"name": "symfony/symfony",
- "version": "v3.0.3",
+ "version": "v3.0.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/symfony.git",
- "reference": "09ae53562ce8b7842206efa217ec81442975f055"
+ "reference": "4e17cb2ecb3fd637097ebeb871fc0e2cbdd5e7ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/symfony/zipball/09ae53562ce8b7842206efa217ec81442975f055",
- "reference": "09ae53562ce8b7842206efa217ec81442975f055",
+ "url": "https://api.github.com/repos/symfony/symfony/zipball/4e17cb2ecb3fd637097ebeb871fc0e2cbdd5e7ff",
+ "reference": "4e17cb2ecb3fd637097ebeb871fc0e2cbdd5e7ff",
"shasum": ""
},
"require": {
@@ -933,10 +1134,7 @@
},
"autoload": {
"psr-4": {
- "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
- "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/",
- "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/",
- "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/",
+ "Symfony\\Bridge\\": "src/Symfony/Bridge/",
"Symfony\\Bundle\\": "src/Symfony/Bundle/",
"Symfony\\Component\\": "src/Symfony/Component/"
},
@@ -966,7 +1164,7 @@
"keywords": [
"framework"
],
- "time": "2016-02-28 21:33:29"
+ "time": "2016-03-30 10:41:14"
},
{
"name": "twig/twig",
@@ -1031,60 +1229,6 @@
}
],
"packages-dev": [
- {
- "name": "doctrine/instantiator",
- "version": "1.0.5",
- "source": {
- "type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3,<8.0-DEV"
- },
- "require-dev": {
- "athletic/athletic": "~0.1.8",
- "ext-pdo": "*",
- "ext-phar": "*",
- "phpunit/phpunit": "~4.0",
- "squizlabs/php_codesniffer": "~2.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "homepage": "http://ocramius.github.com/"
- }
- ],
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://github.com/doctrine/instantiator",
- "keywords": [
- "constructor",
- "instantiate"
- ],
- "time": "2015-06-14 21:17:01"
- },
{
"name": "fabpot/php-cs-fixer",
"version": "v1.11.2",
@@ -1294,16 +1438,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "3.3.0",
+ "version": "3.3.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "fe33716763b604ade4cb442c0794f5bd5ad73004"
+ "reference": "2431befdd451fac43fbcde94d1a92fb3b8b68f86"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe33716763b604ade4cb442c0794f5bd5ad73004",
- "reference": "fe33716763b604ade4cb442c0794f5bd5ad73004",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2431befdd451fac43fbcde94d1a92fb3b8b68f86",
+ "reference": "2431befdd451fac43fbcde94d1a92fb3b8b68f86",
"shasum": ""
},
"require": {
@@ -1321,7 +1465,7 @@
},
"suggest": {
"ext-dom": "*",
- "ext-xdebug": ">=2.2.1",
+ "ext-xdebug": ">=2.4.0",
"ext-xmlwriter": "*"
},
"type": "library",
@@ -1353,7 +1497,7 @@
"testing",
"xunit"
],
- "time": "2016-03-03 08:49:08"
+ "time": "2016-04-08 08:14:53"
},
{
"name": "phpunit/php-file-iterator",
@@ -1535,16 +1679,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "5.2.10",
+ "version": "5.3.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "37fa29b17b87a3e9f0a4d77c42f0aac5183b84d1"
+ "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/37fa29b17b87a3e9f0a4d77c42f0aac5183b84d1",
- "reference": "37fa29b17b87a3e9f0a4d77c42f0aac5183b84d1",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2c6da3536035617bae3fe3db37283c9e0eb63ab3",
+ "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3",
"shasum": ""
},
"require": {
@@ -1559,13 +1703,14 @@
"phpunit/php-code-coverage": "^3.3.0",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
- "phpunit/php-timer": ">=1.0.6",
- "phpunit/phpunit-mock-objects": ">=3.0.5",
+ "phpunit/php-timer": "^1.0.6",
+ "phpunit/phpunit-mock-objects": "^3.1",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
+ "sebastian/object-enumerator": "~1.0",
"sebastian/resource-operations": "~1.0",
"sebastian/version": "~1.0|~2.0",
"symfony/yaml": "~2.1|~3.0"
@@ -1579,7 +1724,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.2.x-dev"
+ "dev-master": "5.3.x-dev"
}
},
"autoload": {
@@ -1605,20 +1750,20 @@
"testing",
"xunit"
],
- "time": "2016-03-03 08:52:58"
+ "time": "2016-04-12 16:20:08"
},
{
"name": "phpunit/phpunit-mock-objects",
- "version": "3.0.6",
+ "version": "3.1.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "49bc700750196c04dd6bc2c4c99cb632b893836b"
+ "reference": "151c96874bff6fe61a25039df60e776613a61489"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/49bc700750196c04dd6bc2c4c99cb632b893836b",
- "reference": "49bc700750196c04dd6bc2c4c99cb632b893836b",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/151c96874bff6fe61a25039df60e776613a61489",
+ "reference": "151c96874bff6fe61a25039df60e776613a61489",
"shasum": ""
},
"require": {
@@ -1636,7 +1781,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0.x-dev"
+ "dev-master": "3.1.x-dev"
}
},
"autoload": {
@@ -1661,7 +1806,7 @@
"mock",
"xunit"
],
- "time": "2015-12-08 08:47:06"
+ "time": "2016-04-20 14:39:26"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -1991,6 +2136,52 @@
],
"time": "2015-10-12 03:26:01"
},
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "d4ca2fb70344987502567bc50081c03e6192fb26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26",
+ "reference": "d4ca2fb70344987502567bc50081c03e6192fb26",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "time": "2016-01-28 13:25:10"
+ },
{
"name": "sebastian/recursion-context",
"version": "1.0.2",
diff --git a/src/Majora/Bundle/OAuthServerBundle/Resources/config/mapping/ORM/Token.orm.yml b/src/Majora/Bundle/OAuthServerBundle/Resources/config/mapping/ORM/Token.orm.yml
index 2236c78..bbdd5b4 100644
--- a/src/Majora/Bundle/OAuthServerBundle/Resources/config/mapping/ORM/Token.orm.yml
+++ b/src/Majora/Bundle/OAuthServerBundle/Resources/config/mapping/ORM/Token.orm.yml
@@ -14,8 +14,7 @@ Majora\Component\OAuth\Entity\Token:
generator: { strategy: AUTO }
fields:
hash:
- type: string
- length: 128
+ type: text
expireIn:
type: integer
expireAt:
diff --git a/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/extensions.xml b/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/extensions.xml
index 979371d..2027f72 100644
--- a/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/extensions.xml
+++ b/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/extensions.xml
@@ -22,6 +22,12 @@
-
+
+
+
+
+
diff --git a/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/server.xml b/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/server.xml
index 9ea7357..3f6f649 100644
--- a/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/server.xml
+++ b/src/Majora/Bundle/OAuthServerBundle/Resources/config/services/server.xml
@@ -23,6 +23,7 @@
+
diff --git a/src/Majora/Bundle/OAuthServerBundle/Security/AccessTokenAuthenticator.php b/src/Majora/Bundle/OAuthServerBundle/Security/AccessTokenAuthenticator.php
index 3279637..274c46d 100644
--- a/src/Majora/Bundle/OAuthServerBundle/Security/AccessTokenAuthenticator.php
+++ b/src/Majora/Bundle/OAuthServerBundle/Security/AccessTokenAuthenticator.php
@@ -53,7 +53,8 @@ public function getCredentials(Request $request)
// token through headers
case $request->headers->has('Authorization') :
- if (!preg_match('#^Bearer ([\w]+)$#', $request->headers->get('Authorization'), $matches)) {
+ $accessTokenPattern = '[\w--_]+';
+ if (!preg_match(sprintf('#^Bearer (%s)$#', $accessTokenPattern), $request->headers->get('Authorization'), $matches)) {
break; // bad Authorization format
}
diff --git a/src/Majora/Component/OAuth/Entity/AccessToken.php b/src/Majora/Component/OAuth/Entity/AccessToken.php
index 417da66..e7c72bc 100644
--- a/src/Majora/Component/OAuth/Entity/AccessToken.php
+++ b/src/Majora/Component/OAuth/Entity/AccessToken.php
@@ -8,14 +8,14 @@
use Majora\Component\OAuth\Model\RefreshTokenInterface;
use Majora\Framework\Model\CollectionableInterface;
use Majora\Framework\Model\CollectionableTrait;
-use Majora\Framework\Serializer\Model\SerializableTrait;
+use Majora\Framework\Normalizer\Model\NormalizableTrait;
/**
* Access token class.
*/
class AccessToken extends Token implements AccessTokenInterface, CollectionableInterface
{
- use CollectionableTrait, SerializableTrait;
+ use CollectionableTrait, NormalizableTrait;
/**
* @var RefreshTokenInterface
@@ -51,7 +51,7 @@ public function getRefreshToken()
public static function getScopes()
{
return array(
- 'default' => array('id', 'hash', 'expire_in', 'refresh_token', 'application@id', 'account@id'),
+ 'default' => array('id', 'hash', 'expire_in', 'refresh_token', 'application@id', 'account@id?'),
);
}
}
diff --git a/src/Majora/Component/OAuth/Entity/Account.php b/src/Majora/Component/OAuth/Entity/Account.php
index 6ecf4ca..2d01201 100644
--- a/src/Majora/Component/OAuth/Entity/Account.php
+++ b/src/Majora/Component/OAuth/Entity/Account.php
@@ -5,14 +5,14 @@
use Majora\Component\OAuth\Model\AccountInterface;
use Majora\Framework\Model\CollectionableInterface;
use Majora\Framework\Model\CollectionableTrait;
-use Majora\Framework\Serializer\Model\SerializableTrait;
+use Majora\Framework\Normalizer\Model\NormalizableTrait;
/**
* Basic implementation on AccountInterface.
*/
class Account implements AccountInterface, CollectionableInterface
{
- use CollectionableTrait, SerializableTrait;
+ use CollectionableTrait, NormalizableTrait;
/**
* @var int
@@ -183,9 +183,13 @@ public function getApplications()
/**
* @param array $applications
+ *
+ * @return self
*/
public function setApplications($applications)
{
$this->applications = $applications;
+
+ return $this;
}
}
diff --git a/src/Majora/Component/OAuth/Entity/Application.php b/src/Majora/Component/OAuth/Entity/Application.php
index fd1e8ad..e44d939 100644
--- a/src/Majora/Component/OAuth/Entity/Application.php
+++ b/src/Majora/Component/OAuth/Entity/Application.php
@@ -5,14 +5,14 @@
use Majora\Component\OAuth\Model\ApplicationInterface;
use Majora\Framework\Model\CollectionableInterface;
use Majora\Framework\Model\CollectionableTrait;
-use Majora\Framework\Serializer\Model\SerializableTrait;
+use Majora\Framework\Normalizer\Model\NormalizableTrait;
/**
* Basic implementation on ApplicationInterface.
*/
class Application implements ApplicationInterface, CollectionableInterface
{
- use CollectionableTrait, SerializableTrait;
+ use CollectionableTrait, NormalizableTrait;
/**
* @var int
@@ -225,9 +225,13 @@ public function getAccounts()
/**
* @param array $accounts
+ *
+ * @return self
*/
public function setAccounts($accounts)
{
$this->accounts = $accounts;
+
+ return $this;
}
}
diff --git a/src/Majora/Component/OAuth/Entity/RefreshToken.php b/src/Majora/Component/OAuth/Entity/RefreshToken.php
index 85829b1..6f00a2e 100644
--- a/src/Majora/Component/OAuth/Entity/RefreshToken.php
+++ b/src/Majora/Component/OAuth/Entity/RefreshToken.php
@@ -5,14 +5,14 @@
use Majora\Component\OAuth\Model\RefreshTokenInterface;
use Majora\Framework\Model\CollectionableInterface;
use Majora\Framework\Model\CollectionableTrait;
-use Majora\Framework\Serializer\Model\SerializableTrait;
+use Majora\Framework\Normalizer\Model\NormalizableTrait;
/**
* Class RefreshToken is the default implementation of RefreshTokenInterface.
*/
class RefreshToken extends Token implements RefreshTokenInterface, CollectionableInterface
{
- use CollectionableTrait, SerializableTrait;
+ use CollectionableTrait, NormalizableTrait;
/**
* {@inheritdoc}
diff --git a/src/Majora/Component/OAuth/Entity/Token.php b/src/Majora/Component/OAuth/Entity/Token.php
index e1abf21..a9eeff3 100644
--- a/src/Majora/Component/OAuth/Entity/Token.php
+++ b/src/Majora/Component/OAuth/Entity/Token.php
@@ -48,7 +48,7 @@ abstract class Token implements TokenInterface
public function __construct(
ApplicationInterface $application,
AccountInterface $account = null,
- $expireIn = TokenInterface::DEFAULT_TTL,
+ $expireIn = null,
\DateTime $expireAt = null,
$hash = null
) {
@@ -58,7 +58,7 @@ public function __construct(
$this->expireAt = $expireAt ?: \DateTime::createFromFormat('U', time() + intval($expireIn));
$this->hash = $hash ?: (new MessageDigestPasswordEncoder())->encodePassword(
- sprintf('[%s\o/%s]', $application->getSecret(), $account->getPassword() ?: time()),
+ sprintf('[%s\o/%s]', $application->getSecret(), $account ? $account->getPassword() : time()),
uniqid(mt_rand(), true)
);
}
diff --git a/src/Majora/Component/OAuth/GrantType/ClientCredentialsGrantExtension.php b/src/Majora/Component/OAuth/GrantType/ClientCredentialsGrantExtension.php
new file mode 100644
index 0000000..2d99b73
--- /dev/null
+++ b/src/Majora/Component/OAuth/GrantType/ClientCredentialsGrantExtension.php
@@ -0,0 +1,30 @@
+retrieveOnApplicationByUsernameQueryBuilder($application, $username)
+ ->getQuery()
+ ->getOneOrNullResult();
+ }
+
+ /**
+ * @param ApplicationInterface $application
+ * @param $username
+ *
+ * @return \Doctrine\ORM\QueryBuilder
+ */
+ public function retrieveOnApplicationByUsernameQueryBuilder(ApplicationInterface $application, $username)
{
return $this->accountRepository
->createQueryBuilder('ac')
- ->innerJoin('ac.applications', 'app')
- ->where('ac.username = :username')
- ->setParameter('username', $username)
- ->andWhere('app.id = :application')
- ->setParameter('application', $application->getId())
- ->getQuery()
- ->getOneOrNullResult()
- ;
+ ->innerJoin('ac.applications', 'app')
+ ->where('ac.username = :username')
+ ->setParameter('username', $username)
+ ->andWhere('app.id = :application')
+ ->setParameter('application', $application->getId());
}
}
diff --git a/src/Majora/Component/OAuth/Loader/ORM/ApplicationLoader.php b/src/Majora/Component/OAuth/Loader/ORM/ApplicationLoader.php
index 506e86c..f3f63e5 100644
--- a/src/Majora/Component/OAuth/Loader/ORM/ApplicationLoader.php
+++ b/src/Majora/Component/OAuth/Loader/ORM/ApplicationLoader.php
@@ -16,7 +16,7 @@ class ApplicationLoader implements ApplicationLoaderInterface
protected $applicationRepository;
/**
- * Construct.
+ * Constructor.
*
* @param ApplicationRepository $applicationRepository
*/
@@ -29,15 +29,25 @@ public function __construct(ApplicationRepository $applicationRepository)
* {@inheritdoc}
*/
public function retrieveByApiKeyAndSecret($apiKey, $secret)
+ {
+ return $this->retrieveByApiKeyAndSecretQueryBuilder($apiKey, $secret)
+ ->getQuery()
+ ->getOneOrNullResult();
+ }
+
+ /**
+ * @param $apiKey
+ * @param $secret
+ *
+ * @return \Doctrine\ORM\QueryBuilder
+ */
+ public function retrieveByApiKeyAndSecretQueryBuilder($apiKey, $secret)
{
return $this->applicationRepository
->createQueryBuilder('a')
- ->where('a.secret = :secret')
- ->setParameter('secret', $secret)
- ->andWhere('a.apiKey = :api_key')
- ->setParameter('api_key', $apiKey)
- ->getQuery()
- ->getOneOrNullResult()
- ;
+ ->where('a.secret = :secret')
+ ->setParameter('secret', $secret)
+ ->andWhere('a.apiKey = :api_key')
+ ->setParameter('api_key', $apiKey);
}
}
diff --git a/src/Majora/Component/OAuth/Loader/ORM/TokenLoader.php b/src/Majora/Component/OAuth/Loader/ORM/TokenLoader.php
index 0d7298f..af4d251 100644
--- a/src/Majora/Component/OAuth/Loader/ORM/TokenLoader.php
+++ b/src/Majora/Component/OAuth/Loader/ORM/TokenLoader.php
@@ -37,30 +37,48 @@ public function __construct(TokenRepository $tokenRepository, Clock $clock)
* @see TokenLoaderInterface::retrieveByHash()
*/
public function retrieveByHash($hash)
+ {
+ return $this->retrieveByHashQueryBuilder($hash)
+ ->getQuery()
+ ->setMaxResults(1)
+ ->getOneOrNullResult();
+ }
+
+ /**
+ * @param $hash
+ *
+ * @return \Doctrine\ORM\QueryBuilder
+ */
+ public function retrieveByHashQueryBuilder($hash)
{
return $this->tokenRepository
->createQueryBuilder('t')
- ->where('t.hash = :hash')
- ->setParameter('hash', $hash)
- ->andWhere('t.expireAt > :now')
- ->setParameter('now', $this->clock->now())
- ->getQuery()
- ->setMaxResults(1)
- ->getOneOrNullResult()
- ;
+ ->where('t.hash = :hash')
+ ->setParameter('hash', $hash)
+ ->andWhere('t.expireAt > :now')
+ ->setParameter('now', $this->clock->now());
}
/**
* @see TokenLoaderInterface::retrieveExpired()
*/
public function retrieveExpired(\DateTime $datetime = null)
+ {
+ return $this->retrieveExpiredQueryBuilder($datetime)
+ ->getQuery()
+ ->getResult();
+ }
+
+ /**
+ * @param \DateTime|null $datetime
+ *
+ * @return \Doctrine\ORM\QueryBuilder
+ */
+ public function retrieveExpiredQueryBuilder(\DateTime $datetime = null)
{
return $this->tokenRepository
->createQueryBuilder('t')
- ->where('t.expireAt < :date')
- ->setParameter('date', $datetime ?: $this->clock->now())
- ->getQuery()
- ->getResult()
- ;
+ ->where('t.expireAt < :date')
+ ->setParameter('date', $datetime ?: $this->clock->now());
}
}
diff --git a/src/Majora/Component/OAuth/Tests/Loader/ORM/AccessTokenLoaderTest.php b/src/Majora/Component/OAuth/Tests/Loader/ORM/AccessTokenLoaderTest.php
new file mode 100644
index 0000000..4e709b6
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Loader/ORM/AccessTokenLoaderTest.php
@@ -0,0 +1,36 @@
+clock = new Clock();
+
+ $this->tokenRepository = new AccessTokenRepository(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata(AccessTokenRepository::class)
+ );
+
+ $this->tokenLoader = new AccessTokenLoader(
+ $this->tokenRepository,
+ $this->clock
+ );
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Loader/ORM/AccountLoaderTest.php b/src/Majora/Component/OAuth/Tests/Loader/ORM/AccountLoaderTest.php
new file mode 100644
index 0000000..777d4a5
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Loader/ORM/AccountLoaderTest.php
@@ -0,0 +1,70 @@
+getProperty('accountRepository');
+ $property->setAccessible(true);
+
+ $this->assertEquals($property->getValue($accountLoader), $accountRepository);
+ }
+
+ /**
+ * Tests retrieveOnApplicationByUsernameQueryBuilder() method.
+ */
+ public function testRetrieveOnApplicationByUsernameQueryBuilder()
+ {
+ $accountRepository = new AccountRepository(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata(AccountRepository::class)
+ );
+
+ $accountLoader = new AccountLoader(
+ $accountRepository
+ );
+
+ $application = $this->prophesize('Majora\Component\OAuth\Entity\Application');
+
+ $queryBuilder = $accountLoader->retrieveOnApplicationByUsernameQueryBuilder(
+ $application->reveal(),
+ Argument::any()
+ );
+
+ $query = $queryBuilder->getQuery();
+
+ $this->assertEquals(
+ $query->getDQL(),
+ sprintf(
+ 'SELECT ac FROM %s ac INNER JOIN ac.applications app WHERE ac.username = :username AND app.id = :application',
+ AccountRepository::class
+ )
+ );
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Loader/ORM/ApplicationLoaderTest.php b/src/Majora/Component/OAuth/Tests/Loader/ORM/ApplicationLoaderTest.php
new file mode 100644
index 0000000..c54269d
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Loader/ORM/ApplicationLoaderTest.php
@@ -0,0 +1,62 @@
+getProperty('applicationRepository');
+ $property->setAccessible(true);
+
+ $this->assertEquals($property->getValue($applicationLoader), $applicationRepository);
+ }
+
+ /**
+ * Tests retrieveByApiKeyAndSecretQueryBuilder() method.
+ */
+ public function testRetrieveByApiKeyAndSecretQueryBuilder()
+ {
+ $applicationRepository = new ApplicationRepository(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata(ApplicationRepository::class)
+ );
+
+ $applicationLoader = new ApplicationLoader(
+ $applicationRepository
+ );
+
+ $queryBuilder = $applicationLoader->retrieveByApiKeyAndSecretQueryBuilder(Argument::any(), Argument::any());
+
+ $query = $queryBuilder->getQuery();
+
+ $this->assertEquals(
+ $query->getDQL(),
+ sprintf('SELECT a FROM %s a WHERE a.secret = :secret AND a.apiKey = :api_key', ApplicationRepository::class)
+ );
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Loader/ORM/RefreshTokenLoaderTest.php b/src/Majora/Component/OAuth/Tests/Loader/ORM/RefreshTokenLoaderTest.php
new file mode 100644
index 0000000..c2ad564
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Loader/ORM/RefreshTokenLoaderTest.php
@@ -0,0 +1,36 @@
+clock = new Clock();
+
+ $this->tokenRepository = new RefreshTokenRepository(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata(RefreshTokenRepository::class)
+ );
+
+ $this->tokenLoader = new RefreshTokenLoader(
+ $this->tokenRepository,
+ $this->clock
+ );
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Loader/ORM/TokenLoaderTest.php b/src/Majora/Component/OAuth/Tests/Loader/ORM/TokenLoaderTest.php
new file mode 100644
index 0000000..a1e91a0
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Loader/ORM/TokenLoaderTest.php
@@ -0,0 +1,109 @@
+clock = new Clock();
+
+ $this->tokenRepository = new TokenRepository(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata(TokenRepository::class)
+ );
+
+ $this->tokenLoader = new TokenLoader(
+ $this->tokenRepository,
+ $this->clock
+ );
+ }
+
+ /**
+ * Tests __construct() method.
+ */
+ public function testConstructor()
+ {
+ $tokenRepositoryClass = $this->tokenRepository->getClassName();
+ $tokenLoaderClass = get_class($this->tokenLoader);
+
+ $tokenRepository = new $tokenRepositoryClass(
+ DoctrineTestHelper::createTestEntityManager(),
+ new ClassMetadata($tokenRepositoryClass)
+ );
+
+ $tokenLoader = new $tokenLoaderClass(
+ $tokenRepository,
+ $this->clock
+ );
+
+ $reflectedClass = new \ReflectionClass($tokenLoaderClass);
+ $property = $reflectedClass->getProperty('tokenRepository');
+ $property->setAccessible(true);
+
+ $this->assertEquals($property->getValue($tokenLoader), $tokenRepository);
+ }
+
+ /**
+ * Tests retrieveByHashQueryBuilder() method.
+ */
+ public function testRetrieveByHashQueryBuilder()
+ {
+ $queryBuilder = $this->tokenLoader->retrieveByHashQueryBuilder('1234');
+
+ $query = $queryBuilder->getQuery();
+
+ $this->assertEquals(
+ $query->getDQL(),
+ sprintf(
+ 'SELECT t FROM %s t WHERE t.hash = :hash AND t.expireAt > :now',
+ $this->tokenRepository->getClassName()
+ )
+ );
+ }
+
+ /**
+ * Tests retrieveExpiredQueryBuilder() method.
+ */
+ public function testRetrieveExpiredQueryBuilder()
+ {
+ $queryBuilder = $this->tokenLoader->retrieveExpiredQueryBuilder($this->clock->now());
+
+ $query = $queryBuilder->getQuery();
+
+ $this->assertEquals(
+ $query->getDQL(),
+ sprintf('SELECT t FROM %s t WHERE t.expireAt < :date', $this->tokenRepository->getClassName())
+ );
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Repository/ORM/AccessTokenRepositoryTest.php b/src/Majora/Component/OAuth/Tests/Repository/ORM/AccessTokenRepositoryTest.php
new file mode 100644
index 0000000..563a533
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Repository/ORM/AccessTokenRepositoryTest.php
@@ -0,0 +1,54 @@
+prophesize(AccessToken::class)->reveal();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->persist($token)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new AccessTokenRepository(
+ $em->reveal(),
+ new ClassMetadata(AccessToken::class)
+ );
+
+ $repository->persist($token);
+ }
+
+ /**
+ * Tests remove() method.
+ */
+ public function testRemove()
+ {
+ $token = $this->prophesize(AccessToken::class)->reveal();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->remove($token)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new AccessTokenRepository(
+ $em->reveal(),
+ new ClassMetadata(AccessToken::class)
+ );
+
+ $repository->remove($token);
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Repository/ORM/AccountRepositoryTest.php b/src/Majora/Component/OAuth/Tests/Repository/ORM/AccountRepositoryTest.php
new file mode 100644
index 0000000..92e1be2
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Repository/ORM/AccountRepositoryTest.php
@@ -0,0 +1,54 @@
+prophesize(EntityManagerInterface::class);
+
+ $em->persist($account)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new AccountRepository(
+ $em->reveal(),
+ new ClassMetadata(Account::class)
+ );
+
+ $repository->persist($account);
+ }
+
+ /**
+ * Tests remove() method.
+ */
+ public function testRemove()
+ {
+ $account = new Account();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->remove($account)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new AccountRepository(
+ $em->reveal(),
+ new ClassMetadata(Account::class)
+ );
+
+ $repository->remove($account);
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Repository/ORM/ApplicationRepositoryTest.php b/src/Majora/Component/OAuth/Tests/Repository/ORM/ApplicationRepositoryTest.php
new file mode 100644
index 0000000..4672dc7
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Repository/ORM/ApplicationRepositoryTest.php
@@ -0,0 +1,54 @@
+prophesize(EntityManagerInterface::class);
+
+ $em->persist($application)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new ApplicationRepository(
+ $em->reveal(),
+ new ClassMetadata(Application::class)
+ );
+
+ $repository->persist($application);
+ }
+
+ /**
+ * Tests remove() method.
+ */
+ public function testRemove()
+ {
+ $application = new Application();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->remove($application)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new ApplicationRepository(
+ $em->reveal(),
+ new ClassMetadata(Application::class)
+ );
+
+ $repository->remove($application);
+ }
+}
diff --git a/src/Majora/Component/OAuth/Tests/Repository/ORM/RefreshTokenRepositoryTest.php b/src/Majora/Component/OAuth/Tests/Repository/ORM/RefreshTokenRepositoryTest.php
new file mode 100644
index 0000000..984b076
--- /dev/null
+++ b/src/Majora/Component/OAuth/Tests/Repository/ORM/RefreshTokenRepositoryTest.php
@@ -0,0 +1,54 @@
+prophesize(RefreshToken::class)->reveal();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->persist($token)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new RefreshTokenRepository(
+ $em->reveal(),
+ new ClassMetadata(RefreshToken::class)
+ );
+
+ $repository->persist($token);
+ }
+
+ /**
+ * Tests remove() method.
+ */
+ public function testRemove()
+ {
+ $token = $this->prophesize(RefreshToken::class)->reveal();
+ $em = $this->prophesize(EntityManagerInterface::class);
+
+ $em->remove($token)->shouldBeCalled();
+ $em->flush()->shouldBeCalled();
+
+ $repository = new RefreshTokenRepository(
+ $em->reveal(),
+ new ClassMetadata(RefreshToken::class)
+ );
+
+ $repository->remove($token);
+ }
+}