diff --git a/.env b/.env index 74c21f5b..5f105b59 100755 --- a/.env +++ b/.env @@ -28,4 +28,4 @@ ELASTIC_AUTH=ember-nexus-elasticsearch:9200 REDIS_AUTH=tcp://ember-nexus-redis?password=redis-password RABBITMQ_AUTH=amqp://user:password@ember-nexus-rabbitmq:5672 -REFERENCE_DATASET_VERSION=0.0.8 +REFERENCE_DATASET_VERSION=0.0.9 diff --git a/docs/api-endpoints/user/get-token.md b/docs/api-endpoints/user/get-token.md index c09965ec..dc90d51e 100644 --- a/docs/api-endpoints/user/get-token.md +++ b/docs/api-endpoints/user/get-token.md @@ -3,3 +3,5 @@ Returns the currently used token. To display all tokens, you can return all root elements and filter for the `Token` type. + +Currently under development. diff --git a/docs/api-endpoints/user/post-token.md b/docs/api-endpoints/user/post-token.md index 771f4b17..9a5a5837 100644 --- a/docs/api-endpoints/user/post-token.md +++ b/docs/api-endpoints/user/post-token.md @@ -14,21 +14,18 @@ The posted request must be a valid JSON document. The request must contain the following attributes: -- `type`: Containing the content "User". No other values are currently possible. -- `password`: The plain text password of the new user. Can contain any string, will be hashed internally. Whitespace at - the start or end of the string will **not** be removed, though it is discouraged. - No password complexity check is performed. -- `data.`: By default `data.email`, must contain a new unique string. While not required, it is encouraged - to keep the content within 256 bytes. Optional limits might be added at a later time. - The required identifier name is returned by the - [instance configuration endpoint](/api-endpoints/get-instance-configuration) and in error messages. +- `type`: Containing the content "Token". No other values are currently possible. +- `user`: The value for the user's identifying property, by default the user's email address. +- `password`: The plain text password of the user. +- `data`: Object of properties, optional. ```json { - "type": "User", + "type": "Token", + "user": "test@localhost.dev", "password": "1234", "data": { - "": "test@example.com" + "key": "value" } } ``` @@ -39,16 +36,20 @@ The request must contain the following attributes: curl \ -X POST \ -H "Content-Type: application/json" \ - -d '{"type": "User", "password": "1234", "data": {"email": "test@example.com"}}' \ - https://api.localhost/register + -d '{"type": "Token", "user": "test@localhost.dev", "password": "1234"}' \ + https://api.localhost/token ``` ### **Success 200** -Success responses do not have a return body. The location of the new user, containing the user's UUID, is written in the -`Location` header. +```json +{ + "type": "_TokenResponse", + "token": "secret-token:ERgAAnWl0CY8bQs0m11nZ3" +} +``` ### **Error 400** @@ -57,21 +58,25 @@ Success responses do not have a return body. The location of the new user, conta "type": "400-bad-request", "title": "Bad Request", "status": 400, - "detail": "Property 'email' must be set." + "detail": "Property 'user' must be set." } ``` -### **Error 403** +### **Error 401** ```problem+json { - "type": "403-forbidden", - "title": "Forbidden", - "status": 403, - "detail": "Client does not have permissions to perform action." + "type": "401-unauthorized", + "title": "Request does not contain valid token, or anonymous user is disabled.", + "status": 401, + "detail": "" } ``` +### **Error 500** + +wip + @@ -131,32 +136,29 @@ G6.registerEdge('polyline-edge', { renderWorkflow(document.getElementById('graph-container-1'), { nodes: [ { id: 'init', ...workflowStart, label: 'server receives POST-request' }, - { id: 'checkEndpointEnabled', ...workflowDecision, label: 'is endpoint enabled?' }, - { id: 'checkPassword', ...workflowDecision, label: 'is password given?' }, { id: 'checkType', ...workflowDecision, label: 'is type given?' }, - { id: 'checkTypeContent', ...workflowDecision, label: 'is type equal to "User"?' }, - { id: 'checkIdentifier', ...workflowDecision, label: "is identifier given?" }, - { id: 'checkIdentifierUnique', ...workflowDecision, label: 'is identifier unique?' }, - { id: 'createUser', ...workflowStep, label: "create user" }, + { id: 'checkTypeContent', ...workflowDecision, label: 'is type equal\nto "Token"?' }, + { id: 'checkUserProperty', ...workflowDecision, label: 'is user given?' }, + { id: 'checkPasswordProperty', ...workflowDecision, label: "is password given?" }, + { id: 'checkCredentials', ...workflowDecision, label: 'are credentials ok?' }, + { id: 'createToken', ...workflowStep, label: "create token" }, { id: 'error400', ...workflowEndError, label: "return 400" }, - { id: 'error403', ...workflowEndError, label: 'return 403' }, + { id: 'error401', ...workflowEndError, label: 'return 401' }, { id: 'success200', ...workflowEndSuccess , label: "return 200"}, ], edges: [ - { source: 'init', target: 'checkEndpointEnabled', label: '' }, - { source: 'checkEndpointEnabled', target: 'checkPassword', label: 'yes' }, - { source: 'checkEndpointEnabled', target: 'error403', label: 'no' }, - { source: 'checkPassword', target: 'checkType', label: 'yes' }, - { source: 'checkPassword', target: 'error400', label: 'no' }, + { source: 'init', target: 'checkType', label: '' }, { source: 'checkType', target: 'checkTypeContent', label: 'yes' }, { source: 'checkType', target: 'error400', label: 'no' }, - { source: 'checkTypeContent', target: 'checkIdentifier', label: 'yes' }, + { source: 'checkTypeContent', target: 'checkUserProperty', label: 'yes' }, { source: 'checkTypeContent', target: 'error400', label: 'no' }, - { source: 'checkIdentifier', target: 'checkIdentifierUnique', label: 'yes' }, - { source: 'checkIdentifier', target: 'error400', label: 'no' }, - { source: 'checkIdentifierUnique', target: 'createUser', label: 'yes' }, - { source: 'checkIdentifierUnique', target: 'error400', label: 'no' }, - { source: 'createUser', target: 'success200', label: '' }, + { source: 'checkUserProperty', target: 'checkPasswordProperty', label: 'yes' }, + { source: 'checkUserProperty', target: 'error400', label: 'no' }, + { source: 'checkPasswordProperty', target: 'checkCredentials', label: 'yes' }, + { source: 'checkPasswordProperty', target: 'error400', label: 'no' }, + { source: 'checkCredentials', target: 'createToken', label: 'yes' }, + { source: 'checkCredentials', target: 'error401', label: 'no' }, + { source: 'createToken', target: 'success200', label: '' }, ], }, 'TB'); diff --git a/src/Controller/User/PostTokenController.php b/src/Controller/User/PostTokenController.php index 43224f06..ae65f593 100644 --- a/src/Controller/User/PostTokenController.php +++ b/src/Controller/User/PostTokenController.php @@ -42,15 +42,23 @@ public function __construct( public function postToken(Request $request): Response { $body = \Safe\json_decode($request->getContent(), true); + + if (!array_key_exists('type', $body)) { + throw $this->client400MissingPropertyExceptionFactory->createFromTemplate('type', 'string'); + } + if ('Token' !== $body['type']) { + throw $this->client400BadContentExceptionFactory->createFromTemplate('type', 'Token', $body['type']); + } + /** * @var array $body */ - $uniqueIdentifier = $this->emberNexusConfiguration->getRegisterUniqueIdentifier(); - if (!array_key_exists($uniqueIdentifier, $body)) { - throw $this->client400MissingPropertyExceptionFactory->createFromTemplate($uniqueIdentifier, 'string'); + if (!array_key_exists('user', $body)) { + throw $this->client400MissingPropertyExceptionFactory->createFromTemplate('user', 'string'); } - $uniqueIdentifierValue = $body[$uniqueIdentifier]; + $uniqueIdentifierValue = $body['user']; + $uniqueIdentifier = $this->emberNexusConfiguration->getRegisterUniqueIdentifier(); $res = $this->cypherEntityManager->getClient()->runStatement(Statement::create( sprintf( 'MATCH (u:User {%s: $identifier}) RETURN u.id AS id', @@ -84,13 +92,6 @@ public function postToken(Request $request): Response $lifetimeInSeconds = (int) $body['lifetimeInSeconds']; } - if (!array_key_exists('type', $body)) { - throw $this->client400MissingPropertyExceptionFactory->createFromTemplate('type', 'string'); - } - if ('Token' !== $body['type']) { - throw $this->client400BadContentExceptionFactory->createFromTemplate('type', 'Token', $body['type']); - } - $data = []; if (array_key_exists('data', $body)) { $data = $body['data']; diff --git a/test-feature-prepare b/test-feature-prepare old mode 100644 new mode 100755 diff --git a/tests/FeatureTests/Endpoint/User/PostTokenTest.php b/tests/FeatureTests/Endpoint/User/PostTokenTest.php index 3c61cd0b..f66013be 100644 --- a/tests/FeatureTests/Endpoint/User/PostTokenTest.php +++ b/tests/FeatureTests/Endpoint/User/PostTokenTest.php @@ -4,11 +4,14 @@ use App\Tests\FeatureTests\BaseRequestTestCase; +/** + * @group test + */ class PostTokenTest extends BaseRequestTestCase { public const TOKEN = 'secret-token:3tgEP9MhD81rkp3qiJcm1U'; - public const EMAIL = ''; - public const PASSWORD = ''; + public const EMAIL = 'user@postToken.user.endpoint.localhost.de'; + public const PASSWORD = '1234'; public function testPostToken(): void { @@ -25,6 +28,8 @@ public function testPostToken(): void ] ); + echo "\n\n".((string) $response->getBody())."\n\n"; + $this->assertSame(200, $response->getStatusCode()); $this->assertSame('application/json; charset=utf-8', $response->getHeader('content-type')[0]); $body = \Safe\json_decode((string) $response->getBody(), true);