mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Update tests
This commit is contained in:
@@ -872,30 +872,36 @@ trait OAuth2Base
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Update Authentik (clientId + clientSecret + REQUIRED endpoint)
|
||||
// Update Authentik (clientId + clientSecret + optional endpoint)
|
||||
// =========================================================================
|
||||
|
||||
public function testUpdateOAuth2AuthentikRequiresEndpoint(): void
|
||||
public function testUpdateOAuth2AuthentikAllowsOmittedEndpointWhenDisabled(): void
|
||||
{
|
||||
// The `endpoint` param is required (Text(min=1)); omitting → 400.
|
||||
$response = $this->updateOAuth2('authentik', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('authentik', $response['body']['$id']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('authentik', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2AuthentikEmptyEndpointRejected(): void
|
||||
public function testUpdateOAuth2AuthentikEmptyEndpointRejectedWhenEnabling(): void
|
||||
{
|
||||
// The `endpoint` validator is Text(min=1). Sending `''` must be
|
||||
// rejected the same way as omitting — the validator should treat the
|
||||
// empty-string degenerate case as a missing required field.
|
||||
$response = $this->updateOAuth2('authentik', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'endpoint' => '',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
@@ -920,15 +926,14 @@ trait OAuth2Base
|
||||
$this->updateOAuth2('authentik', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.authentik.com',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2AuthentikPartialPreservesSecret(): void
|
||||
{
|
||||
// Authentik's `endpoint` is required on every call, so we always
|
||||
// re-send it. The `clientSecret` lives in the JSON blob and must
|
||||
// The `clientSecret` and `endpoint` live in the JSON blob and must
|
||||
// survive when omitted on a subsequent call that only changes clientId.
|
||||
$this->updateOAuth2('authentik', [
|
||||
'clientId' => 'authentik-merge-client',
|
||||
@@ -939,27 +944,24 @@ trait OAuth2Base
|
||||
|
||||
$response = $this->updateOAuth2('authentik', [
|
||||
'clientId' => 'authentik-rotated-client',
|
||||
'endpoint' => 'merge.authentik.com',
|
||||
]);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('authentik-rotated-client', $response['body']['clientId']);
|
||||
$this->assertSame('merge.authentik.com', $response['body']['endpoint']);
|
||||
|
||||
// Confirm clientSecret survived the omitted-field merge by enabling
|
||||
// — Authentik has no verifyCredentials() hook, so non-empty stored
|
||||
// secret is enough. `endpoint` must be re-sent (required on enable too).
|
||||
// without re-sending endpoint.
|
||||
$enable = $this->updateOAuth2('authentik', [
|
||||
'endpoint' => 'merge.authentik.com',
|
||||
'enabled' => true,
|
||||
]);
|
||||
$this->assertSame(200, $enable['headers']['status-code']);
|
||||
$this->assertTrue($enable['body']['enabled']);
|
||||
|
||||
// Cleanup — endpoint is required, use a placeholder.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('authentik', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.authentik.com',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -984,40 +986,46 @@ trait OAuth2Base
|
||||
$this->assertSame('enable.authentik.com', $get['body']['endpoint']);
|
||||
$this->assertSame('', $get['body']['clientSecret']);
|
||||
|
||||
// Cleanup — endpoint is required (Text(min=1)) so use a placeholder.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('authentik', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.authentik.com',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Update FusionAuth (clientId + clientSecret + REQUIRED endpoint)
|
||||
// Update FusionAuth (clientId + clientSecret + optional endpoint)
|
||||
// =========================================================================
|
||||
|
||||
public function testUpdateOAuth2FusionAuthRequiresEndpoint(): void
|
||||
public function testUpdateOAuth2FusionAuthAllowsOmittedEndpointWhenDisabled(): void
|
||||
{
|
||||
// The `endpoint` param is required (Text(min=1)); omitting → 400.
|
||||
$response = $this->updateOAuth2('fusionauth', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('fusionauth', $response['body']['$id']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('fusionauth', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2FusionAuthEmptyEndpointRejected(): void
|
||||
public function testUpdateOAuth2FusionAuthEmptyEndpointRejectedWhenEnabling(): void
|
||||
{
|
||||
// The `endpoint` validator is Text(min=1). Sending `''` must be
|
||||
// rejected the same way as omitting — the validator should treat the
|
||||
// empty-string degenerate case as a missing required field.
|
||||
$response = $this->updateOAuth2('fusionauth', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'endpoint' => '',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
@@ -1042,15 +1050,14 @@ trait OAuth2Base
|
||||
$this->updateOAuth2('fusionauth', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.fusionauth.io',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2FusionAuthPartialPreservesSecret(): void
|
||||
{
|
||||
// FusionAuth's `endpoint` is required on every call, so we always
|
||||
// re-send it. The `clientSecret` lives in the JSON blob and must
|
||||
// The `clientSecret` and `endpoint` live in the JSON blob and must
|
||||
// survive when omitted on a subsequent call that only changes clientId.
|
||||
$this->updateOAuth2('fusionauth', [
|
||||
'clientId' => 'fusionauth-merge-client',
|
||||
@@ -1061,27 +1068,24 @@ trait OAuth2Base
|
||||
|
||||
$response = $this->updateOAuth2('fusionauth', [
|
||||
'clientId' => 'fusionauth-rotated-client',
|
||||
'endpoint' => 'merge.fusionauth.io',
|
||||
]);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('fusionauth-rotated-client', $response['body']['clientId']);
|
||||
$this->assertSame('merge.fusionauth.io', $response['body']['endpoint']);
|
||||
|
||||
// Confirm clientSecret survived the omitted-field merge by enabling
|
||||
// — FusionAuth has no verifyCredentials() hook, so non-empty stored
|
||||
// secret is enough. `endpoint` must be re-sent (required on enable too).
|
||||
// without re-sending endpoint.
|
||||
$enable = $this->updateOAuth2('fusionauth', [
|
||||
'endpoint' => 'merge.fusionauth.io',
|
||||
'enabled' => true,
|
||||
]);
|
||||
$this->assertSame(200, $enable['headers']['status-code']);
|
||||
$this->assertTrue($enable['body']['enabled']);
|
||||
|
||||
// Cleanup — endpoint is required, use a placeholder.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('fusionauth', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.fusionauth.io',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -1106,70 +1110,85 @@ trait OAuth2Base
|
||||
$this->assertSame('enable.fusionauth.io', $get['body']['endpoint']);
|
||||
$this->assertSame('', $get['body']['clientSecret']);
|
||||
|
||||
// Cleanup — endpoint is required (Text(min=1)) so use a placeholder.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('fusionauth', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.fusionauth.io',
|
||||
'endpoint' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Update Keycloak (clientId + clientSecret + REQUIRED endpoint + REQUIRED realmName)
|
||||
// Update Keycloak (clientId + clientSecret + optional endpoint + optional realmName)
|
||||
// =========================================================================
|
||||
|
||||
public function testUpdateOAuth2KeycloakRequiresEndpoint(): void
|
||||
public function testUpdateOAuth2KeycloakAllowsOmittedEndpointWhenDisabled(): void
|
||||
{
|
||||
// The `endpoint` param is required (Text(min=1)); omitting → 400.
|
||||
$response = $this->updateOAuth2('keycloak', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'realmName' => 'appwrite-realm',
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('keycloak', $response['body']['$id']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('keycloak', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => '',
|
||||
'realmName' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2KeycloakEmptyEndpointRejected(): void
|
||||
public function testUpdateOAuth2KeycloakEmptyEndpointRejectedWhenEnabling(): void
|
||||
{
|
||||
// The `endpoint` validator is Text(min=1). Sending `''` must be
|
||||
// rejected the same way as omitting — the validator should treat the
|
||||
// empty-string degenerate case as a missing required field.
|
||||
$response = $this->updateOAuth2('keycloak', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'endpoint' => '',
|
||||
'realmName' => 'appwrite-realm',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2KeycloakRequiresRealmName(): void
|
||||
public function testUpdateOAuth2KeycloakAllowsOmittedRealmNameWhenDisabled(): void
|
||||
{
|
||||
// The `realmName` param is required (Text(min=1)); omitting → 400.
|
||||
$response = $this->updateOAuth2('keycloak', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'endpoint' => 'keycloak.example.com',
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('keycloak', $response['body']['$id']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('keycloak', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => '',
|
||||
'realmName' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2KeycloakEmptyRealmNameRejected(): void
|
||||
public function testUpdateOAuth2KeycloakEmptyRealmNameRejectedWhenEnabling(): void
|
||||
{
|
||||
// The `realmName` validator is Text(min=1). Sending `''` must be
|
||||
// rejected the same way as omitting.
|
||||
$response = $this->updateOAuth2('keycloak', [
|
||||
'clientId' => 'whatever',
|
||||
'clientSecret' => 'whatever',
|
||||
'endpoint' => 'keycloak.example.com',
|
||||
'realmName' => '',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
@@ -1196,16 +1215,15 @@ trait OAuth2Base
|
||||
$this->updateOAuth2('keycloak', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.keycloak.com',
|
||||
'realmName' => 'cleanup-realm',
|
||||
'endpoint' => '',
|
||||
'realmName' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2KeycloakPartialPreservesSecret(): void
|
||||
{
|
||||
// Keycloak's `endpoint` and `realmName` are required on every call,
|
||||
// so we always re-send them. The `clientSecret` lives in the JSON
|
||||
// The `clientSecret`, `endpoint`, and `realmName` live in the JSON
|
||||
// blob and must survive when omitted on a subsequent call that only
|
||||
// changes clientId.
|
||||
$this->updateOAuth2('keycloak', [
|
||||
@@ -1218,8 +1236,6 @@ trait OAuth2Base
|
||||
|
||||
$response = $this->updateOAuth2('keycloak', [
|
||||
'clientId' => 'keycloak-rotated-client',
|
||||
'endpoint' => 'merge.keycloak.com',
|
||||
'realmName' => 'merge-realm',
|
||||
]);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('keycloak-rotated-client', $response['body']['clientId']);
|
||||
@@ -1227,23 +1243,19 @@ trait OAuth2Base
|
||||
$this->assertSame('merge-realm', $response['body']['realmName']);
|
||||
|
||||
// Confirm clientSecret survived the omitted-field merge by enabling
|
||||
// — Keycloak has no verifyCredentials() hook, so non-empty stored
|
||||
// secret is enough. `endpoint`/`realmName` must be re-sent (required
|
||||
// on enable too).
|
||||
// without re-sending endpoint or realmName.
|
||||
$enable = $this->updateOAuth2('keycloak', [
|
||||
'endpoint' => 'merge.keycloak.com',
|
||||
'realmName' => 'merge-realm',
|
||||
'enabled' => true,
|
||||
]);
|
||||
$this->assertSame(200, $enable['headers']['status-code']);
|
||||
$this->assertTrue($enable['body']['enabled']);
|
||||
|
||||
// Cleanup — endpoint and realmName are required, use placeholders.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('keycloak', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.keycloak.com',
|
||||
'realmName' => 'cleanup-realm',
|
||||
'endpoint' => '',
|
||||
'realmName' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -1270,40 +1282,47 @@ trait OAuth2Base
|
||||
$this->assertSame('enable-realm', $get['body']['realmName']);
|
||||
$this->assertSame('', $get['body']['clientSecret']);
|
||||
|
||||
// Cleanup — endpoint and realmName are required (Text(min=1)) so use placeholders.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('keycloak', [
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'endpoint' => 'cleanup.keycloak.com',
|
||||
'realmName' => 'cleanup-realm',
|
||||
'endpoint' => '',
|
||||
'realmName' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Update Microsoft (applicationId + applicationSecret + REQUIRED tenant)
|
||||
// Update Microsoft (applicationId + applicationSecret + optional tenant)
|
||||
// =========================================================================
|
||||
|
||||
public function testUpdateOAuth2MicrosoftRequiresTenant(): void
|
||||
public function testUpdateOAuth2MicrosoftAllowsOmittedTenantWhenDisabled(): void
|
||||
{
|
||||
$response = $this->updateOAuth2('microsoft', [
|
||||
'applicationId' => 'whatever',
|
||||
'applicationSecret' => 'whatever',
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
$this->assertSame('general_argument_invalid', $response['body']['type']);
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('microsoft', $response['body']['$id']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('microsoft', [
|
||||
'applicationId' => '',
|
||||
'applicationSecret' => '',
|
||||
'tenant' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpdateOAuth2MicrosoftEmptyTenantRejected(): void
|
||||
public function testUpdateOAuth2MicrosoftEmptyTenantRejectedWhenEnabling(): void
|
||||
{
|
||||
// The `tenant` validator is Text(min=1). Sending `''` must be rejected
|
||||
// the same way as omitting — the validator should treat the empty
|
||||
// string as a missing required field.
|
||||
$response = $this->updateOAuth2('microsoft', [
|
||||
'applicationId' => 'whatever',
|
||||
'applicationSecret' => 'whatever',
|
||||
'tenant' => '',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(400, $response['headers']['status-code']);
|
||||
@@ -1331,7 +1350,7 @@ trait OAuth2Base
|
||||
$this->updateOAuth2('microsoft', [
|
||||
'applicationId' => '',
|
||||
'applicationSecret' => '',
|
||||
'tenant' => 'common',
|
||||
'tenant' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -1346,23 +1365,21 @@ trait OAuth2Base
|
||||
'enabled' => false,
|
||||
]);
|
||||
|
||||
// Patch with only `tenant` (it's required on every call) and a new
|
||||
// applicationId, leaving applicationSecret omitted. The stored secret
|
||||
// must not be wiped.
|
||||
// Patch with only a new applicationId, leaving applicationSecret and
|
||||
// tenant omitted. The stored JSON values must not be wiped.
|
||||
$response = $this->updateOAuth2('microsoft', [
|
||||
'applicationId' => 'updated-app-id',
|
||||
'tenant' => 'organizations',
|
||||
]);
|
||||
|
||||
$this->assertSame(200, $response['headers']['status-code']);
|
||||
$this->assertSame('updated-app-id', $response['body']['applicationId']);
|
||||
$this->assertSame('organizations', $response['body']['tenant']);
|
||||
$this->assertSame('common', $response['body']['tenant']);
|
||||
|
||||
// Cleanup
|
||||
$this->updateOAuth2('microsoft', [
|
||||
'applicationId' => '',
|
||||
'applicationSecret' => '',
|
||||
'tenant' => 'common',
|
||||
'tenant' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -1387,11 +1404,11 @@ trait OAuth2Base
|
||||
$this->assertSame('common', $get['body']['tenant']);
|
||||
$this->assertSame('', $get['body']['applicationSecret']);
|
||||
|
||||
// Cleanup — tenant is required (Text(min=1)) so use a placeholder.
|
||||
// Cleanup
|
||||
$this->updateOAuth2('microsoft', [
|
||||
'applicationId' => '',
|
||||
'applicationSecret' => '',
|
||||
'tenant' => 'common',
|
||||
'tenant' => '',
|
||||
'enabled' => false,
|
||||
]);
|
||||
}
|
||||
@@ -2401,8 +2418,9 @@ trait OAuth2Base
|
||||
//
|
||||
// Ensures each provider's Update endpoint is wired up correctly: routing,
|
||||
// provider class, response model and `$id`. Custom-shaped providers
|
||||
// (apple, auth0, authentik, gitlab, microsoft, oidc, okta, dropbox) and
|
||||
// sandboxes (paypalSandbox, tradeshiftSandbox) have dedicated tests above.
|
||||
// (apple, auth0, authentik, fusionauth, gitlab, keycloak, microsoft, oidc,
|
||||
// okta, dropbox) and sandboxes (paypalSandbox, tradeshiftSandbox) have
|
||||
// dedicated tests above.
|
||||
// Github is excluded because its `verifyCredentials()` hook is exercised
|
||||
// separately.
|
||||
// =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user