feat: teamHideSensitiveFields

This commit is contained in:
loks0n
2024-11-01 11:38:56 +00:00
parent 5be76494c2
commit c9b2d6eb90
4 changed files with 121 additions and 17 deletions
+32
View File
@@ -111,6 +111,7 @@ App::post('/v1/projects')
'personalDataCheck' => false,
'mockNumbers' => [],
'sessionAlerts' => false,
'teamHideSensitiveFields' => false,
];
foreach ($auth as $method) {
@@ -648,6 +649,37 @@ App::patch('/v1/projects/:projectId/auth/session-alerts')
$response->dynamic($project, Response::MODEL_PROJECT);
});
App::patch('/v1/projects/:projectId/auth/session-alerts')
->desc('Update project team hide sensitive fields')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateTeamHideSensitiveFields')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('teamHideSensitiveFields', false, new Boolean(true), 'Set to true to hide sensitive fields from team members.')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, bool $alerts, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$auths = $project->getAttribute('auths', []);
$auths['teamShowSensitiveFields'] = $alerts;
$dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute('auths', $auths));
$response->dynamic($project, Response::MODEL_PROJECT);
});
App::patch('/v1/projects/:projectId/auth/limit')
->desc('Update project users limit')
->groups(['api', 'projects'])
+21 -17
View File
@@ -727,8 +727,9 @@ App::get('/v1/teams/:teamId/memberships')
->param('queries', [], new Memberships(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Memberships::ALLOWED_ATTRIBUTES), true)
->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true)
->inject('response')
->inject('project')
->inject('dbForProject')
->action(function (string $teamId, array $queries, string $search, Response $response, Database $dbForProject) {
->action(function (string $teamId, array $queries, string $search, Response $response, Document $project, Database $dbForProject) {
$team = $dbForProject->getDocument('teams', $teamId);
@@ -790,27 +791,30 @@ App::get('/v1/teams/:teamId/memberships')
$memberships = array_filter($memberships, fn (Document $membership) => !empty($membership->getAttribute('userId')));
$memberships = array_map(function ($membership) use ($dbForProject, $team) {
$hideSensitiveFields = $project->getAttribute('auths', [])['teamHideSensitiveFields'] ?? false;
$memberships = array_map(function ($membership) use ($dbForProject, $team, $hideSensitiveFields) {
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
$membership->setAttribute('teamName', $team->getAttribute('name'));
$mfa = $user->getAttribute('mfa', false);
if ($mfa) {
$totp = TOTP::getAuthenticatorFromUser($user);
$totpEnabled = $totp && $totp->getAttribute('verified', false);
$emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false);
$phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false);
if (!$hideSensitiveFields) {
$mfa = $user->getAttribute('mfa', false);
if ($mfa) {
$totp = TOTP::getAuthenticatorFromUser($user);
$totpEnabled = $totp && $totp->getAttribute('verified', false);
$emailEnabled = $user->getAttribute('email', false) && $user->getAttribute('emailVerification', false);
$phoneEnabled = $user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false);
if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) {
$mfa = false;
if (!$totpEnabled && !$emailEnabled && !$phoneEnabled) {
$mfa = false;
}
}
}
$membership
->setAttribute('mfa', $mfa)
->setAttribute('teamName', $team->getAttribute('name'))
->setAttribute('userName', $user->getAttribute('name'))
->setAttribute('userEmail', $user->getAttribute('email'))
;
$membership
->setAttribute('mfa', $mfa)
->setAttribute('userName', $user->getAttribute('name'))
->setAttribute('userEmail', $user->getAttribute('email'));
}
return $membership;
}, $memberships);
@@ -151,6 +151,12 @@ class Project extends Model
'default' => false,
'example' => true,
])
->addRule('teamHideSensitiveFields', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Whether or not to hide sensitive data in the teams API.',
'default' => false,
'example' => true,
])
->addRule('oAuthProviders', [
'type' => Response::MODEL_AUTH_PROVIDER,
'description' => 'List of Auth Providers.',
@@ -348,6 +354,7 @@ class Project extends Model
$document->setAttribute('authPersonalDataCheck', $authValues['personalDataCheck'] ?? false);
$document->setAttribute('authMockNumbers', $authValues['mockNumbers'] ?? []);
$document->setAttribute('authSessionAlerts', $authValues['sessionAlerts'] ?? false);
$document->setAttribute('authTeamHideSensitiveFields', $authValues['teamHideSensitiveFields'] ?? false);
foreach ($auth as $index => $method) {
$key = $method['key'];
@@ -130,6 +130,67 @@ trait TeamsBaseClient
$this->assertEmpty($response['body']['memberships']);
$this->assertEquals(0, $response['body']['total']);
/**
* Update project settings to hide sensitive fields
*/
$projectId = $this->getProject()['$id'];
$response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/auth/session-alerts', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
'x-appwrite-key' => $this->getRoot()['secret'],
]), [
'teamHideSensitiveFields' => true,
]);
$this->assertEquals(200, $response['headers']['status-code']);
/**
* Test that sensitive fields are hidden
*/
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertIsInt($response['body']['total']);
$this->assertNotEmpty($response['body']['memberships'][0]['$id']);
// Assert that sensitive fields are not present
$this->assertArrayNotHasKey('userName', $response['body']['memberships'][0]);
$this->assertArrayNotHasKey('userEmail', $response['body']['memberships'][0]);
$this->assertArrayNotHasKey('mfa', $response['body']['memberships'][0]);
/**
* Update project settings to show sensitive fields
*/
$response = $this->client->call(Client::METHOD_PATCH, '/projects/' . $projectId . '/auth/session-alerts', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
'x-appwrite-key' => $this->getRoot()['secret'],
]), [
'teamHideSensitiveFields' => false,
]);
$this->assertEquals(200, $response['headers']['status-code']);
/**
* Test that sensitive fields are shown
*/
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertIsInt($response['body']['total']);
$this->assertNotEmpty($response['body']['memberships'][0]['$id']);
// Assert that sensitive fields are present
$this->assertEquals($this->getUser()['name'], $response['body']['memberships'][0]['userName']);
$this->assertEquals($this->getUser()['email'], $response['body']['memberships'][0]['userEmail']);
$this->assertFalse($response['body']['memberships'][0]['mfa']);
/**
* Test for FAILURE
*/