1
0
Fork 0
mirror of synced 2024-09-28 07:21:35 +12:00

Merge pull request #5174 from yatharth1706/fix-4797-verified-user-getting-email-verifications

Fix verified user getting email verifications
This commit is contained in:
Torsten Dittmann 2023-11-15 13:35:23 +01:00 committed by GitHub
commit 115ca23a58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 183 additions and 114 deletions

View file

@ -240,6 +240,16 @@ return [
'description' => 'OAuth2 provider returned some error.',
'code' => 424,
],
Exception::USER_EMAIL_ALREADY_VERIFIED => [
'name' => Exception::USER_EMAIL_ALREADY_VERIFIED,
'description' => 'User email is already verified',
'code' => 409,
],
Exception::USER_PHONE_ALREADY_VERIFIED => [
'name' => Exception::USER_PHONE_ALREADY_VERIFIED,
'description' => 'User phone is already verified',
'code' => 409
],
/** Teams */
Exception::TEAM_NOT_FOUND => [

View file

@ -2662,6 +2662,10 @@ App::post('/v1/account/verification')
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
}
if ($user->getAttribute('emailVerification')) {
throw new Exception(Exception::USER_EMAIL_ALREADY_VERIFIED);
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);
@ -2883,6 +2887,10 @@ App::post('/v1/account/verification/phone')
throw new Exception(Exception::USER_PHONE_NOT_FOUND);
}
if ($user->getAttribute('phoneVerification')) {
throw new Exception(Exception::USER_PHONE_ALREADY_VERIFIED);
}
$roles = Authorization::getRoles();
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
$isAppUser = Auth::isAppUser($roles);

View file

@ -84,6 +84,8 @@ class Exception extends \Exception
public const USER_OAUTH2_BAD_REQUEST = 'user_oauth2_bad_request';
public const USER_OAUTH2_UNAUTHORIZED = 'user_oauth2_unauthorized';
public const USER_OAUTH2_PROVIDER_ERROR = 'user_oauth2_provider_error';
public const USER_EMAIL_ALREADY_VERIFIED = 'user_email_alread_verified';
public const USER_PHONE_ALREADY_VERIFIED = 'user_phone_already_verified';
/** Teams */
public const TEAM_NOT_FOUND = 'team_not_found';

View file

@ -945,6 +945,32 @@ trait AccountBase
return $data;
}
/**
* @depends testUpdateAccountVerification
*/
public function testCreateAccountVerificationForVerifiedEmail($data): array
{
$email = $data['email'] ?? '';
$name = $data['name'] ?? '';
$session = $data['session'] ?? '';
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_POST, '/account/verification', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'url' => 'http://localhost/verification',
]);
$this->assertEquals(409, $response['headers']['status-code']);
return $data;
}
/**
* @depends testUpdateAccountVerification
*/

View file

@ -1068,4 +1068,27 @@ class AccountCustomClientTest extends Scope
return $data;
}
/**
* @depends testPhoneVerification
*/
#[Retry(count: 1)]
public function testPhoneVerificationForVerifiedPhone(array $data): array
{
$session = $data['session'] ?? '';
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_POST, '/account/verification/phone', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]));
$this->assertEquals(409, $response['headers']['status-code']);
return $data;
}
}

View file

@ -636,6 +636,120 @@ class WebhooksCustomClientTest extends Scope
return $data;
}
/**
* @depends testUpdateAccountPrefs
*/
public function testCreateAccountVerification($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$session = $data['session'] ?? '';
$verification = $this->client->call(Client::METHOD_POST, '/account/verification', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'url' => 'http://localhost/verification',
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(201, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
$webhook = $this->getLastRequest();
$signatureKey = $this->getProject()['signatureKey'];
$payload = json_encode($webhook['data']);
$url = $webhook['url'];
$signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true));
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide()));
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertNotEmpty($webhook['data']['userId']);
$this->assertNotEmpty($webhook['data']['secret']);
$this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire']));
$data['secret'] = $webhook['data']['secret'];
return $data;
}
/**
* @depends testCreateAccountVerification
*/
public function testUpdateAccountVerification($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$session = $data['session'] ?? '';
$secret = $data['secret'] ?? '';
$verification = $this->client->call(Client::METHOD_PUT, '/account/verification', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'userId' => $id,
'secret' => $secret,
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(200, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
$webhook = $this->getLastRequest();
$signatureKey = $this->getProject()['signatureKey'];
$payload = json_encode($webhook['data']);
$url = $webhook['url'];
$signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true));
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide()));
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertNotEmpty($webhook['data']['userId']);
$this->assertNotEmpty($webhook['data']['secret']);
$this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire']));
$data['secret'] = $webhook['data']['secret'];
return $data;
}
/**
* @depends testUpdateAccountPrefs
*/
@ -751,120 +865,6 @@ class WebhooksCustomClientTest extends Scope
return $data;
}
/**
* @depends testUpdateAccountPrefs
*/
public function testCreateAccountVerification($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$session = $data['session'] ?? '';
$verification = $this->client->call(Client::METHOD_POST, '/account/verification', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'url' => 'http://localhost/verification',
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(201, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
$webhook = $this->getLastRequest();
$signatureKey = $this->getProject()['signatureKey'];
$payload = json_encode($webhook['data']);
$url = $webhook['url'];
$signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true));
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*.create', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.create", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide()));
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertNotEmpty($webhook['data']['userId']);
$this->assertNotEmpty($webhook['data']['secret']);
$this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire']));
$data['secret'] = $webhook['data']['secret'];
return $data;
}
/**
* @depends testCreateAccountVerification
*/
public function testUpdateAccountVerification($data): array
{
$id = $data['id'] ?? '';
$email = $data['email'] ?? '';
$session = $data['session'] ?? '';
$secret = $data['secret'] ?? '';
$verification = $this->client->call(Client::METHOD_PUT, '/account/verification', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
]), [
'userId' => $id,
'secret' => $secret,
]);
$verificationId = $verification['body']['$id'];
$this->assertEquals(200, $verification['headers']['status-code']);
$this->assertIsArray($verification['body']);
$webhook = $this->getLastRequest();
$signatureKey = $this->getProject()['signatureKey'];
$payload = json_encode($webhook['data']);
$url = $webhook['url'];
$signatureExpected = base64_encode(hash_hmac('sha1', $url . $payload, $signatureKey, true));
$this->assertEquals($webhook['method'], 'POST');
$this->assertEquals($webhook['headers']['Content-Type'], 'application/json');
$this->assertEquals($webhook['headers']['User-Agent'], 'Appwrite-Server vdev. Please report abuse at security@appwrite.io');
$this->assertStringContainsString('users.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString('users.*.verification.*.update', $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.*.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.*.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertStringContainsString("users.{$id}.verification.{$verificationId}.update", $webhook['headers']['X-Appwrite-Webhook-Events']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Signature'], $signatureExpected);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Id'] ?? '', $this->getProject()['webhookId']);
$this->assertEquals($webhook['headers']['X-Appwrite-Webhook-Project-Id'] ?? '', $this->getProject()['$id']);
$this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide()));
$this->assertNotEmpty($webhook['data']['$id']);
$this->assertNotEmpty($webhook['data']['userId']);
$this->assertNotEmpty($webhook['data']['secret']);
$this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire']));
$data['secret'] = $webhook['data']['secret'];
return $data;
}
/**
* @depends testCreateTeamMembership
*/