assertUrlIsSecured('/api/users'); } /** * @return array> */ public static function getRoleTestData(): array { return [ [User::ROLE_USER], [User::ROLE_TEAMLEAD], [User::ROLE_ADMIN], ]; } #[DataProvider('getRoleTestData')] public function testIsSecureForRole(string $role): void { $this->assertUrlIsSecuredForRole($role, '/api/users'); } public function testGetCollection(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(7, \count($result)); foreach ($result as $user) { self::assertIsArray($user); self::assertApiResponseTypeStructure('UserCollection', $user); } } public function testGetCollectionFull(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users?full=true'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(7, \count($result)); foreach ($result as $user) { self::assertIsArray($user); self::assertApiResponseTypeStructure('UserEntity', $user); } } public function testGetCollectionWithQuery(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users', 'GET', ['visible' => 2, 'orderBy' => 'email', 'order' => 'DESC', 'term' => 'chris']); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(1, \count($result)); foreach ($result as $user) { self::assertIsArray($user); self::assertApiResponseTypeStructure('UserCollection', $user); } } public function testGetCollectionWithQuery2(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users', 'GET', ['visible' => 3, 'orderBy' => 'email', 'order' => 'DESC']); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertNotEmpty($result); self::assertEquals(8, \count($result)); foreach ($result as $user) { self::assertIsArray($user); self::assertApiResponseTypeStructure('UserCollection', $user); } } public function testGetEntity(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users/1'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('UserEntity', $result); self::assertEquals('1', $result['id']); self::assertEquals('CFO', $result['title']); self::assertEquals('Clara Haynes', $result['alias']); } public function testGetMyProfile(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $this->assertAccessIsGranted($client, '/api/users/me'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('UserEntity', $result); self::assertEquals('6', $result['id']); self::assertEquals('Super Administrator', $result['title']); self::assertEquals('', $result['alias']); } public function testNotFound(): void { $this->assertEntityNotFound(User::ROLE_SUPER_ADMIN, '/api/users/99'); } public function testGetEntityAccessDenied(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $this->assertApiAccessDenied($client, '/api/users/4', 'You are not allowed to view this profile'); } public function testGetEntityAccessAllowedForOwnProfile(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $this->assertAccessIsGranted($client, '/api/users/2'); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('UserEntity', $result); } public function testPostAction(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $data = [ 'username' => 'foo', 'email' => 'foo@example.com', 'title' => 'asdfghjkl', 'plainPassword' => 'foo@example.com', 'enabled' => true, 'supervisor' => 2, 'language' => 'ru', 'timezone' => 'Europe/Paris', 'roles' => [ 'ROLE_TEAMLEAD', 'ROLE_ADMIN' ], ]; $this->request($client, '/api/users', 'POST', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('UserEntity', $result); self::assertNotEmpty($result['id']); self::assertEquals('foo', $result['username']); self::assertEquals('asdfghjkl', $result['title']); self::assertTrue($result['enabled']); self::assertEquals('ru', $result['language']); self::assertEquals('Europe/Paris', $result['timezone']); self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN'], $result['roles']); } public function testPostActionWithShortPassword(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $data = [ 'username' => 'foo', 'email' => 'foo@example.com', 'title' => 'asdfghjkl', 'plainPassword' => '1234567', 'enabled' => true, 'language' => 'ru', 'timezone' => 'Europe/Paris', 'roles' => [ 'ROLE_TEAMLEAD', 'ROLE_ADMIN' ], ]; $this->request($client, '/api/users', 'POST', [], (string) json_encode($data)); $response = $client->getResponse(); self::assertEquals(400, $response->getStatusCode()); $this->assertApiCallValidationError($response, ['plainPassword']); } public function testPostActionWithValidationErrors(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $data = [ 'username' => '', 'email' => '', 'plainPassword' => '123456', 'language' => 'xx', 'timezone' => 'XXX/YYY', 'roles' => [ 'ABC', ], ]; $this->request($client, '/api/users', 'POST', [], (string) json_encode($data)); $response = $client->getResponse(); self::assertEquals(400, $response->getStatusCode()); $this->assertApiCallValidationError($response, ['username', 'email', 'plainPassword', 'language', 'timezone', 'roles']); } public function testPostActionWithInvalidUser(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN); $data = [ 'username' => 'foo', 'email' => 'foo@example.com', 'plainPassword' => 'foo@example.com', 'enabled' => true, 'language' => 'ru', 'timezone' => 'Europe/Paris', ]; $this->request($client, '/api/users', 'POST', [], (string) json_encode($data)); $response = $client->getResponse(); $this->assertApiResponseAccessDenied($response, 'Access denied.'); } public function testPatchAction(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $data = [ 'username' => 'foo', 'email' => 'foo@example.com', 'title' => 'asdfghjkl', 'plainPassword' => 'foo@example.com', 'language' => 'ru', 'timezone' => 'Europe/Paris', 'roles' => [ 'ROLE_TEAMLEAD', 'ROLE_ADMIN' ], ]; $this->request($client, '/api/users', 'POST', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertFalse($result['enabled']); $data = [ 'title' => 'qwertzui', 'enabled' => true, 'language' => 'it', 'timezone' => 'America/New_York', 'roles' => [ 'ROLE_TEAMLEAD', ], ]; $id = $result['id']; self::assertIsNumeric($id); $this->request($client, '/api/users/' . $id, 'PATCH', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); $content = $client->getResponse()->getContent(); self::assertIsString($content); $result = json_decode($content, true); self::assertIsArray($result); self::assertApiResponseTypeStructure('UserEntity', $result); self::assertNotEmpty($result['id']); self::assertEquals('foo', $result['username']); self::assertEquals('qwertzui', $result['title']); self::assertTrue($result['enabled']); self::assertEquals('it', $result['language']); self::assertEquals('America/New_York', $result['timezone']); self::assertEquals(['ROLE_TEAMLEAD'], $result['roles']); } public function testPatchActionWithUnknownUser(): void { $this->assertEntityNotFoundForPatch(User::ROLE_SUPER_ADMIN, '/api/users/255', []); } public function testPatchActionWithInvalidUser(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $this->request($client, '/api/users/1', 'PATCH', [], (string) json_encode(['language' => 'hu'])); $this->assertApiResponseAccessDenied($client->getResponse(), 'Not allowed to edit user'); } public function testPatchActionWithValidationErrors(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); $data = [ 'username' => '1', // not existing in form 'email' => '', 'plainPassword' => '123456', // not existing in form 'plainApiToken' => '123456', // not existing in form 'language' => 'xx', 'timezone' => 'XXX/YYY', 'roles' => [ 'ABC', ], ]; $this->request($client, '/api/users/1', 'PATCH', [], (string) json_encode($data)); $response = $client->getResponse(); self::assertEquals(400, $response->getStatusCode()); $this->assertApiCallValidationError($response, ['email', 'language', 'timezone', 'roles'], true); } // ------------------------------------- [USER PREFERENCES] ------------------------------------- public function testUpdateUserPreferenceThrowsNotFound(): void { $this->assertEntityNotFoundForPatch(User::ROLE_ADMIN, '/api/users/42/preferences', []); } public function testUpdateUserPreferenceThrowsExceptionOnWrongStructure(): void { $this->assertExceptionForPatchAction(User::ROLE_SUPER_ADMIN, '/api/users/1/preferences', ['name' => 'X', 'value' => 'X'], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateUserPreferenceThrowsExceptionOnMissingName(): void { $this->assertExceptionForPatchAction(User::ROLE_SUPER_ADMIN, '/api/users/1/preferences', [['value' => 'X']], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateUserPreferenceThrowsExceptionOnMissingValue(): void { $this->assertExceptionForPatchAction(User::ROLE_SUPER_ADMIN, '/api/users/1/preferences', [['name' => 'X']], [ 'code' => Response::HTTP_BAD_REQUEST, 'message' => 'Bad Request' ]); } public function testUpdateUserPreferenceThrowsExceptionOnMissingMetafield(): void { $this->assertExceptionForPatchAction(User::ROLE_SUPER_ADMIN, '/api/users/1/preferences', [['name' => 'X', 'value' => 'Y']], [ 'code' => Response::HTTP_NOT_FOUND, 'message' => 'Not Found' ]); } public function testUpdateUserPreference(): void { $client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN); /** @var EventDispatcher $dispatcher */ $dispatcher = static::getContainer()->get('event_dispatcher'); $dispatcher->addSubscriber(new PrepareUserEventSubscriberMock()); $data = [ [ 'name' => 'metatestmock', 'value' => 'another,testing,bar' ] ]; $this->request($client, '/api/users/1/preferences', 'PATCH', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); $em = $this->getEntityManager(); /** @var User $user */ $user = $em->getRepository(User::class)->find(1); self::assertEquals('another,testing,bar', $user->getPreferenceValue('metatestmock')); self::assertEquals('another,testing,bar', $user->getPreferenceValue('metatestmock')); } public function testUpdateUserPreferenceWithEnabledPreference(): void { $role = User::ROLE_SUPER_ADMIN; $id = $this->getAuthenticatedUserId($role); $client = $this->getClientForAuthenticatedUser($role); $em = $this->getEntityManager(); /** @var User $user */ $user = $em->getRepository(User::class)->find($id); self::assertEquals(46, $user->getPreferenceValue('hourly_rate')); $data = [ [ 'name' => 'hourly_rate', 'value' => 99 ] ]; $this->request($client, '/api/users/' . $id . '/preferences', 'PATCH', [], (string) json_encode($data)); self::assertTrue($client->getResponse()->isSuccessful()); /** @var User $user */ $user = $em->getRepository(User::class)->find($id); self::assertEquals(99, $user->getPreferenceValue('hourly_rate')); } public function testUpdateUserPreferenceWithDisabledPreference(): void { $role = User::ROLE_USER; $id = $this->getAuthenticatedUserId($role); $client = $this->getClientForAuthenticatedUser($role); $em = $this->getEntityManager(); /** @var User $user */ $user = $em->getRepository(User::class)->find($id); self::assertEquals(82, $user->getPreferenceValue('hourly_rate')); $data = [ [ 'name' => 'hourly_rate', 'value' => 99 ] ]; $this->request($client, '/api/users/' . $id . '/preferences', 'PATCH', [], (string) json_encode($data)); self::assertApiResponseAccessDenied($client->getResponse()); } }