Merge remote-tracking branch 'origin/0.16.x' into datetime-attributes-merge
# Conflicts: # app/controllers/api/account.php # app/controllers/api/databases.php # app/controllers/api/functions.php # app/controllers/api/projects.php # app/controllers/api/storage.php # app/controllers/api/teams.php # app/controllers/api/users.php # app/controllers/general.php # app/controllers/shared/api.php
This commit is contained in:
commit
fb34ecfa7d
|
@ -102,7 +102,7 @@ return [
|
|||
],
|
||||
Exception::USER_ALREADY_EXISTS => [
|
||||
'name' => Exception::USER_ALREADY_EXISTS,
|
||||
'description' => 'A user with the same email ID already exists in your project.',
|
||||
'description' => 'A user with the same email already exists in your project.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::USER_BLOCKED => [
|
||||
|
@ -122,12 +122,12 @@ return [
|
|||
],
|
||||
Exception::USER_EMAIL_NOT_WHITELISTED => [
|
||||
'name' => Exception::USER_EMAIL_NOT_WHITELISTED,
|
||||
'description' => 'The user\'s email is not part of the whitelist. Please check the _APP_CONSOLE_WHITELIST_EMAILS environment variable of your Appwrite server.',
|
||||
'description' => 'Console registration is restricted to specific emails. Contact your administrator for more information.',
|
||||
'code' => 401,
|
||||
],
|
||||
Exception::USER_IP_NOT_WHITELISTED => [
|
||||
'name' => Exception::USER_IP_NOT_WHITELISTED,
|
||||
'description' => 'The user\'s IP address is not part of the whitelist. Please check the _APP_CONSOLE_WHITELIST_IPS environment variable of your Appwrite server.',
|
||||
'description' => 'Console registration is restricted to specific IPs. Contact your administrator for more information.',
|
||||
'code' => 401,
|
||||
],
|
||||
Exception::USER_INVALID_CREDENTIALS => [
|
||||
|
@ -152,7 +152,7 @@ return [
|
|||
],
|
||||
Exception::USER_EMAIL_ALREADY_EXISTS => [
|
||||
'name' => Exception::USER_EMAIL_ALREADY_EXISTS,
|
||||
'description' => 'Another user with the same email already exists in the current project.',
|
||||
'description' => 'A user with the same email already exists in the current project.',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::USER_PASSWORD_MISMATCH => [
|
||||
|
@ -185,6 +185,11 @@ return [
|
|||
'description' => 'The current user does not have a phone number associated with their account.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::USER_MISSING_ID => [
|
||||
'name' => Exception::USER_MISSING_ID,
|
||||
'description' => 'Missing ID from OAuth2 provider.',
|
||||
'code' => 400,
|
||||
],
|
||||
|
||||
/** Teams */
|
||||
Exception::TEAM_NOT_FOUND => [
|
||||
|
@ -194,7 +199,7 @@ return [
|
|||
],
|
||||
Exception::TEAM_INVITE_ALREADY_EXISTS => [
|
||||
'name' => Exception::TEAM_INVITE_ALREADY_EXISTS,
|
||||
'description' => 'The current user has already received an invitation to join the team.',
|
||||
'description' => 'User has already been invited or is already a member of this team',
|
||||
'code' => 409,
|
||||
],
|
||||
Exception::TEAM_INVITE_NOT_FOUND => [
|
||||
|
@ -218,13 +223,17 @@ return [
|
|||
'code' => 401,
|
||||
],
|
||||
|
||||
|
||||
/** Membership */
|
||||
Exception::MEMBERSHIP_NOT_FOUND => [
|
||||
'name' => Exception::MEMBERSHIP_NOT_FOUND,
|
||||
'description' => 'Membership with the requested ID could not be found.',
|
||||
'code' => 404,
|
||||
],
|
||||
Exception::MEMBERSHIP_ALREADY_CONFIRMED => [
|
||||
'name' => Exception::MEMBERSHIP_ALREADY_CONFIRMED,
|
||||
'description' => 'Membership already confirmed',
|
||||
'code' => 409,
|
||||
],
|
||||
|
||||
/** Avatars */
|
||||
Exception::AVATAR_SET_NOT_FOUND => [
|
||||
|
@ -271,7 +280,7 @@ return [
|
|||
],
|
||||
Exception::STORAGE_FILE_TYPE_UNSUPPORTED => [
|
||||
'name' => Exception::STORAGE_FILE_TYPE_UNSUPPORTED,
|
||||
'description' => 'The file type is not supported.',
|
||||
'description' => 'The given file extension is not supported.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::STORAGE_INVALID_FILE_SIZE => [
|
||||
|
@ -325,7 +334,7 @@ return [
|
|||
],
|
||||
Exception::BUILD_NOT_READY => [
|
||||
'name' => Exception::BUILD_NOT_READY,
|
||||
'description' => 'Build with the requested ID is builing and not ready for execution.',
|
||||
'description' => 'Build with the requested ID is building and not ready for execution.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::BUILD_IN_PROGRESS => [
|
||||
|
@ -348,6 +357,19 @@ return [
|
|||
'code' => 404,
|
||||
],
|
||||
|
||||
/** Databases */
|
||||
Exception::DATABASE_NOT_FOUND => [
|
||||
'name' => Exception::DATABASE_NOT_FOUND,
|
||||
'description' => 'Database not found',
|
||||
'code' => 404
|
||||
],
|
||||
|
||||
Exception::DATABASE_ALREADY_EXISTS => [
|
||||
'name' => Exception::DATABASE_ALREADY_EXISTS,
|
||||
'description' => 'Database already exists',
|
||||
'code' => 409
|
||||
],
|
||||
|
||||
/** Collections */
|
||||
Exception::COLLECTION_NOT_FOUND => [
|
||||
'name' => Exception::COLLECTION_NOT_FOUND,
|
||||
|
@ -469,19 +491,24 @@ return [
|
|||
],
|
||||
Exception::PROJECT_INVALID_SUCCESS_URL => [
|
||||
'name' => Exception::PROJECT_INVALID_SUCCESS_URL,
|
||||
'description' => 'Invalid URL received for OAuth success redirect.',
|
||||
'description' => 'Invalid redirect URL for OAuth success.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::PROJECT_INVALID_FAILURE_URL => [
|
||||
'name' => Exception::PROJECT_INVALID_FAILURE_URL,
|
||||
'description' => 'Invalid URL received for OAuth failure redirect.',
|
||||
'description' => 'Invalid redirect URL for OAuth failure.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::PROJECT_MISSING_USER_ID => [
|
||||
'name' => Exception::PROJECT_MISSING_USER_ID,
|
||||
'description' => 'Failed to obtain user ID from the OAuth provider.',
|
||||
Exception::PROJECT_RESERVED_PROJECT => [
|
||||
'name' => Exception::PROJECT_RESERVED_PROJECT,
|
||||
'description' => 'The project ID is reserved. Please choose another project ID.',
|
||||
'code' => 400,
|
||||
],
|
||||
Exception::PROJECT_KEY_EXPIRED => [
|
||||
'name' => Exception::PROJECT_KEY_EXPIRED,
|
||||
'description' => 'The project key has expired. Please generate a new key using the Appwrite console.',
|
||||
'code' => 401,
|
||||
],
|
||||
Exception::WEBHOOK_NOT_FOUND => [
|
||||
'name' => Exception::WEBHOOK_NOT_FOUND,
|
||||
'description' => 'Webhook with the requested ID could not be found.',
|
||||
|
@ -511,5 +538,5 @@ return [
|
|||
'name' => Exception::DOMAIN_VERIFICATION_FAILED,
|
||||
'description' => 'Domain verification for the requested domain has failed.',
|
||||
'code' => 401,
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
|
@ -75,11 +75,11 @@ App::post('/v1/account')
|
|||
$whitelistIPs = $project->getAttribute('authWhitelistIPs');
|
||||
|
||||
if (!empty($whitelistEmails) && !\in_array($email, $whitelistEmails)) {
|
||||
throw new Exception('Console registration is restricted to specific emails. Contact your administrator for more information.', 401, Exception::USER_EMAIL_NOT_WHITELISTED);
|
||||
throw new Exception(Exception::USER_EMAIL_NOT_WHITELISTED);
|
||||
}
|
||||
|
||||
if (!empty($whitelistIPs) && !\in_array($request->getIP(), $whitelistIPs)) {
|
||||
throw new Exception('Console registration is restricted to specific IPs. Contact your administrator for more information.', 401, Exception::USER_IP_NOT_WHITELISTED);
|
||||
throw new Exception(Exception::USER_IP_NOT_WHITELISTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ App::post('/v1/account')
|
|||
$total = $dbForProject->count('users', max: APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ App::post('/v1/account')
|
|||
'search' => implode(' ', [$userId, $email, $name])
|
||||
])));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Account already exists', 409, Exception::USER_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
Authorization::unsetRole('role:' . Auth::USER_ROLE_GUEST);
|
||||
|
@ -169,11 +169,11 @@ App::post('/v1/account/sessions/email')
|
|||
]);
|
||||
|
||||
if (!$profile || !Auth::passwordVerify($password, $profile->getAttribute('password'))) {
|
||||
throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS); // Wrong password or username
|
||||
throw new Exception(Exception::USER_INVALID_CREDENTIALS); // Wrong password or username
|
||||
}
|
||||
|
||||
if (false === $profile->getAttribute('status')) { // Account is blocked
|
||||
throw new Exception('Invalid credentials. User is blocked', 401, Exception::USER_BLOCKED); // User is in status blocked
|
||||
throw new Exception(Exception::USER_BLOCKED); // User is in status blocked
|
||||
}
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
|
@ -278,13 +278,13 @@ App::get('/v1/account/sessions/oauth2/:provider')
|
|||
}
|
||||
|
||||
if (empty($appId) || empty($appSecret)) {
|
||||
throw new Exception('This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.', 412, Exception::PROJECT_PROVIDER_DISABLED);
|
||||
throw new Exception(Exception::PROJECT_PROVIDER_DISABLED, 'This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.');
|
||||
}
|
||||
|
||||
$className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
|
||||
|
||||
if (!\class_exists($className)) {
|
||||
throw new Exception('Provider is not supported', 501, Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (empty($success)) {
|
||||
|
@ -390,7 +390,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
|
||||
|
||||
if (!\class_exists($className)) {
|
||||
throw new Exception('Provider is not supported', 501, Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
}
|
||||
|
||||
$oauth2 = new $className($appId, $appSecret, $callback);
|
||||
|
@ -399,18 +399,18 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
try {
|
||||
$state = \array_merge($defaultState, $oauth2->parseState($state));
|
||||
} catch (\Exception$exception) {
|
||||
throw new Exception('Failed to parse login state params as passed from OAuth2 provider', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to parse login state params as passed from OAuth2 provider');
|
||||
}
|
||||
} else {
|
||||
$state = $defaultState;
|
||||
}
|
||||
|
||||
if (!$validateURL->isValid($state['success'])) {
|
||||
throw new Exception('Invalid redirect URL for success login', 400, Exception::PROJECT_INVALID_SUCCESS_URL);
|
||||
throw new Exception(Exception::PROJECT_INVALID_SUCCESS_URL);
|
||||
}
|
||||
|
||||
if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) {
|
||||
throw new Exception('Invalid redirect URL for failure login', 400, Exception::PROJECT_INVALID_FAILURE_URL);
|
||||
throw new Exception(Exception::PROJECT_INVALID_FAILURE_URL);
|
||||
}
|
||||
|
||||
$state['failure'] = null;
|
||||
|
@ -424,7 +424,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$response->redirect($state['failure'], 301, 0);
|
||||
}
|
||||
|
||||
throw new Exception('Failed to obtain access token', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to obtain access token');
|
||||
}
|
||||
|
||||
$oauth2ID = $oauth2->getUserID($accessToken);
|
||||
|
@ -434,7 +434,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$response->redirect($state['failure'], 301, 0);
|
||||
}
|
||||
|
||||
throw new Exception('Missing ID from OAuth2 provider', 400, Exception::PROJECT_MISSING_USER_ID);
|
||||
throw new Exception(Exception::USER_MISSING_ID);
|
||||
}
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
@ -473,7 +473,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$total = $dbForProject->count('users', max: APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,13 +498,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
'search' => implode(' ', [$userId, $email, $name])
|
||||
])));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Account already exists', 409, Exception::USER_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $user->getAttribute('status')) { // Account is blocked
|
||||
throw new Exception('Invalid credentials. User is blocked', 401, Exception::USER_BLOCKED); // User is in status blocked
|
||||
throw new Exception(Exception::USER_BLOCKED); // User is in status blocked
|
||||
}
|
||||
|
||||
// Create session token, verify user account and update OAuth2 ID and Access Token
|
||||
|
@ -623,7 +623,7 @@ App::post('/v1/account/sessions/magic-url')
|
|||
->action(function (string $userId, string $email, string $url, Request $request, Response $response, Document $project, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails) {
|
||||
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP disabled');
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
|
@ -639,7 +639,7 @@ App::post('/v1/account/sessions/magic-url')
|
|||
$total = $dbForProject->count('users', max: APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,13 +753,13 @@ App::put('/v1/account/sessions/magic-url')
|
|||
$user = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$token = Auth::tokenVerify($user->getAttribute('tokens', []), Auth::TOKEN_TYPE_MAGIC_URL, $secret);
|
||||
|
||||
if (!$token) {
|
||||
throw new Exception('Invalid login token', 401, Exception::USER_INVALID_TOKEN);
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
|
@ -806,7 +806,7 @@ App::put('/v1/account/sessions/magic-url')
|
|||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed saving user to DB');
|
||||
}
|
||||
|
||||
$audits->setResource('user/' . $user->getId());
|
||||
|
@ -864,7 +864,7 @@ App::post('/v1/account/sessions/phone')
|
|||
->inject('phone')
|
||||
->action(function (string $userId, string $number, Request $request, Response $response, Document $project, Database $dbForProject, Audit $audits, Event $events, EventPhone $messaging, Phone $phone) {
|
||||
if (empty(App::getEnv('_APP_PHONE_PROVIDER'))) {
|
||||
throw new Exception('Phone provider not configured', 503, Exception::GENERAL_PHONE_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
|
@ -880,7 +880,7 @@ App::post('/v1/account/sessions/phone')
|
|||
$total = $dbForProject->count('users', max: APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -983,13 +983,13 @@ App::put('/v1/account/sessions/phone')
|
|||
$user = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$token = Auth::phoneTokenVerify($user->getAttribute('tokens', []), $secret);
|
||||
|
||||
if (!$token) {
|
||||
throw new Exception('Invalid login token', 401, Exception::USER_INVALID_TOKEN);
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
|
@ -1034,7 +1034,7 @@ App::put('/v1/account/sessions/phone')
|
|||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
|
||||
if (false === $user) {
|
||||
throw new Exception('Failed saving user to DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed saving user to DB');
|
||||
}
|
||||
|
||||
$audits->setResource('user/' . $user->getId());
|
||||
|
@ -1096,11 +1096,11 @@ App::post('/v1/account/sessions/anonymous')
|
|||
$protocol = $request->getProtocol();
|
||||
|
||||
if ('console' === $project->getId()) {
|
||||
throw new Exception('Failed to create anonymous user.', 401, Exception::USER_ANONYMOUS_CONSOLE_PROHIBITED);
|
||||
throw new Exception(Exception::USER_ANONYMOUS_CONSOLE_PROHIBITED, 'Failed to create anonymous user');
|
||||
}
|
||||
|
||||
if (!$user->isEmpty()) {
|
||||
throw new Exception('Cannot create an anonymous user when logged in.', 401, Exception::USER_SESSION_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_SESSION_ALREADY_EXISTS, 'Cannot create an anonymous user when logged in');
|
||||
}
|
||||
|
||||
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
|
||||
|
@ -1109,7 +1109,7 @@ App::post('/v1/account/sessions/anonymous')
|
|||
$total = $dbForProject->count('users', max: APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1227,7 @@ App::post('/v1/account/jwt')
|
|||
}
|
||||
|
||||
if ($current->isEmpty()) {
|
||||
throw new Exception('No valid session found', 404, Exception::USER_SESSION_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_SESSION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
|
||||
|
@ -1422,7 +1422,7 @@ App::get('/v1/account/sessions/:sessionId')
|
|||
}
|
||||
}
|
||||
|
||||
throw new Exception('Session not found', 404, Exception::USER_SESSION_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_SESSION_NOT_FOUND);
|
||||
});
|
||||
|
||||
App::patch('/v1/account/name')
|
||||
|
@ -1484,8 +1484,8 @@ App::patch('/v1/account/password')
|
|||
->action(function (string $password, string $oldPassword, Response $response, Document $user, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
|
||||
|
||||
// Check old password only if its an existing user.
|
||||
if ($user->getAttribute('passwordUpdate') !== null && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS);
|
||||
if ($user->getAttribute('passwordUpdate') !== 0 && !Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
|
||||
throw new Exception(Exception::USER_INVALID_CREDENTIALS);
|
||||
}
|
||||
|
||||
$user = $dbForProject->updateDocument(
|
||||
|
@ -1535,7 +1535,7 @@ App::patch('/v1/account/email')
|
|||
!$isAnonymousUser &&
|
||||
!Auth::passwordVerify($password, $user->getAttribute('password'))
|
||||
) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS);
|
||||
throw new Exception(Exception::USER_INVALID_CREDENTIALS);
|
||||
}
|
||||
|
||||
$email = \strtolower($email);
|
||||
|
@ -1549,7 +1549,7 @@ App::patch('/v1/account/email')
|
|||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Email already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -1591,7 +1591,7 @@ App::patch('/v1/account/phone')
|
|||
!$isAnonymousUser &&
|
||||
!Auth::passwordVerify($password, $user->getAttribute('password'))
|
||||
) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS);
|
||||
throw new Exception(Exception::USER_INVALID_CREDENTIALS);
|
||||
}
|
||||
|
||||
$user
|
||||
|
@ -1602,7 +1602,7 @@ App::patch('/v1/account/phone')
|
|||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Phone number already exists', 409, Exception::USER_PHONE_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_PHONE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -1760,7 +1760,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
|||
}
|
||||
}
|
||||
|
||||
throw new Exception('Session not found', 404, Exception::USER_SESSION_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_SESSION_NOT_FOUND);
|
||||
});
|
||||
|
||||
App::patch('/v1/account/sessions/:sessionId')
|
||||
|
@ -1814,7 +1814,7 @@ App::patch('/v1/account/sessions/:sessionId')
|
|||
$className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
|
||||
|
||||
if (!\class_exists($className)) {
|
||||
throw new Exception('Provider is not supported', 501, Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
throw new Exception(Exception::PROJECT_PROVIDER_UNSUPPORTED);
|
||||
}
|
||||
|
||||
$oauth2 = new $className($appId, $appSecret, '', [], []);
|
||||
|
@ -1847,7 +1847,7 @@ App::patch('/v1/account/sessions/:sessionId')
|
|||
}
|
||||
}
|
||||
|
||||
throw new Exception('Session not found', 404, Exception::USER_SESSION_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_SESSION_NOT_FOUND);
|
||||
});
|
||||
|
||||
App::delete('/v1/account/sessions')
|
||||
|
@ -1946,7 +1946,7 @@ App::post('/v1/account/recovery')
|
|||
->action(function (string $email, string $url, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Mail $mails, Audit $audits, Event $events, Stats $usage) {
|
||||
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
|
@ -1960,11 +1960,11 @@ App::post('/v1/account/recovery')
|
|||
]);
|
||||
|
||||
if (!$profile) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (false === $profile->getAttribute('status')) { // Account is blocked
|
||||
throw new Exception('Invalid credentials. User is blocked', 401, Exception::USER_BLOCKED);
|
||||
throw new Exception(Exception::USER_BLOCKED);
|
||||
}
|
||||
|
||||
$expire = DateTime::addSeconds(new \DateTime(), Auth::TOKEN_EXPIRATION_RECOVERY);
|
||||
|
@ -2048,20 +2048,20 @@ App::put('/v1/account/recovery')
|
|||
->action(function (string $userId, string $secret, string $password, string $passwordAgain, Response $response, Database $dbForProject, Audit $audits, Stats $usage, Event $events) {
|
||||
|
||||
if ($password !== $passwordAgain) {
|
||||
throw new Exception('Passwords must match', 400, Exception::USER_PASSWORD_MISMATCH);
|
||||
throw new Exception(Exception::USER_PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
$profile = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$tokens = $profile->getAttribute('tokens', []);
|
||||
$recovery = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_RECOVERY, $secret);
|
||||
|
||||
if (!$recovery) {
|
||||
throw new Exception('Invalid recovery token', 401, Exception::USER_INVALID_TOKEN);
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole('user:' . $profile->getId());
|
||||
|
@ -2120,7 +2120,7 @@ App::post('/v1/account/verification')
|
|||
->action(function (string $url, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Locale $locale, Audit $audits, Event $events, Mail $mails, Stats $usage) {
|
||||
|
||||
if (empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED, 'SMTP Disabled');
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
|
@ -2207,14 +2207,14 @@ App::put('/v1/account/verification')
|
|||
$profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$tokens = $profile->getAttribute('tokens', []);
|
||||
$verification = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_VERIFICATION, $secret);
|
||||
|
||||
if (!$verification) {
|
||||
throw new Exception('Invalid verification token', 401, Exception::USER_INVALID_TOKEN);
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole('user:' . $profile->getId());
|
||||
|
@ -2268,11 +2268,11 @@ App::post('/v1/account/verification/phone')
|
|||
->action(function (Request $request, Response $response, Phone $phone, Document $user, Database $dbForProject, Audit $audits, Event $events, Stats $usage, EventPhone $messaging) {
|
||||
|
||||
if (empty(App::getEnv('_APP_PHONE_PROVIDER'))) {
|
||||
throw new Exception('Phone provider not configured', 503, Exception::GENERAL_PHONE_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_PHONE_DISABLED, 'Phone provider not configured');
|
||||
}
|
||||
|
||||
if (empty($user->getAttribute('phone'))) {
|
||||
throw new Exception('User has no phone number.', 400, Exception::USER_PHONE_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_PHONE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$roles = Authorization::getRoles();
|
||||
|
@ -2353,13 +2353,13 @@ App::put('/v1/account/verification/phone')
|
|||
$profile = Authorization::skip(fn() => $dbForProject->getDocument('users', $userId));
|
||||
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$verification = Auth::phoneTokenVerify($user->getAttribute('tokens', []), $secret);
|
||||
|
||||
if (!$verification) {
|
||||
throw new Exception('Invalid verification token', 401, Exception::USER_INVALID_TOKEN);
|
||||
throw new Exception(Exception::USER_INVALID_TOKEN);
|
||||
}
|
||||
|
||||
Authorization::setRole('user:' . $profile->getId());
|
||||
|
|
|
@ -25,15 +25,15 @@ $avatarCallback = function (string $type, string $code, int $width, int $height,
|
|||
$set = Config::getParam('avatar-' . $type, []);
|
||||
|
||||
if (empty($set)) {
|
||||
throw new Exception('Avatar set not found', 404, Exception::AVATAR_SET_NOT_FOUND);
|
||||
throw new Exception(Exception::AVATAR_SET_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!\array_key_exists($code, $set)) {
|
||||
throw new Exception('Avatar not found', 404, Exception::AVATAR_NOT_FOUND);
|
||||
throw new Exception(Exception::AVATAR_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception('Imagick extension is missing', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
}
|
||||
|
||||
$output = 'png';
|
||||
|
@ -43,7 +43,7 @@ $avatarCallback = function (string $type, string $code, int $width, int $height,
|
|||
$type = 'png';
|
||||
|
||||
if (!\is_readable($path)) {
|
||||
throw new Exception('File not readable in ' . $path, 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'File not readable in ' . $path);
|
||||
}
|
||||
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . '/app-0')); // Limit file number or size
|
||||
|
@ -166,19 +166,19 @@ App::get('/v1/avatars/image')
|
|||
}
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception('Imagick extension is missing', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
}
|
||||
|
||||
$fetch = @\file_get_contents($url, false);
|
||||
|
||||
if (!$fetch) {
|
||||
throw new Exception('Image not found', 404, Exception::AVATAR_IMAGE_NOT_FOUND);
|
||||
throw new Exception(Exception::AVATAR_IMAGE_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$image = new Image($fetch);
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('Unable to parse image', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unable to parse image');
|
||||
}
|
||||
|
||||
$image->crop((int) $width, (int) $height);
|
||||
|
@ -232,7 +232,7 @@ App::get('/v1/avatars/favicon')
|
|||
}
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception('Imagick extension is missing', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
}
|
||||
|
||||
$curl = \curl_init();
|
||||
|
@ -254,7 +254,7 @@ App::get('/v1/avatars/favicon')
|
|||
\curl_close($curl);
|
||||
|
||||
if (!$html) {
|
||||
throw new Exception('Failed to fetch remote URL', 404, Exception::AVATAR_REMOTE_URL_FAILED);
|
||||
throw new Exception(Exception::AVATAR_REMOTE_URL_FAILED);
|
||||
}
|
||||
|
||||
$doc = new DOMDocument();
|
||||
|
@ -312,7 +312,7 @@ App::get('/v1/avatars/favicon')
|
|||
$data = @\file_get_contents($outputHref, false);
|
||||
|
||||
if (empty($data) || (\mb_substr($data, 0, 5) === '<html') || \mb_substr($data, 0, 5) === '<!doc') {
|
||||
throw new Exception('Favicon not found', 404, Exception::AVATAR_ICON_NOT_FOUND);
|
||||
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND, 'Favicon not found');
|
||||
}
|
||||
|
||||
$cache->save($key, $data);
|
||||
|
@ -327,7 +327,7 @@ App::get('/v1/avatars/favicon')
|
|||
$fetch = @\file_get_contents($outputHref, false);
|
||||
|
||||
if (!$fetch) {
|
||||
throw new Exception('Icon not found', 404, Exception::AVATAR_ICON_NOT_FOUND);
|
||||
throw new Exception(Exception::AVATAR_ICON_NOT_FOUND);
|
||||
}
|
||||
|
||||
$image = new Image($fetch);
|
||||
|
|
|
@ -69,28 +69,28 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
|||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!empty($format)) {
|
||||
if (!Structure::hasFormat($format, $type)) {
|
||||
throw new Exception("Format {$format} not available for {$type} attributes.", 400, Exception::ATTRIBUTE_FORMAT_UNSUPPORTED);
|
||||
throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, "Format {$format} not available for {$type} attributes.");
|
||||
}
|
||||
}
|
||||
|
||||
// Must throw here since dbForProject->createAttribute is performed by db worker
|
||||
if ($required && $default) {
|
||||
throw new Exception('Cannot set default value for required attribute', 400, Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED);
|
||||
throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for required attribute');
|
||||
}
|
||||
|
||||
if ($array && $default) {
|
||||
throw new Exception('Cannot set default value for array attributes', 400, Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED);
|
||||
throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes');
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -116,9 +116,9 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
|||
$dbForProject->checkAttribute($collection, $attribute);
|
||||
$attribute = $dbForProject->createDocument('attributes', $attribute);
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Attribute already exists', 409, Exception::ATTRIBUTE_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
|
||||
} catch (LimitException $exception) {
|
||||
throw new Exception('Attribute limit exceeded', 400, Exception::ATTRIBUTE_LIMIT_EXCEEDED);
|
||||
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
@ -186,7 +186,7 @@ App::post('/v1/databases')
|
|||
|
||||
$collections = Config::getParam('collections', [])['collections'] ?? [];
|
||||
if (empty($collections)) {
|
||||
throw new Exception('Collections collection is not configured.', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'The "collections" collection is not configured.');
|
||||
}
|
||||
|
||||
$attributes = [];
|
||||
|
@ -217,7 +217,7 @@ App::post('/v1/databases')
|
|||
}
|
||||
$dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes);
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception('Database already exists', 409, Exception::DATABASE_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DATABASE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -268,7 +268,7 @@ App::get('/v1/databases')
|
|||
$cursorDocument = $dbForProject->getDocument('databases', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Collection '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -302,7 +302,7 @@ App::get('/v1/databases/:databaseId')
|
|||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage->setParam('databases.read', 1);
|
||||
|
@ -333,7 +333,7 @@ App::get('/v1/databases/:databaseId/logs')
|
|||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
@ -413,7 +413,7 @@ App::put('/v1/databases/:databaseId')
|
|||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -421,9 +421,9 @@ App::put('/v1/databases/:databaseId')
|
|||
->setAttribute('name', $name)
|
||||
->setAttribute('search', implode(' ', [$databaseId, $name])));
|
||||
} catch (AuthorizationException $exception) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception('Bad structure. ' . $exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -460,11 +460,11 @@ App::delete('/v1/databases/:databaseId')
|
|||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('databases', $databaseId)) {
|
||||
throw new Exception('Failed to remove collection from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedCollection('databases' . $database->getInternalId());
|
||||
|
@ -518,7 +518,7 @@ App::post('/v1/databases/:databaseId/collections')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collectionId = $collectionId == 'unique()' ? $dbForProject->getId() : $collectionId;
|
||||
|
@ -539,9 +539,9 @@ App::post('/v1/databases/:databaseId/collections')
|
|||
|
||||
$dbForProject->createCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception('Collection already exists', 409, Exception::COLLECTION_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::COLLECTION_ALREADY_EXISTS);
|
||||
} catch (LimitException $th) {
|
||||
throw new Exception('Collection limit exceeded', 400, Exception::COLLECTION_LIMIT_EXCEEDED);
|
||||
throw new Exception(Exception::COLLECTION_LIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -589,7 +589,7 @@ App::get('/v1/databases/:databaseId/collections')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$filterQueries = [];
|
||||
|
@ -606,7 +606,7 @@ App::get('/v1/databases/:databaseId/collections')
|
|||
$cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Collection '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -644,12 +644,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -684,13 +684,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
@ -779,12 +779,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$read ??= $collection->getRead() ?? []; // By default inherit read permissions
|
||||
|
@ -800,9 +800,9 @@ App::put('/v1/databases/:databaseId/collections/:collectionId')
|
|||
->setAttribute('enabled', $enabled)
|
||||
->setAttribute('search', implode(' ', [$collectionId, $name])));
|
||||
} catch (AuthorizationException $exception) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception('Bad structure. ' . $exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Bad structure. ' . $exception->getMessage());
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -847,17 +847,17 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) {
|
||||
throw new Exception('Failed to remove collection from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
@ -917,7 +917,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string
|
|||
// Ensure attribute default is within required size
|
||||
$validator = new Text($size);
|
||||
if (!is_null($default) && !$validator->isValid($default)) {
|
||||
throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$attribute = createAttribute($databaseId, $collectionId, new Document([
|
||||
|
@ -1007,13 +1007,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum')
|
|||
foreach ($elements as $element) {
|
||||
$length = \strlen($element);
|
||||
if ($length === 0) {
|
||||
throw new Exception('Each enum element must not be empty', 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Each enum element must not be empty');
|
||||
}
|
||||
$size = ($length > $size) ? $length : $size;
|
||||
}
|
||||
|
||||
if (!is_null($default) && !in_array($default, $elements)) {
|
||||
throw new Exception('Default value not found in elements', 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Default value not found in elements');
|
||||
}
|
||||
|
||||
$attribute = createAttribute($databaseId, $collectionId, new Document([
|
||||
|
@ -1147,13 +1147,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege
|
|||
$max = (is_null($max)) ? PHP_INT_MAX : \intval($max);
|
||||
|
||||
if ($min > $max) {
|
||||
throw new Exception('Minimum value must be lesser than maximum value', 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value');
|
||||
}
|
||||
|
||||
$validator = new Range($min, $max, Database::VAR_INTEGER);
|
||||
|
||||
if (!is_null($default) && !$validator->isValid($default)) {
|
||||
throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$size = $max > 2147483647 ? 8 : 4; // Automatically create BigInt depending on max value
|
||||
|
@ -1217,7 +1217,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
|
|||
$max = (is_null($max)) ? PHP_FLOAT_MAX : \floatval($max);
|
||||
|
||||
if ($min > $max) {
|
||||
throw new Exception('Minimum value must be lesser than maximum value', 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value');
|
||||
}
|
||||
|
||||
// Ensure default value is a float
|
||||
|
@ -1228,7 +1228,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float'
|
|||
$validator = new Range($min, $max, Database::VAR_FLOAT);
|
||||
|
||||
if (!is_null($default) && !$validator->isValid($default)) {
|
||||
throw new Exception($validator->getDescription(), 400, Exception::ATTRIBUTE_VALUE_INVALID);
|
||||
throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription());
|
||||
}
|
||||
|
||||
$attribute = createAttribute($databaseId, $collectionId, new Document([
|
||||
|
@ -1361,12 +1361,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$attributes = $collection->getAttribute('attributes');
|
||||
|
@ -1413,19 +1413,19 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key);
|
||||
|
||||
if ($attribute->isEmpty()) {
|
||||
throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND);
|
||||
throw new Exception(Exception::ATTRIBUTE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Select response model based on type and format
|
||||
|
@ -1480,18 +1480,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key
|
|||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$attribute = $dbForProject->getDocument('attributes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key);
|
||||
|
||||
if ($attribute->isEmpty()) {
|
||||
throw new Exception('Attribute not found', 404, Exception::ATTRIBUTE_NOT_FOUND);
|
||||
throw new Exception(Exception::ATTRIBUTE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Only update status if removing available attribute
|
||||
|
@ -1579,12 +1579,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$count = $dbForProject->count('indexes', [
|
||||
|
@ -1595,7 +1595,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
$limit = 64 - MariaDB::getNumberOfDefaultIndexes();
|
||||
|
||||
if ($count >= $limit) {
|
||||
throw new Exception('Index limit exceeded', 400, Exception::INDEX_LIMIT_EXCEEDED);
|
||||
throw new Exception(Exception::INDEX_LIMIT_EXCEEDED, 'Index limit exceeded');
|
||||
}
|
||||
|
||||
// Convert Document[] to array of attribute metadata
|
||||
|
@ -1641,7 +1641,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
$attributeIndex = \array_search($attribute, array_column($oldAttributes, 'key'));
|
||||
|
||||
if ($attributeIndex === false) {
|
||||
throw new Exception('Unknown attribute: ' . $attribute, 400, Exception::ATTRIBUTE_UNKNOWN);
|
||||
throw new Exception(Exception::ATTRIBUTE_UNKNOWN, 'Unknown attribute: ' . $attribute);
|
||||
}
|
||||
|
||||
$attributeStatus = $oldAttributes[$attributeIndex]['status'];
|
||||
|
@ -1650,7 +1650,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
|
||||
// ensure attribute is available
|
||||
if ($attributeStatus !== 'available') {
|
||||
throw new Exception('Attribute not available: ' . $oldAttributes[$attributeIndex]['key'], 400, Exception::ATTRIBUTE_NOT_AVAILABLE);
|
||||
throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']);
|
||||
}
|
||||
|
||||
// set attribute size as index length only for strings
|
||||
|
@ -1672,7 +1672,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
'orders' => $orders,
|
||||
]));
|
||||
} catch (DuplicateException $th) {
|
||||
throw new Exception('Index already exists', 409, Exception::INDEX_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::INDEX_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
@ -1727,12 +1727,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$indexes = $collection->getAttribute('indexes');
|
||||
|
@ -1770,12 +1770,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$indexes = $collection->getAttribute('indexes');
|
||||
|
@ -1784,7 +1784,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
|
|||
$indexIndex = array_search($key, array_column($indexes, 'key'));
|
||||
|
||||
if ($indexIndex === false) {
|
||||
throw new Exception('Index not found', 404, Exception::INDEX_NOT_FOUND);
|
||||
throw new Exception(Exception::INDEX_NOT_FOUND);
|
||||
}
|
||||
|
||||
$index = new Document([\array_merge($indexes[$indexIndex], [
|
||||
|
@ -1824,18 +1824,18 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key')
|
|||
$db = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($db->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$index = $dbForProject->getDocument('indexes', $db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key);
|
||||
|
||||
if (empty($index->getId())) {
|
||||
throw new Exception('Index not found', 404, Exception::INDEX_NOT_FOUND);
|
||||
throw new Exception(Exception::INDEX_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Only update status if removing available index
|
||||
|
@ -1904,16 +1904,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
if (empty($data)) {
|
||||
throw new Exception('Missing payload', 400, Exception::DOCUMENT_MISSING_PAYLOAD);
|
||||
throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD);
|
||||
}
|
||||
|
||||
if (isset($data['$id'])) {
|
||||
throw new Exception('$id is not allowed for creating new documents, try update instead', 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, '$id is not allowed for creating new documents, try update instead');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1925,7 +1925,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
|
||||
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
|
||||
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1933,7 +1933,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($collection->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1948,13 +1948,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) {
|
||||
foreach ($data['$read'] as $read) {
|
||||
if (!Authorization::isRole($read)) {
|
||||
// TODO: Isn't this a 401: Unauthorized Error ?
|
||||
throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Read permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
foreach ($data['$write'] as $write) {
|
||||
if (!Authorization::isRole($write)) {
|
||||
throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Write permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1968,9 +1967,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
}
|
||||
$document->setAttribute('$collection', $collectionId);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$events
|
||||
|
@ -2026,7 +2025,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
/**
|
||||
* Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions.
|
||||
|
@ -2037,7 +2036,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
|
||||
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
|
||||
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2045,12 +2044,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($collection->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
$filterQueries = \array_map(function ($query) {
|
||||
return Query::parse($query);
|
||||
$query = Query::parse($query);
|
||||
|
||||
if (\count($query->getValues()) > 100) {
|
||||
throw new Exception(Exception::GENERAL_QUERY_LIMIT_EXCEEDED, "You cannot use more than 100 query values on attribute '{$query->getAttribute()}'");
|
||||
}
|
||||
|
||||
return $query;
|
||||
}, $queries);
|
||||
|
||||
$otherQueries = [];
|
||||
|
@ -2066,7 +2071,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
: $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Document '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$otherQueries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -2078,7 +2083,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents')
|
|||
$attributes = $collection->getAttribute('attributes', []);
|
||||
$validator = new QueriesValidator(new QueryValidator($attributes), $attributes, $collection->getAttribute('indexes', []), true);
|
||||
if (!$validator->isValid($allQueries)) {
|
||||
throw new Exception($validator->getDescription(), 400, Exception::GENERAL_QUERY_INVALID);
|
||||
throw new Exception(Exception::GENERAL_QUERY_INVALID, $validator->getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2132,7 +2137,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
/**
|
||||
* Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions.
|
||||
|
@ -2141,7 +2146,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
|||
|
||||
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
|
||||
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2149,7 +2154,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
|||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($collection->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2166,7 +2171,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
|||
$document->setAttribute('$collection', $collectionId);
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -2204,18 +2209,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
$collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId);
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
@ -2302,7 +2307,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
/**
|
||||
* Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions.
|
||||
|
@ -2311,7 +2316,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
|
||||
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
|
||||
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2319,7 +2324,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($collection->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$document = Authorization::skip(fn() => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId));
|
||||
|
@ -2329,17 +2334,17 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new Exception('Document not found', 404, Exception::DOCUMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||
|
||||
if (empty($data) && empty($read) && empty($write)) {
|
||||
throw new Exception('Missing payload or read/write permissions', 400, Exception::DOCUMENT_MISSING_PAYLOAD);
|
||||
throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD, 'Missing payload or read/write permissions');
|
||||
}
|
||||
|
||||
if (!\is_array($data)) {
|
||||
throw new Exception('Data param should be a valid JSON object', 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, 'Data param should be a valid JSON object');
|
||||
}
|
||||
|
||||
$data = \array_merge($document->getArrayCopy(), $data);
|
||||
|
@ -2357,14 +2362,14 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
if (!is_null($read)) {
|
||||
foreach ($data['$read'] as $read) {
|
||||
if (!Authorization::isRole($read)) {
|
||||
throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Read permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_null($write)) {
|
||||
foreach ($data['$write'] as $write) {
|
||||
if (!Authorization::isRole($write)) {
|
||||
throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Write permissions must be one of: (' . \implode(', ', $roles) . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2382,11 +2387,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum
|
|||
*/
|
||||
$document->setAttribute('$collection', $collectionId);
|
||||
} catch (AuthorizationException $exception) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
}
|
||||
|
||||
$events
|
||||
|
@ -2438,7 +2443,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
|
|||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
if ($database->isEmpty()) {
|
||||
throw new Exception('Database not found', 404, Exception::DATABASE_NOT_FOUND);
|
||||
throw new Exception(Exception::DATABASE_NOT_FOUND);
|
||||
}
|
||||
/**
|
||||
* Skip Authorization to get the collection. Needed in case of empty permissions for document level permissions.
|
||||
|
@ -2447,7 +2452,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
|
|||
|
||||
if ($collection->isEmpty() || !$collection->getAttribute('enabled')) {
|
||||
if (!($mode === APP_MODE_ADMIN && Auth::isPrivilegedUser(Authorization::getRoles()))) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2455,7 +2460,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
|
|||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($collection->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2467,7 +2472,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu
|
|||
}
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new Exception('No document found', 404, Exception::DOCUMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DOCUMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($collection->getAttribute('permission') === 'collection') {
|
||||
|
@ -2762,7 +2767,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage')
|
|||
$collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId());
|
||||
|
||||
if ($collection->isEmpty()) {
|
||||
throw new Exception('Collection not found', 404, Exception::COLLECTION_NOT_FOUND);
|
||||
throw new Exception(Exception::COLLECTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage = [];
|
||||
|
|
|
@ -122,7 +122,7 @@ App::get('/v1/functions')
|
|||
$cursorDocument = $dbForProject->getDocument('functions', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Function '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Function '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -179,7 +179,7 @@ App::get('/v1/functions/:functionId')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($function, Response::MODEL_FUNCTION);
|
||||
|
@ -204,7 +204,7 @@ App::get('/v1/functions/:functionId/usage')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage = [];
|
||||
|
@ -314,7 +314,7 @@ App::put('/v1/functions/:functionId')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$original = $function->getAttribute('schedule', '');
|
||||
|
@ -373,19 +373,19 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId')
|
|||
$build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', ''));
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception('Build not found', 404, Exception::BUILD_NOT_FOUND);
|
||||
throw new Exception(Exception::BUILD_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->getAttribute('status') !== 'ready') {
|
||||
throw new Exception('Build not ready', 400, Exception::BUILD_NOT_READY);
|
||||
throw new Exception(Exception::BUILD_NOT_READY);
|
||||
}
|
||||
|
||||
$schedule = $function->getAttribute('schedule', '');
|
||||
|
@ -434,11 +434,11 @@ App::delete('/v1/functions/:functionId')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('functions', $function->getId())) {
|
||||
throw new Exception('Failed to remove function from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove function from DB');
|
||||
}
|
||||
|
||||
$deletes
|
||||
|
@ -481,7 +481,7 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$file = $request->getFiles('code');
|
||||
|
@ -490,7 +490,7 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
$upload = new Upload();
|
||||
|
||||
if (empty($file)) {
|
||||
throw new Exception('No file sent', 400, Exception::STORAGE_FILE_EMPTY);
|
||||
throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent');
|
||||
}
|
||||
|
||||
// Make sure we handle a single file and multiple files the same way
|
||||
|
@ -499,7 +499,7 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
|
||||
|
||||
if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed
|
||||
throw new Exception('File type not allowed', 400, Exception::STORAGE_FILE_TYPE_UNSUPPORTED);
|
||||
throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED);
|
||||
}
|
||||
|
||||
$contentRange = $request->getHeader('content-range');
|
||||
|
@ -513,7 +513,7 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
$fileSize = $request->getContentRangeSize();
|
||||
$deploymentId = $request->getHeader('x-appwrite-id', $deploymentId);
|
||||
if (is_null($start) || is_null($end) || is_null($fileSize)) {
|
||||
throw new Exception('Invalid content-range header', 400, Exception::STORAGE_INVALID_CONTENT_RANGE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE);
|
||||
}
|
||||
|
||||
if ($end === $fileSize) {
|
||||
|
@ -527,11 +527,11 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
}
|
||||
|
||||
if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit
|
||||
throw new Exception('File size not allowed', 400, Exception::STORAGE_INVALID_FILE_SIZE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE);
|
||||
}
|
||||
|
||||
if (!$upload->isValid($fileTmpName)) {
|
||||
throw new Exception('Invalid file', 403, Exception::STORAGE_INVALID_FILE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_FILE);
|
||||
}
|
||||
|
||||
// Save to storage
|
||||
|
@ -552,7 +552,7 @@ App::post('/v1/functions/:functionId/deployments')
|
|||
$chunksUploaded = $deviceFunctions->upload($fileTmpName, $path, $chunk, $chunks, $metadata);
|
||||
|
||||
if (empty($chunksUploaded)) {
|
||||
throw new Exception('Failed moving file', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed moving file');
|
||||
}
|
||||
|
||||
$activate = (bool) filter_var($activate, FILTER_VALIDATE_BOOLEAN);
|
||||
|
@ -659,7 +659,7 @@ App::get('/v1/functions/:functionId/deployments')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$filterQueries = [];
|
||||
|
@ -679,7 +679,7 @@ App::get('/v1/functions/:functionId/deployments')
|
|||
$cursorDocument = $dbForProject->getDocument('deployments', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Tag '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Tag '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -721,17 +721,17 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId')
|
|||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($deployment, Response::MODEL_DEPLOYMENT);
|
||||
|
@ -760,21 +760,21 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId')
|
|||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deviceFunctions->delete($deployment->getAttribute('path', ''))) {
|
||||
if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) {
|
||||
throw new Exception('Failed to remove deployment from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove deployment from DB');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -826,7 +826,7 @@ App::post('/v1/functions/:functionId/executions')
|
|||
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$runtimes = Config::getParam('runtimes', []);
|
||||
|
@ -834,33 +834,33 @@ App::post('/v1/functions/:functionId/executions')
|
|||
$runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null;
|
||||
|
||||
if (\is_null($runtime)) {
|
||||
throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported', 400, Exception::FUNCTION_RUNTIME_UNSUPPORTED);
|
||||
throw new Exception(Exception::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $function->getAttribute('runtime', '') . '" is not supported');
|
||||
}
|
||||
|
||||
$deployment = Authorization::skip(fn () => $dbForProject->getDocument('deployments', $function->getAttribute('deployment', '')));
|
||||
|
||||
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
|
||||
throw new Exception('Deployment not found. Create a deployment before trying to execute a function', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function');
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found. Create a deployment before trying to execute a function', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND, 'Deployment not found. Create a deployment before trying to execute a function');
|
||||
}
|
||||
|
||||
/** Check if build has completed */
|
||||
$build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')));
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception('Build not found', 404, Exception::BUILD_NOT_FOUND);
|
||||
throw new Exception(Exception::BUILD_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->getAttribute('status') !== 'ready') {
|
||||
throw new Exception('Build not ready', 400, Exception::BUILD_NOT_READY);
|
||||
throw new Exception(Exception::BUILD_NOT_READY);
|
||||
}
|
||||
|
||||
$validator = new Authorization('execute');
|
||||
|
||||
if (!$validator->isValid($function->getAttribute('execute'))) { // Check if user has write access to execute function
|
||||
throw new Exception($validator->getDescription(), 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, $validator->getDescription());
|
||||
}
|
||||
|
||||
$executionId = $dbForProject->getId();
|
||||
|
@ -1007,7 +1007,7 @@ App::get('/v1/functions/:functionId/executions')
|
|||
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$filterQueries = [
|
||||
|
@ -1026,7 +1026,7 @@ App::get('/v1/functions/:functionId/executions')
|
|||
$cursorDocument = $dbForProject->getDocument('executions', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Execution '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Tag '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -1061,17 +1061,17 @@ App::get('/v1/functions/:functionId/executions/:executionId')
|
|||
$function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId));
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$execution = $dbForProject->getDocument('executions', $executionId);
|
||||
|
||||
if ($execution->getAttribute('functionId') !== $function->getId()) {
|
||||
throw new Exception('Execution not found', 404, Exception::EXECUTION_NOT_FOUND);
|
||||
throw new Exception(Exception::EXECUTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($execution->isEmpty()) {
|
||||
throw new Exception('Execution not found', 404, Exception::EXECUTION_NOT_FOUND);
|
||||
throw new Exception(Exception::EXECUTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($execution, Response::MODEL_EXECUTION);
|
||||
|
@ -1101,21 +1101,21 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
|
|||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404, Exception::FUNCTION_NOT_FOUND);
|
||||
throw new Exception(Exception::FUNCTION_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found', 404, Exception::DEPLOYMENT_NOT_FOUND);
|
||||
throw new Exception(Exception::DEPLOYMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$build = Authorization::skip(fn () => $dbForProject->getDocument('builds', $buildId));
|
||||
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception('Build not found', 404, Exception::BUILD_NOT_FOUND);
|
||||
throw new Exception(Exception::BUILD_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($build->getAttribute('status') !== 'failed') {
|
||||
throw new Exception('Build not failed', 400, Exception::BUILD_IN_PROGRESS);
|
||||
throw new Exception(Exception::BUILD_IN_PROGRESS, 'Build not failed');
|
||||
}
|
||||
|
||||
$events
|
||||
|
|
|
@ -19,6 +19,6 @@ App::post('/v1/graphql')
|
|||
->label('scope', 'public')
|
||||
->action(
|
||||
function () {
|
||||
throw new Exception('GraphQL support is coming soon!', 502, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'GraphQL support is coming soon!', 503);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -73,7 +73,7 @@ App::get('/v1/health/db')
|
|||
|
||||
$statement->execute();
|
||||
} catch (Exception $_e) {
|
||||
throw new Exception('Database is not available', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Database is not available');
|
||||
}
|
||||
|
||||
$output = [
|
||||
|
@ -104,7 +104,7 @@ App::get('/v1/health/cache')
|
|||
$redis = $utopia->getResource('cache');
|
||||
|
||||
if (!$redis->ping(true)) {
|
||||
throw new Exception('Cache is not available', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Cache is not available');
|
||||
}
|
||||
|
||||
$output = [
|
||||
|
@ -160,7 +160,7 @@ App::get('/v1/health/time')
|
|||
$diff = ($timestamp - \time());
|
||||
|
||||
if ($diff > $gap || $diff < ($gap * -1)) {
|
||||
throw new Exception('Server time gaps detected', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Server time gaps detected');
|
||||
}
|
||||
|
||||
$output = [
|
||||
|
@ -267,11 +267,11 @@ App::get('/v1/health/storage/local')
|
|||
$device = new Local($volume);
|
||||
|
||||
if (!\is_readable($device->getRoot())) {
|
||||
throw new Exception('Device ' . $key . ' dir is not readable', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not readable');
|
||||
}
|
||||
|
||||
if (!\is_writable($device->getRoot())) {
|
||||
throw new Exception('Device ' . $key . ' dir is not writable', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Device ' . $key . ' dir is not writable');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ App::get('/v1/health/anti-virus')
|
|||
$output['version'] = @$antivirus->version();
|
||||
$output['status'] = (@$antivirus->ping()) ? 'pass' : 'fail';
|
||||
} catch (\Exception $e) {
|
||||
throw new Exception('Antivirus is not available', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Antivirus is not available');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ App::init()
|
|||
->inject('project')
|
||||
->action(function (Document $project) {
|
||||
if ($project->getId() !== 'console') {
|
||||
throw new Exception('Access to this API is forbidden.', 401, Exception::GENERAL_ACCESS_FORBIDDEN);
|
||||
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -71,7 +71,7 @@ App::post('/v1/projects')
|
|||
$team = $dbForConsole->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auth = Config::getParam('auth', []);
|
||||
|
@ -83,7 +83,7 @@ App::post('/v1/projects')
|
|||
$projectId = ($projectId == 'unique()') ? $dbForConsole->getId() : $projectId;
|
||||
|
||||
if ($projectId === 'console') {
|
||||
throw new Exception("'console' is a reserved project.", 400, Exception::PROJECT_RESERVED_PROJECT);
|
||||
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
|
||||
}
|
||||
|
||||
$project = $dbForConsole->createDocument('projects', new Document([
|
||||
|
@ -196,7 +196,7 @@ App::get('/v1/projects')
|
|||
$cursorDocument = $dbForConsole->getDocument('projects', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Project '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Project '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -229,7 +229,7 @@ App::get('/v1/projects/:projectId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
|
@ -256,7 +256,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage = [];
|
||||
|
@ -375,7 +375,7 @@ App::patch('/v1/projects/:projectId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
|
@ -414,7 +414,7 @@ App::patch('/v1/projects/:projectId/service')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$services = $project->getAttribute('services', []);
|
||||
|
@ -446,7 +446,7 @@ App::patch('/v1/projects/:projectId/oauth2')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$providers = $project->getAttribute('authProviders', []);
|
||||
|
@ -477,7 +477,7 @@ App::patch('/v1/projects/:projectId/auth/limit')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
|
@ -512,7 +512,7 @@ App::patch('/v1/projects/:projectId/auth/:method')
|
|||
$status = ($status === '1' || $status === 'true' || $status === 1 || $status === true);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$auths = $project->getAttribute('auths', []);
|
||||
|
@ -541,13 +541,13 @@ App::delete('/v1/projects/:projectId')
|
|||
->action(function (string $projectId, string $password, Response $response, Document $user, Database $dbForConsole, Delete $deletes) {
|
||||
|
||||
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
|
||||
throw new Exception('Invalid credentials', 401, Exception::USER_INVALID_CREDENTIALS);
|
||||
throw new Exception(Exception::USER_INVALID_CREDENTIALS);
|
||||
}
|
||||
|
||||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deletes
|
||||
|
@ -556,11 +556,11 @@ App::delete('/v1/projects/:projectId')
|
|||
;
|
||||
|
||||
if (!$dbForConsole->deleteDocument('teams', $project->getAttribute('teamId', null))) {
|
||||
throw new Exception('Failed to remove project team from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project team from DB');
|
||||
}
|
||||
|
||||
if (!$dbForConsole->deleteDocument('projects', $projectId)) {
|
||||
throw new Exception('Failed to remove project from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB');
|
||||
}
|
||||
|
||||
$response->noContent();
|
||||
|
@ -592,7 +592,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN);
|
||||
|
@ -638,7 +638,7 @@ App::get('/v1/projects/:projectId/webhooks')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhooks = $dbForConsole->find('webhooks', [
|
||||
|
@ -671,7 +671,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForConsole->findOne('webhooks', [
|
||||
|
@ -680,7 +680,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
]);
|
||||
|
||||
if ($webhook === false || $webhook->isEmpty()) {
|
||||
throw new Exception('Webhook not found', 404, Exception::WEBHOOK_NOT_FOUND);
|
||||
throw new Exception(Exception::WEBHOOK_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||
|
@ -711,7 +711,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
|
@ -722,7 +722,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
]);
|
||||
|
||||
if ($webhook === false || $webhook->isEmpty()) {
|
||||
throw new Exception('Webhook not found', 404, Exception::WEBHOOK_NOT_FOUND);
|
||||
throw new Exception(Exception::WEBHOOK_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook
|
||||
|
@ -759,7 +759,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForConsole->findOne('webhooks', [
|
||||
|
@ -768,7 +768,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature')
|
|||
]);
|
||||
|
||||
if ($webhook === false || $webhook->isEmpty()) {
|
||||
throw new Exception('Webhook not found', 404, Exception::WEBHOOK_NOT_FOUND);
|
||||
throw new Exception(Exception::WEBHOOK_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook->setAttribute('signatureKey', \bin2hex(\random_bytes(64)));
|
||||
|
@ -797,7 +797,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$webhook = $dbForConsole->findOne('webhooks', [
|
||||
|
@ -806,7 +806,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
]);
|
||||
|
||||
if ($webhook === false || $webhook->isEmpty()) {
|
||||
throw new Exception('Webhook not found', 404, Exception::WEBHOOK_NOT_FOUND);
|
||||
throw new Exception(Exception::WEBHOOK_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForConsole->deleteDocument('webhooks', $webhook->getId());
|
||||
|
@ -839,7 +839,7 @@ App::post('/v1/projects/:projectId/keys')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = new Document([
|
||||
|
@ -880,7 +880,7 @@ App::get('/v1/projects/:projectId/keys')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$keys = $dbForConsole->find('keys', [
|
||||
|
@ -913,7 +913,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForConsole->findOne('keys', [
|
||||
|
@ -922,7 +922,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
|||
]);
|
||||
|
||||
if ($key === false || $key->isEmpty()) {
|
||||
throw new Exception('Key not found', 404, Exception::KEY_NOT_FOUND);
|
||||
throw new Exception(Exception::KEY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($key, Response::MODEL_KEY);
|
||||
|
@ -950,7 +950,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForConsole->findOne('keys', [
|
||||
|
@ -959,7 +959,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
|||
]);
|
||||
|
||||
if ($key === false || $key->isEmpty()) {
|
||||
throw new Exception('Key not found', 404, Exception::KEY_NOT_FOUND);
|
||||
throw new Exception(Exception::KEY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key
|
||||
|
@ -993,7 +993,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $dbForConsole->findOne('keys', [
|
||||
|
@ -1002,7 +1002,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId')
|
|||
]);
|
||||
|
||||
if ($key === false || $key->isEmpty()) {
|
||||
throw new Exception('Key not found', 404, Exception::KEY_NOT_FOUND);
|
||||
throw new Exception(Exception::KEY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForConsole->deleteDocument('keys', $key->getId());
|
||||
|
@ -1036,7 +1036,7 @@ App::post('/v1/projects/:projectId/platforms')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = new Document([
|
||||
|
@ -1078,7 +1078,7 @@ App::get('/v1/projects/:projectId/platforms')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platforms = $dbForConsole->find('platforms', [
|
||||
|
@ -1111,7 +1111,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForConsole->findOne('platforms', [
|
||||
|
@ -1120,7 +1120,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
|||
]);
|
||||
|
||||
if ($platform === false || $platform->isEmpty()) {
|
||||
throw new Exception('Platform not found', 404, Exception::PLATFORM_NOT_FOUND);
|
||||
throw new Exception(Exception::PLATFORM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($platform, Response::MODEL_PLATFORM);
|
||||
|
@ -1148,7 +1148,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForConsole->findOne('platforms', [
|
||||
|
@ -1157,7 +1157,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
|||
]);
|
||||
|
||||
if ($platform === false || $platform->isEmpty()) {
|
||||
throw new Exception('Platform not found', 404, Exception::PLATFORM_NOT_FOUND);
|
||||
throw new Exception(Exception::PLATFORM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform
|
||||
|
@ -1192,7 +1192,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$platform = $dbForConsole->findOne('platforms', [
|
||||
|
@ -1201,7 +1201,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
|||
]);
|
||||
|
||||
if ($platform === false || $platform->isEmpty()) {
|
||||
throw new Exception('Platform not found', 404, Exception::PLATFORM_NOT_FOUND);
|
||||
throw new Exception(Exception::PLATFORM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForConsole->deleteDocument('platforms', $platformId);
|
||||
|
@ -1232,7 +1232,7 @@ App::post('/v1/projects/:projectId/domains')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$document = $dbForConsole->findOne('domains', [
|
||||
|
@ -1241,13 +1241,13 @@ App::post('/v1/projects/:projectId/domains')
|
|||
]);
|
||||
|
||||
if ($document && !$document->isEmpty()) {
|
||||
throw new Exception('Domain already exists', 409, Exception::DOMAIN_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DOMAIN_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.');
|
||||
}
|
||||
|
||||
$domain = new Domain($domain);
|
||||
|
@ -1292,7 +1292,7 @@ App::get('/v1/projects/:projectId/domains')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$domains = $dbForConsole->find('domains', [
|
||||
|
@ -1325,7 +1325,7 @@ App::get('/v1/projects/:projectId/domains/:domainId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$domain = $dbForConsole->findOne('domains', [
|
||||
|
@ -1334,7 +1334,7 @@ App::get('/v1/projects/:projectId/domains/:domainId')
|
|||
]);
|
||||
|
||||
if ($domain === false || $domain->isEmpty()) {
|
||||
throw new Exception('Domain not found', 404, Exception::DOMAIN_NOT_FOUND);
|
||||
throw new Exception(Exception::DOMAIN_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($domain, Response::MODEL_DOMAIN);
|
||||
|
@ -1359,7 +1359,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$domain = $dbForConsole->findOne('domains', [
|
||||
|
@ -1368,13 +1368,13 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
|||
]);
|
||||
|
||||
if ($domain === false || $domain->isEmpty()) {
|
||||
throw new Exception('Domain not found', 404, Exception::DOMAIN_NOT_FOUND);
|
||||
throw new Exception(Exception::DOMAIN_NOT_FOUND);
|
||||
}
|
||||
|
||||
$target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.');
|
||||
}
|
||||
|
||||
if ($domain->getAttribute('verification') === true) {
|
||||
|
@ -1384,7 +1384,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
|||
$validator = new CNAME($target->get()); // Verify Domain with DNS records
|
||||
|
||||
if (!$validator->isValid($domain->getAttribute('domain', ''))) {
|
||||
throw new Exception('Failed to verify domain', 401, Exception::DOMAIN_VERIFICATION_FAILED);
|
||||
throw new Exception(Exception::DOMAIN_VERIFICATION_FAILED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1419,7 +1419,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
|
|||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception('Project not found', 404, Exception::PROJECT_NOT_FOUND);
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
$domain = $dbForConsole->findOne('domains', [
|
||||
|
@ -1428,7 +1428,7 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
|
|||
]);
|
||||
|
||||
if ($domain === false || $domain->isEmpty()) {
|
||||
throw new Exception('Domain not found', 404, Exception::DOMAIN_NOT_FOUND);
|
||||
throw new Exception(Exception::DOMAIN_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForConsole->deleteDocument('domains', $domain->getId());
|
||||
|
|
|
@ -75,7 +75,7 @@ App::post('/v1/storage/buckets')
|
|||
try {
|
||||
$files = Config::getParam('collections', [])['files'] ?? [];
|
||||
if (empty($files)) {
|
||||
throw new Exception('Files collection is not configured.', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Files collection is not configured.');
|
||||
}
|
||||
|
||||
$attributes = [];
|
||||
|
@ -124,7 +124,7 @@ App::post('/v1/storage/buckets')
|
|||
|
||||
$dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Bucket already exists', 409, Exception::STORAGE_BUCKET_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -178,7 +178,7 @@ App::get('/v1/storage/buckets')
|
|||
$cursorDocument = $dbForProject->getDocument('buckets', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Bucket '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Bucket '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -212,7 +212,7 @@ App::get('/v1/storage/buckets/:bucketId')
|
|||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||
|
||||
if ($bucket->isEmpty()) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage->setParam('storage.buckets.read', 1);
|
||||
|
@ -251,7 +251,7 @@ App::put('/v1/storage/buckets/:bucketId')
|
|||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||
|
||||
if ($bucket->isEmpty()) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$read ??= $bucket->getAttribute('$read', []); // By default inherit read permissions
|
||||
|
@ -309,11 +309,11 @@ App::delete('/v1/storage/buckets/:bucketId')
|
|||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||
|
||||
if ($bucket->isEmpty()) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('buckets', $bucketId)) {
|
||||
throw new Exception('Failed to remove project from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove bucket from DB');
|
||||
}
|
||||
|
||||
$deletes
|
||||
|
@ -372,7 +372,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
|
@ -380,7 +380,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
if ($permissionBucket) {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,12 +393,12 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) {
|
||||
foreach ($read as $role) {
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400);
|
||||
}
|
||||
}
|
||||
foreach ($write as $role) {
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,12 +413,12 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
|
||||
$maximumFileSize = $bucket->getAttribute('maximumFileSize', 0);
|
||||
if ($maximumFileSize > (int) App::getEnv('_APP_STORAGE_LIMIT', 0)) {
|
||||
throw new Exception('Maximum bucket file size is larger than _APP_STORAGE_LIMIT', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Maximum bucket file size is larger than _APP_STORAGE_LIMIT');
|
||||
}
|
||||
|
||||
$file = $request->getFiles('file');
|
||||
if (empty($file)) {
|
||||
throw new Exception('No file sent', 400, Exception::STORAGE_FILE_EMPTY);
|
||||
throw new Exception(Exception::STORAGE_FILE_EMPTY);
|
||||
}
|
||||
|
||||
// Make sure we handle a single file and multiple files the same way
|
||||
|
@ -437,7 +437,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
$fileSize = $request->getContentRangeSize();
|
||||
$fileId = $request->getHeader('x-appwrite-id', $fileId);
|
||||
if (is_null($start) || is_null($end) || is_null($fileSize)) {
|
||||
throw new Exception('Invalid content-range header', 400, Exception::STORAGE_INVALID_CONTENT_RANGE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_CONTENT_RANGE);
|
||||
}
|
||||
|
||||
if ($end === $fileSize) {
|
||||
|
@ -457,18 +457,18 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
$allowedFileExtensions = $bucket->getAttribute('allowedFileExtensions', []);
|
||||
$fileExt = new FileExt($allowedFileExtensions);
|
||||
if (!empty($allowedFileExtensions) && !$fileExt->isValid($fileName)) {
|
||||
throw new Exception('File extension not allowed', 400, Exception::STORAGE_FILE_TYPE_UNSUPPORTED);
|
||||
throw new Exception(Exception::STORAGE_FILE_TYPE_UNSUPPORTED, 'File extension not allowed');
|
||||
}
|
||||
|
||||
// Check if file size is exceeding allowed limit
|
||||
$fileSizeValidator = new FileSize($maximumFileSize);
|
||||
if (!$fileSizeValidator->isValid($fileSize)) {
|
||||
throw new Exception('File size not allowed', 400, Exception::STORAGE_INVALID_FILE_SIZE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE, 'File size not allowed');
|
||||
}
|
||||
|
||||
$upload = new Upload();
|
||||
if (!$upload->isValid($fileTmpName)) {
|
||||
throw new Exception('Invalid file', 403, Exception::STORAGE_INVALID_FILE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_FILE);
|
||||
}
|
||||
|
||||
// Save to storage
|
||||
|
@ -495,7 +495,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
|
||||
$chunksUploaded = $deviceFiles->upload($fileTmpName, $path, $chunk, $chunks, $metadata);
|
||||
if (empty($chunksUploaded)) {
|
||||
throw new Exception('Failed uploading file', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed uploading file');
|
||||
}
|
||||
|
||||
$read = (is_null($read) && !$user->isEmpty()) ? ['user:' . $user->getId()] : $read ?? [];
|
||||
|
@ -509,7 +509,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
|
||||
if (!$antivirus->fileScan($path)) {
|
||||
$deviceFiles->delete($path);
|
||||
throw new Exception('Invalid file', 400, Exception::STORAGE_INVALID_FILE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
|
||||
if (!empty($data)) {
|
||||
if (!$deviceFiles->write($path, $data, $mimeType)) {
|
||||
throw new Exception('Failed to save file', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to save file');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,9 +600,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
}
|
||||
}
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$audits
|
||||
|
@ -652,9 +652,9 @@ App::post('/v1/storage/buckets/:bucketId/files')
|
|||
}
|
||||
}
|
||||
} catch (StructureException $exception) {
|
||||
throw new Exception($exception->getMessage(), 400, Exception::DOCUMENT_INVALID_STRUCTURE);
|
||||
throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage());
|
||||
} catch (DuplicateException $exception) {
|
||||
throw new Exception('Document already exists', 409, Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,14 +701,14 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -730,7 +730,7 @@ App::get('/v1/storage/buckets/:bucketId/files')
|
|||
}
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("File '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "File '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -781,14 +781,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,7 +799,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
}
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -846,7 +846,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
->action(function (string $bucketId, string $fileId, int $width, int $height, string $gravity, int $quality, int $borderWidth, string $borderColor, int $borderRadius, float $opacity, int $rotation, string $background, string $output, Request $request, Response $response, Document $project, Database $dbForProject, Stats $usage, string $mode, Device $deviceFiles, Device $deviceLocal) {
|
||||
|
||||
if (!\extension_loaded('imagick')) {
|
||||
throw new Exception('Imagick extension is missing', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Imagick extension is missing');
|
||||
}
|
||||
|
||||
$bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId));
|
||||
|
@ -855,14 +855,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND, 'Unauthorized permissions');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -885,7 +885,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
}
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path');
|
||||
|
@ -914,7 +914,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview')
|
|||
$compressor = new GZIP();
|
||||
|
||||
if (!$deviceFiles->exists($path)) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$cache = new Cache(new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId() . DIRECTORY_SEPARATOR . $bucketId . DIRECTORY_SEPARATOR . $fileId)); // Limit file number or size
|
||||
|
@ -1023,14 +1023,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1041,13 +1041,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
}
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path', '');
|
||||
|
||||
if (!$deviceFiles->exists($path)) {
|
||||
throw new Exception('File not found in ' . $path, 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -1075,7 +1075,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download')
|
|||
}
|
||||
|
||||
if ($unit !== 'bytes' || $start >= $end || $end >= $size) {
|
||||
throw new Exception('Invalid range', 416, Exception::STORAGE_INVALID_RANGE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_RANGE);
|
||||
}
|
||||
|
||||
$response
|
||||
|
@ -1162,14 +1162,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('read');
|
||||
if (!$validator->isValid($bucket->getRead())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1182,13 +1182,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
$mimes = Config::getParam('storage-mimes');
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$path = $file->getAttribute('path', '');
|
||||
|
||||
if (!$deviceFiles->exists($path)) {
|
||||
throw new Exception('File not found in ' . $path, 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path);
|
||||
}
|
||||
|
||||
$compressor = new GZIP();
|
||||
|
@ -1221,7 +1221,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view')
|
|||
}
|
||||
|
||||
if ($unit != 'bytes' || $start >= $end || $end >= $size) {
|
||||
throw new Exception('Invalid range', 416, Exception::STORAGE_INVALID_RANGE);
|
||||
throw new Exception(Exception::STORAGE_INVALID_RANGE);
|
||||
}
|
||||
|
||||
$response
|
||||
|
@ -1321,12 +1321,12 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
if (!Auth::isAppUser($roles) && !Auth::isPrivilegedUser($roles)) {
|
||||
foreach ($read as $role) {
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception('Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Read permissions must be one of: (' . \implode(', ', $roles) . ')', 400);
|
||||
}
|
||||
}
|
||||
foreach ($write as $role) {
|
||||
if (!Authorization::isRole($role)) {
|
||||
throw new Exception('Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'Write permissions must be one of: (' . \implode(', ', $roles) . ')', 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1335,14 +1335,14 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1353,7 +1353,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
}
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$file
|
||||
|
@ -1412,14 +1412,14 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$bucket->isEmpty()
|
||||
|| (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN)
|
||||
) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check bucket permissions when enforced
|
||||
if ($bucket->getAttribute('permission') === 'bucket') {
|
||||
$validator = new Authorization('write');
|
||||
if (!$validator->isValid($bucket->getWrite())) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1430,7 +1430,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
}
|
||||
|
||||
if ($file->isEmpty() || $file->getAttribute('bucketId') !== $bucketId) {
|
||||
throw new Exception('File not found', 404, Exception::STORAGE_FILE_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$deviceDeleted = false;
|
||||
|
@ -1455,10 +1455,10 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId')
|
|||
$deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId);
|
||||
}
|
||||
if (!$deleted) {
|
||||
throw new Exception('Failed to remove file from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove file from DB');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Failed to delete file from device', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to delete file from device');
|
||||
}
|
||||
|
||||
$audits->setResource('file/' . $file->getId());
|
||||
|
@ -1609,7 +1609,7 @@ App::get('/v1/storage/:bucketId/usage')
|
|||
$bucket = $dbForProject->getDocument('buckets', $bucketId);
|
||||
|
||||
if ($bucket->isEmpty()) {
|
||||
throw new Exception('Bucket not found', 404, Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage = [];
|
||||
|
|
|
@ -141,7 +141,7 @@ App::get('/v1/teams')
|
|||
$cursorDocument = $dbForProject->getDocument('teams', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Team '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Team '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -175,7 +175,7 @@ App::get('/v1/teams/:teamId')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response->dynamic($team, Response::MODEL_TEAM);
|
||||
|
@ -204,7 +204,7 @@ App::put('/v1/teams/:teamId')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = $dbForProject->updateDocument('teams', $team->getId(), $team
|
||||
|
@ -239,7 +239,7 @@ App::delete('/v1/teams/:teamId')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$memberships = $dbForProject->find('memberships', [
|
||||
|
@ -250,12 +250,12 @@ App::delete('/v1/teams/:teamId')
|
|||
// TODO delete all members individually from the user object
|
||||
foreach ($memberships as $membership) {
|
||||
if (!$dbForProject->deleteDocument('memberships', $membership->getId())) {
|
||||
throw new Exception('Failed to remove membership for team from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership for team from DB');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteDocument('teams', $teamId)) {
|
||||
throw new Exception('Failed to remove team from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove team from DB');
|
||||
}
|
||||
|
||||
$deletes
|
||||
|
@ -309,7 +309,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$isAppUser = Auth::isAppUser(Authorization::getRoles());
|
||||
|
||||
if (!$isPrivilegedUser && !$isAppUser && empty(App::getEnv('_APP_SMTP_HOST'))) {
|
||||
throw new Exception('SMTP Disabled', 503, Exception::GENERAL_SMTP_DISABLED);
|
||||
throw new Exception(Exception::GENERAL_SMTP_DISABLED);
|
||||
}
|
||||
|
||||
$email = \strtolower($email);
|
||||
|
@ -317,7 +317,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$invitee = $dbForProject->findOne('users', [Query::equal('email', [$email])]); // Get user by email address
|
||||
|
@ -329,7 +329,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
$total = $dbForProject->count('users', [], APP_LIMIT_USERS);
|
||||
|
||||
if ($total >= $limit) {
|
||||
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501, Exception::USER_COUNT_EXCEEDED);
|
||||
throw new Exception(Exception::USER_COUNT_EXCEEDED, 'Project registration is restricted. Contact your administrator for more information.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,14 +359,14 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
'search' => implode(' ', [$userId, $email, $name])
|
||||
])));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Account already exists', 409, Exception::USER_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception('User is not allowed to send invitations for this team', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to send invitations for this team');
|
||||
}
|
||||
|
||||
$secret = Auth::tokenGenerator();
|
||||
|
@ -392,7 +392,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
try {
|
||||
$membership = Authorization::skip(fn() => $dbForProject->createDocument('memberships', $membership));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('User is already a member of this team', 409, Exception::TEAM_INVITE_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS);
|
||||
}
|
||||
$team->setAttribute('total', $team->getAttribute('total', 0) + 1);
|
||||
$team = Authorization::skip(fn() => $dbForProject->updateDocument('teams', $team->getId(), $team));
|
||||
|
@ -402,7 +402,7 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
try {
|
||||
$membership = $dbForProject->createDocument('memberships', $membership);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('User has already been invited or is already a member of this team', 409, Exception::TEAM_INVITE_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::TEAM_INVITE_ALREADY_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,7 +467,7 @@ App::get('/v1/teams/:teamId/memberships')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$filterQueries = [Query::equal('teamId', [$teamId])];
|
||||
|
@ -484,7 +484,7 @@ App::get('/v1/teams/:teamId/memberships')
|
|||
$cursorDocument = $dbForProject->getDocument('memberships', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("Membership '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Membership '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$otherQueries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -541,13 +541,13 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
|
||||
if ($membership->isEmpty() || empty($membership->getAttribute('userId'))) {
|
||||
throw new Exception('Membership not found', 404, Exception::MEMBERSHIP_NOT_FOUND);
|
||||
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
|
||||
|
@ -586,17 +586,17 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
|||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
if ($membership->isEmpty()) {
|
||||
throw new Exception('Membership not found', 404, Exception::MEMBERSHIP_NOT_FOUND);
|
||||
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$profile = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
|
||||
if ($profile->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
|
||||
|
@ -604,7 +604,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
|||
$isOwner = Authorization::isRole('team:' . $team->getId() . '/owner');
|
||||
|
||||
if (!$isOwner && !$isPrivilegedUser && !$isAppUser) { // Not owner, not admin, not app (server)
|
||||
throw new Exception('User is not allowed to modify roles', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED, 'User is not allowed to modify roles');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -662,25 +662,25 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
|||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
|
||||
if ($membership->isEmpty()) {
|
||||
throw new Exception('Membership not found', 404, Exception::MEMBERSHIP_NOT_FOUND);
|
||||
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($membership->getAttribute('teamId') !== $teamId) {
|
||||
throw new Exception('Team IDs don\'t match', 404, Exception::TEAM_MEMBERSHIP_MISMATCH);
|
||||
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
|
||||
}
|
||||
|
||||
$team = Authorization::skip(fn() => $dbForProject->getDocument('teams', $teamId));
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (Auth::hash($secret) !== $membership->getAttribute('secret')) {
|
||||
throw new Exception('Secret key not valid', 401, Exception::TEAM_INVALID_SECRET);
|
||||
throw new Exception(Exception::TEAM_INVALID_SECRET);
|
||||
}
|
||||
|
||||
if ($userId !== $membership->getAttribute('userId')) {
|
||||
throw new Exception('Invite does not belong to current user (' . $user->getAttribute('email') . ')', 401, Exception::TEAM_INVITE_MISMATCH);
|
||||
throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')');
|
||||
}
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
|
@ -688,11 +688,11 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
|||
}
|
||||
|
||||
if ($membership->getAttribute('userId') !== $user->getId()) {
|
||||
throw new Exception('Invite does not belong to current user (' . $user->getAttribute('email') . ')', 401, Exception::TEAM_INVITE_MISMATCH);
|
||||
throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')');
|
||||
}
|
||||
|
||||
if ($membership->getAttribute('confirm') === true) {
|
||||
throw new Exception('Membership already confirmed', 409);
|
||||
throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED);
|
||||
}
|
||||
|
||||
$membership // Attach user to team
|
||||
|
@ -788,31 +788,31 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId')
|
|||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
|
||||
if ($membership->isEmpty()) {
|
||||
throw new Exception('Invite not found', 404, Exception::TEAM_INVITE_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_INVITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($membership->getAttribute('teamId') !== $teamId) {
|
||||
throw new Exception('Team IDs don\'t match', 404);
|
||||
throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH);
|
||||
}
|
||||
|
||||
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$dbForProject->deleteDocument('memberships', $membership->getId());
|
||||
} catch (AuthorizationException $exception) {
|
||||
throw new Exception('Unauthorized permissions', 401, Exception::USER_UNAUTHORIZED);
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
} catch (\Exception $exception) {
|
||||
throw new Exception('Failed to remove membership from DB', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB');
|
||||
}
|
||||
|
||||
$dbForProject->deleteCachedDocument('users', $user->getId());
|
||||
|
@ -861,7 +861,7 @@ App::get('/v1/teams/:teamId/logs')
|
|||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
if ($team->isEmpty()) {
|
||||
throw new Exception('Team not found', 404, Exception::TEAM_NOT_FOUND);
|
||||
throw new Exception(Exception::TEAM_NOT_FOUND);
|
||||
}
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
|
|
@ -75,7 +75,7 @@ App::post('/v1/users')
|
|||
'search' => implode(' ', [$userId, $email, $name])
|
||||
]));
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Account already exists', 409, Exception::USER_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -126,7 +126,7 @@ App::get('/v1/users')
|
|||
$cursorDocument = $dbForProject->getDocument('users', $cursor);
|
||||
|
||||
if ($cursorDocument->isEmpty()) {
|
||||
throw new Exception("User '{$cursor}' for the 'cursor' value not found.", 400, Exception::GENERAL_CURSOR_NOT_FOUND);
|
||||
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "User '{$cursor}' for the 'cursor' value not found.");
|
||||
}
|
||||
|
||||
$queries[] = $cursorDirection === Database::CURSOR_AFTER ? Query::cursorAfter($cursorDocument) : Query::cursorBefore($cursorDocument);
|
||||
|
@ -162,7 +162,7 @@ App::get('/v1/users/:userId')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$usage
|
||||
|
@ -191,7 +191,7 @@ App::get('/v1/users/:userId/prefs')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$prefs = $user->getAttribute('prefs', new \stdClass());
|
||||
|
@ -223,7 +223,7 @@ App::get('/v1/users/:userId/sessions')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
@ -266,7 +266,7 @@ App::get('/v1/users/:userId/memberships')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$memberships = array_map(function ($membership) use ($dbForProject, $user) {
|
||||
|
@ -310,7 +310,7 @@ App::get('/v1/users/:userId/logs')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$audit = new Audit($dbForProject);
|
||||
|
@ -391,7 +391,7 @@ App::patch('/v1/users/:userId/status')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('status', (bool) $status));
|
||||
|
@ -430,7 +430,7 @@ App::patch('/v1/users/:userId/verification')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('emailVerification', $emailVerification));
|
||||
|
@ -469,7 +469,7 @@ App::patch('/v1/users/:userId/verification/phone')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('phoneVerification', $phoneVerification));
|
||||
|
@ -508,7 +508,7 @@ App::patch('/v1/users/:userId/name')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user
|
||||
|
@ -552,7 +552,7 @@ App::patch('/v1/users/:userId/password')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user
|
||||
|
@ -595,7 +595,7 @@ App::patch('/v1/users/:userId/email')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$email = \strtolower($email);
|
||||
|
@ -609,7 +609,7 @@ App::patch('/v1/users/:userId/email')
|
|||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Email already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -647,7 +647,7 @@ App::patch('/v1/users/:userId/phone')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user
|
||||
|
@ -659,7 +659,7 @@ App::patch('/v1/users/:userId/phone')
|
|||
try {
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user);
|
||||
} catch (Duplicate $th) {
|
||||
throw new Exception('Email already exists', 409, Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -697,7 +697,7 @@ App::patch('/v1/users/:userId/prefs')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$user = $dbForProject->updateDocument('users', $user->getId(), $user->setAttribute('prefs', $prefs));
|
||||
|
@ -735,13 +735,13 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$session = $dbForProject->getDocument('sessions', $sessionId);
|
||||
|
||||
if ($session->isEmpty()) {
|
||||
throw new Exception('Session not found', 404, Exception::USER_SESSION_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_SESSION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('sessions', $session->getId());
|
||||
|
@ -782,7 +782,7 @@ App::delete('/v1/users/:userId/sessions')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
$sessions = $user->getAttribute('sessions', []);
|
||||
|
@ -829,7 +829,7 @@ App::delete('/v1/users/:userId')
|
|||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception('User not found', 404, Exception::USER_NOT_FOUND);
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// clone user object to send to workers
|
||||
|
|
|
@ -132,11 +132,11 @@ App::init()
|
|||
}
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new AppwriteException('Project not found', 404, AppwriteException::PROJECT_NOT_FOUND);
|
||||
throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!empty($route->getLabel('sdk.auth', [])) && $project->isEmpty() && ($route->getLabel('scope', '') !== 'public')) {
|
||||
throw new AppwriteException('Missing or unknown project ID', 400, AppwriteException::PROJECT_UNKNOWN);
|
||||
throw new AppwriteException(AppwriteException::PROJECT_UNKNOWN);
|
||||
}
|
||||
|
||||
$referrer = $request->getReferer();
|
||||
|
@ -207,7 +207,7 @@ App::init()
|
|||
if (App::getEnv('_APP_OPTIONS_FORCE_HTTPS', 'disabled') === 'enabled') { // Force HTTPS
|
||||
if ($request->getProtocol() !== 'https') {
|
||||
if ($request->getMethod() !== Request::METHOD_GET) {
|
||||
throw new AppwriteException('Method unsupported over HTTP.', 500, AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_PROTOCOL_UNSUPPORTED, 'Method unsupported over HTTP.');
|
||||
}
|
||||
|
||||
return $response->redirect('https://' . $request->getHostname() . $request->getURI());
|
||||
|
@ -240,7 +240,7 @@ App::init()
|
|||
&& $route->getLabel('origin', false) !== '*'
|
||||
&& empty($request->getHeader('x-appwrite-key', ''))
|
||||
) {
|
||||
throw new AppwriteException($originValidator->getDescription(), 403, AppwriteException::GENERAL_UNKNOWN_ORIGIN);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_UNKNOWN_ORIGIN, $originValidator->getDescription());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -296,7 +296,7 @@ App::init()
|
|||
$expire = $key->getAttribute('expire');
|
||||
|
||||
if (!empty($expire) && $expire < DateTime::now()) {
|
||||
throw new AppwriteException('Project key expired', 401, AppwriteException:: PROJECT_KEY_EXPIRED);
|
||||
throw new AppwriteException(AppwriteException:: PROJECT_KEY_EXPIRED);
|
||||
}
|
||||
|
||||
Authorization::setRole('role:' . Auth::USER_ROLE_APP);
|
||||
|
@ -317,24 +317,24 @@ App::init()
|
|||
&& !$project->getAttribute('services', [])[$service]
|
||||
&& !(Auth::isPrivilegedUser(Authorization::getRoles()) || Auth::isAppUser(Authorization::getRoles()))
|
||||
) {
|
||||
throw new AppwriteException('Service is disabled', 503, AppwriteException::GENERAL_SERVICE_DISABLED);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVICE_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
if (!\in_array($scope, $scopes)) {
|
||||
if ($project->isEmpty()) { // Check if permission is denied because project is missing
|
||||
throw new AppwriteException('Project not found', 404, AppwriteException::PROJECT_NOT_FOUND);
|
||||
throw new AppwriteException(AppwriteException::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
throw new AppwriteException($user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')', 401, AppwriteException::GENERAL_UNAUTHORIZED_SCOPE);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')');
|
||||
}
|
||||
|
||||
if (false === $user->getAttribute('status')) { // Account is blocked
|
||||
throw new AppwriteException('Invalid credentials. User is blocked', 401, AppwriteException::USER_BLOCKED);
|
||||
throw new AppwriteException(AppwriteException::USER_BLOCKED);
|
||||
}
|
||||
|
||||
if ($user->getAttribute('reset')) {
|
||||
throw new AppwriteException('Password reset is required', 412, AppwriteException::USER_PASSWORD_RESET_REQUIRED);
|
||||
throw new AppwriteException(AppwriteException::USER_PASSWORD_RESET_REQUIRED);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -446,7 +446,7 @@ App::error()
|
|||
|
||||
/** Handle Utopia Errors */
|
||||
if ($error instanceof Utopia\Exception) {
|
||||
$error = new AppwriteException($message, $code, AppwriteException::GENERAL_UNKNOWN, $error);
|
||||
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
|
||||
switch ($code) {
|
||||
case 400:
|
||||
$error->setType(AppwriteException::GENERAL_ARGUMENT_INVALID);
|
||||
|
@ -459,7 +459,7 @@ App::error()
|
|||
|
||||
/** Wrap all exceptions inside Appwrite\Extend\Exception */
|
||||
if (!($error instanceof AppwriteException)) {
|
||||
$error = new AppwriteException($message, $code, AppwriteException::GENERAL_UNKNOWN, $error);
|
||||
$error = new AppwriteException(AppwriteException::GENERAL_UNKNOWN, $message, $code, $error);
|
||||
}
|
||||
|
||||
switch ($code) { // Don't show 500 errors!
|
||||
|
@ -602,32 +602,32 @@ App::get('/.well-known/acme-challenge')
|
|||
]);
|
||||
|
||||
if (!$validator->isValid($token) || \count($uriChunks) !== 4) {
|
||||
throw new AppwriteException('Invalid challenge token.', 400);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ARGUMENT_INVALID, 'Invalid challenge token.');
|
||||
}
|
||||
|
||||
$base = \realpath(APP_STORAGE_CERTIFICATES);
|
||||
$absolute = \realpath($base . '/.well-known/acme-challenge/' . $token);
|
||||
|
||||
if (!$base) {
|
||||
throw new AppwriteException('Storage error', 500, AppwriteException::GENERAL_SERVER_ERROR);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Storage error');
|
||||
}
|
||||
|
||||
if (!$absolute) {
|
||||
throw new AppwriteException('Unknown path', 404);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path');
|
||||
}
|
||||
|
||||
if (!\substr($absolute, 0, \strlen($base)) === $base) {
|
||||
throw new AppwriteException('Invalid path', 401);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_UNAUTHORIZED_SCOPE, 'Invalid path');
|
||||
}
|
||||
|
||||
if (!\file_exists($absolute)) {
|
||||
throw new AppwriteException('Unknown path', 404);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ROUTE_NOT_FOUND, 'Unknown path');
|
||||
}
|
||||
|
||||
$content = @\file_get_contents($absolute);
|
||||
|
||||
if (!$content) {
|
||||
throw new AppwriteException('Failed to get contents', 500, AppwriteException::GENERAL_SERVER_ERROR);
|
||||
throw new AppwriteException(AppwriteException::GENERAL_SERVER_ERROR, 'Failed to get contents');
|
||||
}
|
||||
|
||||
$response->text($content);
|
||||
|
|
|
@ -253,31 +253,31 @@ App::post('/v1/mock/tests/general/upload')
|
|||
$file['size'] = (\is_array($file['size'])) ? $file['size'][0] : $file['size'];
|
||||
|
||||
if (is_null($start) || is_null($end) || is_null($size)) {
|
||||
throw new Exception('Invalid content-range header', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid content-range header');
|
||||
}
|
||||
|
||||
if ($start > $end || $end > $size) {
|
||||
throw new Exception('Invalid content-range header', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid content-range header');
|
||||
}
|
||||
|
||||
if ($start === 0 && !empty($id)) {
|
||||
throw new Exception('First chunked request cannot have id header', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'First chunked request cannot have id header');
|
||||
}
|
||||
|
||||
if ($start !== 0 && $id !== 'newfileid') {
|
||||
throw new Exception('All chunked request must have id header (except first)', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'All chunked request must have id header (except first)');
|
||||
}
|
||||
|
||||
if ($end !== $size && $end - $start + 1 !== $chunkSize) {
|
||||
throw new Exception('Chunk size must be 5MB (except last chunk)', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Chunk size must be 5MB (except last chunk)');
|
||||
}
|
||||
|
||||
if ($end !== $size && $file['size'] !== $chunkSize) {
|
||||
throw new Exception('Wrong chunk size', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Wrong chunk size');
|
||||
}
|
||||
|
||||
if ($file['size'] > $chunkSize) {
|
||||
throw new Exception('Chunk size must be 5MB or less', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Chunk size must be 5MB or less');
|
||||
}
|
||||
|
||||
if ($end !== $size) {
|
||||
|
@ -293,15 +293,15 @@ App::post('/v1/mock/tests/general/upload')
|
|||
$file['size'] = (\is_array($file['size'])) ? $file['size'][0] : $file['size'];
|
||||
|
||||
if ($file['name'] !== 'file.png') {
|
||||
throw new Exception('Wrong file name', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Wrong file name');
|
||||
}
|
||||
|
||||
if ($file['size'] !== 38756) {
|
||||
throw new Exception('Wrong file size', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Wrong file size');
|
||||
}
|
||||
|
||||
if (\md5(\file_get_contents($file['tmp_name'])) !== 'd80e7e6999a3eb2ae0d631a96fe135a4') {
|
||||
throw new Exception('Wrong file uploaded', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Wrong file uploaded');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -374,7 +374,7 @@ App::get('/v1/mock/tests/general/get-cookie')
|
|||
->action(function (Request $request) {
|
||||
|
||||
if ($request->getCookie('cookieName', '') !== 'cookieValue') {
|
||||
throw new Exception('Missing cookie value', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Missing cookie value');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -408,7 +408,7 @@ App::get('/v1/mock/tests/general/400-error')
|
|||
->label('sdk.response.model', Response::MODEL_ERROR)
|
||||
->label('sdk.mock', true)
|
||||
->action(function () {
|
||||
throw new Exception('Mock 400 error', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Mock 400 error');
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/500-error')
|
||||
|
@ -424,7 +424,7 @@ App::get('/v1/mock/tests/general/500-error')
|
|||
->label('sdk.response.model', Response::MODEL_ERROR)
|
||||
->label('sdk.mock', true)
|
||||
->action(function () {
|
||||
throw new Exception('Mock 500 error', 500, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Mock 500 error', 500);
|
||||
});
|
||||
|
||||
App::get('/v1/mock/tests/general/502-error')
|
||||
|
@ -480,11 +480,11 @@ App::get('/v1/mock/tests/general/oauth2/token')
|
|||
->action(function (string $client_id, string $client_secret, string $grantType, string $redirectURI, string $code, string $refreshToken, Response $response) {
|
||||
|
||||
if ($client_id != '1') {
|
||||
throw new Exception('Invalid client ID', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid client ID');
|
||||
}
|
||||
|
||||
if ($client_secret != '123456') {
|
||||
throw new Exception('Invalid client secret', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid client secret');
|
||||
}
|
||||
|
||||
$responseJson = [
|
||||
|
@ -495,18 +495,18 @@ App::get('/v1/mock/tests/general/oauth2/token')
|
|||
|
||||
if ($grantType === 'authorization_code') {
|
||||
if ($code !== 'abcdef') {
|
||||
throw new Exception('Invalid token', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid token');
|
||||
}
|
||||
|
||||
$response->json($responseJson);
|
||||
} elseif ($grantType === 'refresh_token') {
|
||||
if ($refreshToken !== 'tuvwxyz') {
|
||||
throw new Exception('Invalid refresh token', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid refresh token');
|
||||
}
|
||||
|
||||
$response->json($responseJson);
|
||||
} else {
|
||||
throw new Exception('Invalid grant type', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid grant type');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -520,7 +520,7 @@ App::get('/v1/mock/tests/general/oauth2/user')
|
|||
->action(function (string $token, Response $response) {
|
||||
|
||||
if ($token != '123456') {
|
||||
throw new Exception('Invalid token', 400, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Invalid token');
|
||||
}
|
||||
|
||||
$response->json([
|
||||
|
@ -571,7 +571,7 @@ App::shutdown()
|
|||
$tests = (\file_exists($path)) ? \json_decode(\file_get_contents($path), true) : [];
|
||||
|
||||
if (!\is_array($tests)) {
|
||||
throw new Exception('Failed to read results', 500, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Failed to read results', 500);
|
||||
}
|
||||
|
||||
$result[$route->getMethod() . ':' . $route->getPath()] = true;
|
||||
|
@ -579,7 +579,7 @@ App::shutdown()
|
|||
$tests = \array_merge($tests, $result);
|
||||
|
||||
if (!\file_put_contents($path, \json_encode($tests), LOCK_EX)) {
|
||||
throw new Exception('Failed to save results', 500, Exception::GENERAL_MOCK);
|
||||
throw new Exception(Exception::GENERAL_MOCK, 'Failed to save results', 500);
|
||||
}
|
||||
|
||||
$response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getPath() . ':passed']), Response::MODEL_MOCK);
|
||||
|
|
|
@ -39,7 +39,7 @@ App::init()
|
|||
$route = $utopia->match($request);
|
||||
|
||||
if ($project->isEmpty() && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope
|
||||
throw new Exception('Missing or unknown project ID', 400, Exception::PROJECT_UNKNOWN);
|
||||
throw new Exception(Exception::PROJECT_UNKNOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,7 +92,7 @@ App::init()
|
|||
&& $abuse->check()) // Abuse is not disabled
|
||||
&& (!$isAppUser && !$isPrivilegedUser)
|
||||
) { // User is not an admin or API key
|
||||
throw new Exception('Too many requests', 429, Exception::GENERAL_RATE_LIMIT_EXCEEDED);
|
||||
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,36 +154,37 @@ App::init()
|
|||
switch ($route->getLabel('auth.type', '')) {
|
||||
case 'emailPassword':
|
||||
if (($auths['emailPassword'] ?? true) === false) {
|
||||
throw new Exception('Email / Password authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Email / Password authentication is disabled for this project');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'magic-url':
|
||||
if ($project->getAttribute('usersAuthMagicURL', true) === false) {
|
||||
throw new Exception('Magic URL authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Magic URL authentication is disabled for this project');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'anonymous':
|
||||
if (($auths['anonymous'] ?? true) === false) {
|
||||
throw new Exception('Anonymous authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Anonymous authentication is disabled for this project');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'invites':
|
||||
if (($auths['invites'] ?? true) === false) {
|
||||
throw new Exception('Invites authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Invites authentication is disabled for this project');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'jwt':
|
||||
if (($auths['JWT'] ?? true) === false) {
|
||||
throw new Exception('JWT authentication is disabled for this project', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'JWT authentication is disabled for this project');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unsupported authentication route', 501, Exception::USER_AUTH_METHOD_UNSUPPORTED);
|
||||
throw new Exception(Exception::USER_AUTH_METHOD_UNSUPPORTED, 'Unsupported authentication route');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -512,9 +512,9 @@ App::get('/console/version')
|
|||
if ($version && isset($version['version'])) {
|
||||
return $response->json(['version' => $version['version']]);
|
||||
} else {
|
||||
throw new Exception('Failed to check for a newer version', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to check for a newer version');
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
throw new Exception('Failed to check for a newer version', 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to check for a newer version');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -458,7 +458,7 @@ $register->set('logger', function () {
|
|||
}
|
||||
|
||||
if (!Logger::hasProvider($providerName)) {
|
||||
throw new Exception("Logging provider not supported. Logging disabled.", 500, Exception::GENERAL_SERVER_ERROR);
|
||||
throw new Exception(Exception::GENERAL_SERVER_ERROR, "Logging provider not supported. Logging is disabled");
|
||||
}
|
||||
|
||||
$classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName);
|
||||
|
@ -828,7 +828,7 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
|
|||
try {
|
||||
$payload = $jwt->decode($authJWT);
|
||||
} catch (JWTException $error) {
|
||||
throw new Exception('Failed to verify JWT. ' . $error->getMessage(), 401, Exception::USER_JWT_INVALID);
|
||||
throw new Exception(Exception::USER_JWT_INVALID, 'Failed to verify JWT. ' . $error->getMessage());
|
||||
}
|
||||
|
||||
$jwtUserId = $payload['userId'] ?? '';
|
||||
|
|
|
@ -595,7 +595,7 @@ services:
|
|||
- _APP_REDIS_PASS
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
image: mariadb:10.8.3 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
|
@ -611,7 +611,7 @@ services:
|
|||
command: 'mysqld --innodb-flush-method=fsync'
|
||||
|
||||
redis:
|
||||
image: redis:6.2-alpine
|
||||
image: redis:7.0.4-alpine
|
||||
container_name: appwrite-redis
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\E2E\\": "tests/e2e",
|
||||
"Tests\\Unit\\": "tests/unit",
|
||||
"Appwrite\\Tests\\": "tests/extensions"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -639,7 +639,7 @@ services:
|
|||
- _APP_REDIS_PASS
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
image: mariadb:10.8.3 # fix issues when upgrading using: mysql_upgrade -u root -p
|
||||
container_name: appwrite-mariadb
|
||||
<<: *x-logging
|
||||
networks:
|
||||
|
@ -669,7 +669,7 @@ services:
|
|||
# - SMARTHOST_PORT=587
|
||||
|
||||
redis:
|
||||
image: redis:6.2-alpine
|
||||
image: redis:7.0.4-alpine
|
||||
<<: *x-logging
|
||||
container_name: appwrite-redis
|
||||
command: >
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</extensions>
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>./tests/unit/</directory>
|
||||
<directory>./tests/unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="e2e">
|
||||
<file>./tests/e2e/Client.php</file>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Appwrite\Extend;
|
||||
|
||||
use Utopia\Config\Config;
|
||||
|
||||
class Exception extends \Exception
|
||||
{
|
||||
/**
|
||||
|
@ -47,7 +49,7 @@ class Exception extends \Exception
|
|||
public const GENERAL_ROUTE_NOT_FOUND = 'general_route_not_found';
|
||||
public const GENERAL_CURSOR_NOT_FOUND = 'general_cursor_not_found';
|
||||
public const GENERAL_SERVER_ERROR = 'general_server_error';
|
||||
public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported';
|
||||
public const GENERAL_PROTOCOL_UNSUPPORTED = 'general_protocol_unsupported';
|
||||
|
||||
/** Users */
|
||||
public const USER_COUNT_EXCEEDED = 'user_count_exceeded';
|
||||
|
@ -69,6 +71,7 @@ class Exception extends \Exception
|
|||
public const USER_AUTH_METHOD_UNSUPPORTED = 'user_auth_method_unsupported';
|
||||
public const USER_PHONE_ALREADY_EXISTS = 'user_phone_already_exists';
|
||||
public const USER_PHONE_NOT_FOUND = 'user_phone_not_found';
|
||||
public const USER_MISSING_ID = 'user_missing_id';
|
||||
|
||||
/** Teams */
|
||||
public const TEAM_NOT_FOUND = 'team_not_found';
|
||||
|
@ -80,6 +83,7 @@ class Exception extends \Exception
|
|||
|
||||
/** Membership */
|
||||
public const MEMBERSHIP_NOT_FOUND = 'membership_not_found';
|
||||
public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed';
|
||||
|
||||
/** Avatars */
|
||||
public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found';
|
||||
|
@ -116,8 +120,8 @@ class Exception extends \Exception
|
|||
public const EXECUTION_NOT_FOUND = 'execution_not_found';
|
||||
|
||||
/** Databases */
|
||||
public const DATABASE_NOT_FOUND = 'database_not_found';
|
||||
public const DATABASE_ALREADY_EXISTS = 'database_already_exists';
|
||||
public const DATABASE_NOT_FOUND = 'database_not_found';
|
||||
public const DATABASE_ALREADY_EXISTS = 'database_already_exists';
|
||||
|
||||
/** Collections */
|
||||
public const COLLECTION_NOT_FOUND = 'collection_not_found';
|
||||
|
@ -152,7 +156,6 @@ class Exception extends \Exception
|
|||
public const PROJECT_PROVIDER_UNSUPPORTED = 'project_provider_unsupported';
|
||||
public const PROJECT_INVALID_SUCCESS_URL = 'project_invalid_success_url';
|
||||
public const PROJECT_INVALID_FAILURE_URL = 'project_invalid_failure_url';
|
||||
public const PROJECT_MISSING_USER_ID = 'project_missing_user_id';
|
||||
public const PROJECT_RESERVED_PROJECT = 'project_reserved_project';
|
||||
public const PROJECT_KEY_EXPIRED = 'project_key_expired';
|
||||
|
||||
|
@ -170,14 +173,22 @@ class Exception extends \Exception
|
|||
public const DOMAIN_ALREADY_EXISTS = 'domain_already_exists';
|
||||
public const DOMAIN_VERIFICATION_FAILED = 'domain_verification_failed';
|
||||
|
||||
protected $type = '';
|
||||
|
||||
private $type = '';
|
||||
|
||||
public function __construct(string $message, int $code = 0, string $type = Exception::GENERAL_UNKNOWN, \Throwable $previous = null)
|
||||
public function __construct(string $type = Exception::GENERAL_UNKNOWN, string $message = null, int $code = null, \Throwable $previous = null)
|
||||
{
|
||||
$this->errors = Config::getParam('errors');
|
||||
$this->type = $type;
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
if (isset($this->errors[$type])) {
|
||||
$this->code = $this->errors[$type]['code'];
|
||||
$this->message = $this->errors[$type]['description'];
|
||||
}
|
||||
|
||||
$this->message = $message ?? $this->message;
|
||||
$this->code = $code ?? $this->code;
|
||||
|
||||
parent::__construct($this->message, $this->code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -201,7 +201,7 @@ class Response extends SwooleResponse
|
|||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $payload = [];
|
||||
protected array $payload = [];
|
||||
|
||||
/**
|
||||
* Response constructor.
|
||||
|
@ -303,8 +303,7 @@ class Response extends SwooleResponse
|
|||
// Verification
|
||||
// Recovery
|
||||
// Tests (keep last)
|
||||
->setModel(new Mock())
|
||||
;
|
||||
->setModel(new Mock());
|
||||
|
||||
parent::__construct($response);
|
||||
}
|
||||
|
@ -394,12 +393,13 @@ class Response extends SwooleResponse
|
|||
|
||||
if ($model->isAny()) {
|
||||
$this->payload = $document->getArrayCopy();
|
||||
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
foreach ($model->getRules() as $key => $rule) {
|
||||
if (!$document->isSet($key) && $rule['require']) { // do not set attribute in response if not required
|
||||
if (!is_null($rule['default'])) {
|
||||
if (!$document->isSet($key) && $rule['required']) { // do not set attribute in response if not required
|
||||
if (\array_key_exists('default', $rule)) {
|
||||
$document->setAttribute($key, $rule['default']);
|
||||
} else {
|
||||
throw new Exception('Model ' . $model->getName() . ' is missing response key: ' . $key);
|
||||
|
@ -411,7 +411,7 @@ class Response extends SwooleResponse
|
|||
throw new Exception($key . ' must be an array of type ' . $rule['type']);
|
||||
}
|
||||
|
||||
foreach ($data[$key] as &$item) {
|
||||
foreach ($data[$key] as $index => $item) {
|
||||
if ($item instanceof Document) {
|
||||
if (\is_array($rule['type'])) {
|
||||
foreach ($rule['type'] as $type) {
|
||||
|
@ -435,9 +435,13 @@ class Response extends SwooleResponse
|
|||
throw new Exception('Missing model for rule: ' . $ruleType);
|
||||
}
|
||||
|
||||
$item = $this->output($item, $ruleType);
|
||||
$data[$key][$index] = $this->output($item, $ruleType);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($data[$key] instanceof Document) {
|
||||
$data[$key] = $this->output($data[$key], $rule['type']);
|
||||
}
|
||||
}
|
||||
|
||||
$output[$key] = $data[$key];
|
||||
|
@ -468,8 +472,7 @@ class Response extends SwooleResponse
|
|||
|
||||
$this
|
||||
->setContentType(Response::CONTENT_TYPE_YAML)
|
||||
->send(yaml_emit($data, YAML_UTF8_ENCODING))
|
||||
;
|
||||
->send(yaml_emit($data, YAML_UTF8_ENCODING));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,22 +17,28 @@ abstract class Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $none = false;
|
||||
protected bool $none = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $any = false;
|
||||
protected bool $any = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = true;
|
||||
protected bool $public = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $rules = [];
|
||||
protected array $rules = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public array $conditions = [];
|
||||
|
||||
|
||||
/**
|
||||
* Filter Document Structure
|
||||
|
@ -78,12 +84,10 @@ abstract class Model
|
|||
protected function addRule(string $key, array $options): self
|
||||
{
|
||||
$this->rules[$key] = array_merge([
|
||||
'require' => true,
|
||||
'type' => '',
|
||||
'required' => true,
|
||||
'array' => false,
|
||||
'description' => '',
|
||||
'default' => null,
|
||||
'example' => '',
|
||||
'array' => false
|
||||
'example' => ''
|
||||
], $options);
|
||||
|
||||
return $this;
|
||||
|
@ -94,7 +98,7 @@ abstract class Model
|
|||
$list = [];
|
||||
|
||||
foreach ($this->rules as $key => $rule) {
|
||||
if ($rule['require'] ?? false) {
|
||||
if ($rule['required'] ?? false) {
|
||||
$list[] = $key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ class Any extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $any = true;
|
||||
protected bool $any = true;
|
||||
|
||||
/**
|
||||
* Get Name
|
||||
|
|
|
@ -39,7 +39,6 @@ class Attribute extends Model
|
|||
'description' => 'Is attribute an array?',
|
||||
'default' => false,
|
||||
'example' => false,
|
||||
'require' => false
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ class AttributeBoolean extends Attribute
|
|||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => false,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
'example' => false
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@ class AttributeEmail extends Attribute
|
|||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 'default@example.com',
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ class AttributeEnum extends Attribute
|
|||
'default' => null,
|
||||
'example' => 'element',
|
||||
'array' => true,
|
||||
'require' => true,
|
||||
])
|
||||
->addRule('format', [
|
||||
'type' => self::TYPE_STRING,
|
||||
|
@ -45,8 +44,6 @@ class AttributeEnum extends Attribute
|
|||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 'element',
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -29,24 +29,18 @@ class AttributeFloat extends Attribute
|
|||
'description' => 'Minimum value to enforce for new documents.',
|
||||
'default' => null,
|
||||
'example' => 1.5,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
->addRule('max', [
|
||||
'type' => self::TYPE_FLOAT,
|
||||
'description' => 'Maximum value to enforce for new documents.',
|
||||
'default' => null,
|
||||
'example' => 10.5,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
->addRule('default', [
|
||||
'type' => self::TYPE_FLOAT,
|
||||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 2.5,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@ class AttributeIP extends Attribute
|
|||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => '192.0.2.0',
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -29,24 +29,18 @@ class AttributeInteger extends Attribute
|
|||
'description' => 'Minimum value to enforce for new documents.',
|
||||
'default' => null,
|
||||
'example' => 1,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
->addRule('max', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Maximum value to enforce for new documents.',
|
||||
'default' => null,
|
||||
'example' => 10,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
->addRule('default', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 10,
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ class AttributeString extends Attribute
|
|||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 'default',
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@ class AttributeURL extends Attribute
|
|||
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
|
||||
'default' => null,
|
||||
'example' => 'http://example.com',
|
||||
'array' => false,
|
||||
'require' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class BaseList extends Model
|
||||
|
@ -10,12 +9,12 @@ class BaseList extends Model
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $name = '';
|
||||
protected string $name = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type = '';
|
||||
protected string $type = '';
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
|
|
|
@ -10,7 +10,7 @@ class Domain extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ class ErrorDev extends Error
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -41,7 +41,6 @@ class Index extends Model
|
|||
'default' => [],
|
||||
'example' => [],
|
||||
'array' => true,
|
||||
'required' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ class Key extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ class Metric extends Model
|
|||
'default' => -1,
|
||||
'example' => 1,
|
||||
])
|
||||
->addRule('timestamp', [
|
||||
->addRule('date', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'The UNIX timestamp at which this metric was aggregated.',
|
||||
'default' => 0,
|
||||
|
|
|
@ -10,7 +10,7 @@ class None extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $none = true;
|
||||
protected bool $none = true;
|
||||
|
||||
/**
|
||||
* Get Name
|
||||
|
|
|
@ -10,7 +10,7 @@ class Platform extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -6,11 +6,6 @@ use Appwrite\Utopia\Response;
|
|||
|
||||
class Preferences extends Any
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $any = true;
|
||||
|
||||
/**
|
||||
* Get Name
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@ class Project extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ class Webhook extends Model
|
|||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $public = false;
|
||||
protected bool $public = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Auth;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Utopia\Database\DateTime;
|
||||
|
@ -11,10 +11,6 @@ use Utopia\Database\Database;
|
|||
|
||||
class AuthTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Roles
|
||||
*/
|
||||
|
@ -24,7 +20,7 @@ class AuthTest extends TestCase
|
|||
Authorization::setRole('role:all');
|
||||
}
|
||||
|
||||
public function testCookieName()
|
||||
public function testCookieName(): void
|
||||
{
|
||||
$name = 'cookie-name';
|
||||
|
||||
|
@ -32,7 +28,7 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(Auth::$cookieName, $name);
|
||||
}
|
||||
|
||||
public function testEncodeDecodeSession()
|
||||
public function testEncodeDecodeSession(): void
|
||||
{
|
||||
$id = 'id';
|
||||
$secret = 'secret';
|
||||
|
@ -42,13 +38,13 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(Auth::decodeSession($session), ['id' => $id, 'secret' => $secret]);
|
||||
}
|
||||
|
||||
public function testHash()
|
||||
public function testHash(): void
|
||||
{
|
||||
$secret = 'secret';
|
||||
$this->assertEquals(Auth::hash($secret), '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b');
|
||||
}
|
||||
|
||||
public function testPassword()
|
||||
public function testPassword(): void
|
||||
{
|
||||
$secret = 'secret';
|
||||
$static = '$2y$08$PDbMtV18J1KOBI9tIYabBuyUwBrtXPGhLxCy9pWP6xkldVOKLrLKy';
|
||||
|
@ -58,19 +54,19 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(Auth::passwordVerify($secret, $static), true);
|
||||
}
|
||||
|
||||
public function testPasswordGenerator()
|
||||
public function testPasswordGenerator(): void
|
||||
{
|
||||
$this->assertEquals(\mb_strlen(Auth::passwordGenerator()), 40);
|
||||
$this->assertEquals(\mb_strlen(Auth::passwordGenerator(5)), 10);
|
||||
}
|
||||
|
||||
public function testTokenGenerator()
|
||||
public function testTokenGenerator(): void
|
||||
{
|
||||
$this->assertEquals(\mb_strlen(Auth::tokenGenerator()), 256);
|
||||
$this->assertEquals(\mb_strlen(Auth::tokenGenerator(5)), 10);
|
||||
}
|
||||
|
||||
public function testSessionVerify()
|
||||
public function testSessionVerify(): void
|
||||
{
|
||||
$secret = 'secret1';
|
||||
$hash = Auth::hash($secret);
|
||||
|
@ -114,7 +110,7 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(Auth::sessionVerify($tokens2, 'false-secret'), false);
|
||||
}
|
||||
|
||||
public function testTokenVerify()
|
||||
public function testTokenVerify(): void
|
||||
{
|
||||
$secret = 'secret1';
|
||||
$hash = Auth::hash($secret);
|
||||
|
@ -171,7 +167,7 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_RECOVERY, 'false-secret'), false);
|
||||
}
|
||||
|
||||
public function testIsPrivilegedUser()
|
||||
public function testIsPrivilegedUser(): void
|
||||
{
|
||||
$this->assertEquals(false, Auth::isPrivilegedUser([]));
|
||||
$this->assertEquals(false, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_GUEST]));
|
||||
|
@ -188,7 +184,7 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(true, Auth::isPrivilegedUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_ADMIN, 'role:' . Auth::USER_ROLE_DEVELOPER]));
|
||||
}
|
||||
|
||||
public function testIsAppUser()
|
||||
public function testIsAppUser(): void
|
||||
{
|
||||
$this->assertEquals(false, Auth::isAppUser([]));
|
||||
$this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_GUEST]));
|
||||
|
@ -205,7 +201,7 @@ class AuthTest extends TestCase
|
|||
$this->assertEquals(false, Auth::isAppUser(['role:' . Auth::USER_ROLE_OWNER, 'role:' . Auth::USER_ROLE_ADMIN, 'role:' . Auth::USER_ROLE_DEVELOPER]));
|
||||
}
|
||||
|
||||
public function testGuestRoles()
|
||||
public function testGuestRoles(): void
|
||||
{
|
||||
$user = new Document([
|
||||
'$id' => ''
|
||||
|
@ -216,7 +212,7 @@ class AuthTest extends TestCase
|
|||
$this->assertContains('role:guest', $roles);
|
||||
}
|
||||
|
||||
public function testUserRoles()
|
||||
public function testUserRoles(): void
|
||||
{
|
||||
$user = new Document([
|
||||
'$id' => '123',
|
||||
|
@ -249,7 +245,7 @@ class AuthTest extends TestCase
|
|||
$this->assertContains('team:def/guest', $roles);
|
||||
}
|
||||
|
||||
public function testPrivilegedUserRoles()
|
||||
public function testPrivilegedUserRoles(): void
|
||||
{
|
||||
Authorization::setRole('role:' . Auth::USER_ROLE_OWNER);
|
||||
$user = new Document([
|
||||
|
@ -283,7 +279,7 @@ class AuthTest extends TestCase
|
|||
$this->assertContains('team:def/guest', $roles);
|
||||
}
|
||||
|
||||
public function testAppUserRoles()
|
||||
public function testAppUserRoles(): void
|
||||
{
|
||||
Authorization::setRole('role:' . Auth::USER_ROLE_APP);
|
||||
$user = new Document([
|
||||
|
|
|
@ -1,27 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Auth\Validator;
|
||||
|
||||
use Appwrite\Auth\Validator\Password;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PasswordTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Password
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?Password $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->object = new Password();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$this->assertEquals($this->object->isValid(false), false);
|
||||
$this->assertEquals($this->object->isValid(null), false);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Auth\Validator;
|
||||
|
||||
use Appwrite\Auth\Validator\Phone;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -14,11 +14,7 @@ class PhoneTest extends TestCase
|
|||
$this->object = new Phone();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$this->assertEquals($this->object->isValid(false), false);
|
||||
$this->assertEquals($this->object->isValid(null), false);
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\DSN;
|
||||
|
||||
use Appwrite\DSN\DSN;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DSNTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testSuccess(): void
|
||||
{
|
||||
$dsn = new DSN("mariadb://user:password@localhost:3306/database?charset=utf8&timezone=UTC");
|
||||
|
@ -84,6 +76,6 @@ class DSNTest extends TestCase
|
|||
public function testFail(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$dsn = new DSN("mariadb://");
|
||||
new DSN("mariadb://");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Detector;
|
||||
|
||||
use Appwrite\Detector\Detector;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DetectorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Detector
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?Detector $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -21,7 +18,7 @@ class DetectorTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testGetOS()
|
||||
public function testGetOS(): void
|
||||
{
|
||||
$this->assertEquals($this->object->getOS(), [
|
||||
'osCode' => 'WIN',
|
||||
|
@ -30,7 +27,7 @@ class DetectorTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
public function testGetClient()
|
||||
public function testGetClient(): void
|
||||
{
|
||||
$this->assertEquals($this->object->getClient(), [
|
||||
'clientType' => 'browser',
|
||||
|
@ -42,7 +39,7 @@ class DetectorTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
public function testGetDevice()
|
||||
public function testGetDevice(): void
|
||||
{
|
||||
$this->assertEquals($this->object->getDevice(), [
|
||||
'deviceName' => 'desktop',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Docker;
|
||||
|
||||
use Appwrite\Docker\Compose;
|
||||
use Exception;
|
||||
|
@ -8,11 +8,7 @@ use PHPUnit\Framework\TestCase;
|
|||
|
||||
class ComposeTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Compose
|
||||
*/
|
||||
protected $object = null;
|
||||
|
||||
protected ?Compose $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -25,16 +21,12 @@ class ComposeTest extends TestCase
|
|||
$this->object = new Compose($data);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testVersion()
|
||||
public function testVersion(): void
|
||||
{
|
||||
$this->assertEquals('3', $this->object->getVersion());
|
||||
}
|
||||
|
||||
public function testServices()
|
||||
public function testServices(): void
|
||||
{
|
||||
$this->assertCount(17, $this->object->getServices());
|
||||
$this->assertEquals('appwrite-telegraf', $this->object->getService('telegraf')->getContainerName());
|
||||
|
@ -44,12 +36,12 @@ class ComposeTest extends TestCase
|
|||
$this->assertEquals(['2080' => '80', '2443' => '443', '8080' => '8080'], $this->object->getService('traefik')->getPorts());
|
||||
}
|
||||
|
||||
public function testNetworks()
|
||||
public function testNetworks(): void
|
||||
{
|
||||
$this->assertCount(2, $this->object->getNetworks());
|
||||
}
|
||||
|
||||
public function testVolumes()
|
||||
public function testVolumes(): void
|
||||
{
|
||||
$this->assertCount(9, $this->object->getVolumes());
|
||||
$this->assertEquals('appwrite-mariadb', $this->object->getVolumes()[0]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Docker;
|
||||
|
||||
use Appwrite\Docker\Env;
|
||||
use Exception;
|
||||
|
@ -8,11 +8,7 @@ use PHPUnit\Framework\TestCase;
|
|||
|
||||
class EnvTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Env
|
||||
*/
|
||||
protected $object = null;
|
||||
|
||||
protected ?Env $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -25,11 +21,7 @@ class EnvTest extends TestCase
|
|||
$this->object = new Env($data);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testVars()
|
||||
public function testVars(): void
|
||||
{
|
||||
$this->object->setVar('_APP_TEST', 'value4');
|
||||
|
||||
|
@ -39,7 +31,7 @@ class EnvTest extends TestCase
|
|||
$this->assertEquals('value4', $this->object->getVar('_APP_TEST'));
|
||||
}
|
||||
|
||||
public function testExport()
|
||||
public function testExport(): void
|
||||
{
|
||||
$this->assertEquals("_APP_X=value1
|
||||
_APP_Y=value2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Event;
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use InvalidArgumentException;
|
||||
|
@ -9,15 +9,8 @@ use Utopia\App;
|
|||
|
||||
class EventTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Event
|
||||
*/
|
||||
protected $object = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $queue = '';
|
||||
protected ?Event $object = null;
|
||||
protected string $queue = '';
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -29,11 +22,7 @@ class EventTest extends TestCase
|
|||
$this->object = new Event($this->queue, 'TestsV1');
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testQueue()
|
||||
public function testQueue(): void
|
||||
{
|
||||
$this->assertEquals($this->queue, $this->object->getQueue());
|
||||
|
||||
|
@ -44,7 +33,7 @@ class EventTest extends TestCase
|
|||
$this->object->setQueue($this->queue);
|
||||
}
|
||||
|
||||
public function testClass()
|
||||
public function testClass(): void
|
||||
{
|
||||
$this->assertEquals('TestsV1', $this->object->getClass());
|
||||
|
||||
|
@ -55,7 +44,7 @@ class EventTest extends TestCase
|
|||
$this->object->setClass('TestsV1');
|
||||
}
|
||||
|
||||
public function testParams()
|
||||
public function testParams(): void
|
||||
{
|
||||
$this->object
|
||||
->setParam('eventKey1', 'eventValue1')
|
||||
|
@ -69,7 +58,7 @@ class EventTest extends TestCase
|
|||
$this->assertEquals(\Resque::size($this->queue), 1);
|
||||
}
|
||||
|
||||
public function testReset()
|
||||
public function testReset(): void
|
||||
{
|
||||
$this->object
|
||||
->setParam('eventKey1', 'eventValue1')
|
||||
|
@ -85,7 +74,7 @@ class EventTest extends TestCase
|
|||
$this->assertEquals(null, $this->object->getParam('eventKey3'));
|
||||
}
|
||||
|
||||
public function testGenerateEvents()
|
||||
public function testGenerateEvents(): void
|
||||
{
|
||||
$event = Event::generateEvents('users.[userId].create', [
|
||||
'userId' => 'torsten'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Event\Validator;
|
||||
|
||||
use Appwrite\Event\Validator\Event;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -20,7 +20,7 @@ class EventValidatorTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\General;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CollectionsTest extends TestCase
|
||||
{
|
||||
protected $collections;
|
||||
protected array $collections;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->collections = require('app/config/collections.php');
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testDuplicateRules()
|
||||
public function testDuplicateRules(): void
|
||||
{
|
||||
foreach ($this->collections as $key => $collection) {
|
||||
if (array_key_exists('attributes', $collection)) {
|
||||
|
|
|
@ -1,116 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\General;
|
||||
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ExtensionsTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
// Core
|
||||
// ctype
|
||||
// curl
|
||||
// date
|
||||
// fileinfo
|
||||
// filter
|
||||
// ftp
|
||||
// hash
|
||||
// iconv
|
||||
// libxml
|
||||
// mysqlnd
|
||||
// pcre
|
||||
// pdo_mysql
|
||||
// pdo_sqlite
|
||||
// Phar
|
||||
// posix
|
||||
// readline
|
||||
// Reflection
|
||||
// session
|
||||
// SimpleXML
|
||||
// sockets
|
||||
// sodium
|
||||
// SPL
|
||||
// sqlite3
|
||||
// standard
|
||||
// tokenizer
|
||||
// xml
|
||||
// xmlreader
|
||||
// xmlwriter
|
||||
// zlib
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function testPHPRedis()
|
||||
public function testPHPRedis(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('redis'));
|
||||
}
|
||||
|
||||
public function testSwoole()
|
||||
public function testSwoole(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('swoole'));
|
||||
}
|
||||
|
||||
public function testYAML()
|
||||
public function testYAML(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('yaml'));
|
||||
}
|
||||
|
||||
public function testOPCache()
|
||||
public function testOPCache(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('Zend OPcache'));
|
||||
}
|
||||
|
||||
public function testDOM()
|
||||
public function testDOM(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('dom'));
|
||||
}
|
||||
|
||||
public function testPDO()
|
||||
public function testPDO(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('PDO'));
|
||||
}
|
||||
|
||||
public function testImagick()
|
||||
public function testImagick(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('imagick'));
|
||||
}
|
||||
|
||||
public function testJSON()
|
||||
public function testJSON(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('json'));
|
||||
}
|
||||
|
||||
public function testCURL()
|
||||
public function testCURL(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('curl'));
|
||||
}
|
||||
|
||||
public function testMBString()
|
||||
public function testMBString(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('mbstring'));
|
||||
}
|
||||
|
||||
public function testOPENSSL()
|
||||
public function testOPENSSL(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('openssl'));
|
||||
}
|
||||
|
||||
public function testZLIB()
|
||||
public function testZLIB(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('zlib'));
|
||||
}
|
||||
|
||||
public function testSockets()
|
||||
public function testSockets(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('sockets'));
|
||||
}
|
||||
|
||||
public function testMaxminddb()
|
||||
public function testMaxminddb(): void
|
||||
{
|
||||
$this->assertEquals(true, extension_loaded('maxminddb'));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Messaging;
|
||||
|
||||
use Appwrite\Auth\Auth;
|
||||
use Utopia\Database\Document;
|
||||
|
@ -106,7 +106,7 @@ class MessagingChannelsTest extends TestCase
|
|||
$this->connectionsCount = 0;
|
||||
}
|
||||
|
||||
public function testSubscriptions()
|
||||
public function testSubscriptions(): void
|
||||
{
|
||||
/**
|
||||
* Check for 1 project.
|
||||
|
@ -148,7 +148,7 @@ class MessagingChannelsTest extends TestCase
|
|||
/**
|
||||
* Tests Wildcard (role:all) Permissions on every channel.
|
||||
*/
|
||||
public function testWildcardPermission()
|
||||
public function testWildcardPermission(): void
|
||||
{
|
||||
foreach ($this->allChannels as $index => $channel) {
|
||||
$event = [
|
||||
|
@ -177,7 +177,7 @@ class MessagingChannelsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
public function testRolePermissions()
|
||||
public function testRolePermissions(): void
|
||||
{
|
||||
$roles = ['role:guest', 'role:member'];
|
||||
foreach ($this->allChannels as $index => $channel) {
|
||||
|
@ -211,7 +211,7 @@ class MessagingChannelsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
public function testUserPermissions()
|
||||
public function testUserPermissions(): void
|
||||
{
|
||||
foreach ($this->allChannels as $index => $channel) {
|
||||
$permissions = [];
|
||||
|
@ -244,7 +244,7 @@ class MessagingChannelsTest extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
public function testTeamPermissions()
|
||||
public function testTeamPermissions(): void
|
||||
{
|
||||
foreach ($this->allChannels as $index => $channel) {
|
||||
$permissions = [];
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Messaging;
|
||||
|
||||
use Appwrite\Messaging\Adapter\Realtime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MessagingGuestTest extends TestCase
|
||||
{
|
||||
public function testGuest()
|
||||
public function testGuest(): void
|
||||
{
|
||||
$realtime = new Realtime();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Messaging;
|
||||
|
||||
use Utopia\Database\Document;
|
||||
use Appwrite\Messaging\Adapter\Realtime;
|
||||
|
@ -16,7 +16,7 @@ class MessagingTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testUser()
|
||||
public function testUser(): void
|
||||
{
|
||||
$realtime = new Realtime();
|
||||
|
||||
|
@ -134,7 +134,7 @@ class MessagingTest extends TestCase
|
|||
$this->assertEmpty($realtime->subscriptions);
|
||||
}
|
||||
|
||||
public function testConvertChannelsGuest()
|
||||
public function testConvertChannelsGuest(): void
|
||||
{
|
||||
$user = new Document([
|
||||
'$id' => ''
|
||||
|
@ -157,7 +157,7 @@ class MessagingTest extends TestCase
|
|||
$this->assertArrayNotHasKey('account.456', $channels);
|
||||
}
|
||||
|
||||
public function testConvertChannelsUser()
|
||||
public function testConvertChannelsUser(): void
|
||||
{
|
||||
$user = new Document([
|
||||
'$id' => '123',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Migration;
|
||||
|
||||
use Appwrite\Migration\Migration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -34,7 +34,7 @@ abstract class MigrationTest extends TestCase
|
|||
/**
|
||||
* Check versions array integrity.
|
||||
*/
|
||||
public function testMigrationVersions()
|
||||
public function testMigrationVersions(): void
|
||||
{
|
||||
require_once __DIR__ . '/../../../app/init.php';
|
||||
|
||||
|
@ -45,7 +45,7 @@ abstract class MigrationTest extends TestCase
|
|||
$this->assertArrayHasKey(APP_VERSION_STABLE, Migration::$versions);
|
||||
}
|
||||
|
||||
public function testHasDifference()
|
||||
public function testHasDifference(): void
|
||||
{
|
||||
$this->assertFalse(Migration::hasDifference([], []));
|
||||
$this->assertFalse(Migration::hasDifference([
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Migration;
|
||||
|
||||
use ReflectionClass;
|
||||
use Appwrite\Migration\Version\V12;
|
||||
|
@ -16,7 +16,7 @@ class MigrationV12Test extends MigrationTest
|
|||
$this->method->setAccessible(true);
|
||||
}
|
||||
|
||||
public function testMigrationProjects()
|
||||
public function testMigrationProjects(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'project',
|
||||
|
@ -30,7 +30,7 @@ class MigrationV12Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('search'), 'project Appwrite');
|
||||
}
|
||||
|
||||
public function testMigrationUsers()
|
||||
public function testMigrationUsers(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'user',
|
||||
|
@ -42,7 +42,7 @@ class MigrationV12Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('search'), 'user test@appwrite.io Torsten Dittmann');
|
||||
}
|
||||
|
||||
public function testMigrationTeams()
|
||||
public function testMigrationTeams(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'team',
|
||||
|
@ -53,7 +53,7 @@ class MigrationV12Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('search'), 'team Appwrite');
|
||||
}
|
||||
|
||||
public function testMigrationFunctions()
|
||||
public function testMigrationFunctions(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'function',
|
||||
|
@ -65,7 +65,7 @@ class MigrationV12Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('search'), 'function My Function php-8.0');
|
||||
}
|
||||
|
||||
public function testMigrationExecutions()
|
||||
public function testMigrationExecutions(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'execution',
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Migration;
|
||||
|
||||
use Appwrite\Event\Validator\Event;
|
||||
use ReflectionClass;
|
||||
use Appwrite\Migration\Version\V13;
|
||||
use Utopia\Database\Document;
|
||||
|
@ -17,7 +16,7 @@ class MigrationV13Test extends MigrationTest
|
|||
$this->method->setAccessible(true);
|
||||
}
|
||||
|
||||
public function testMigrateFunctions()
|
||||
public function testMigrateFunctions(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'func',
|
||||
|
@ -28,7 +27,7 @@ class MigrationV13Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('events'), ['users.*.create']);
|
||||
}
|
||||
|
||||
public function testMigrationWebhooks()
|
||||
public function testMigrationWebhooks(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'webh',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Migration;
|
||||
|
||||
use ReflectionClass;
|
||||
use Appwrite\Migration\Version\V14;
|
||||
|
@ -16,7 +16,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->method->setAccessible(true);
|
||||
}
|
||||
|
||||
public function testMigrateProjects()
|
||||
public function testMigrateProjects(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -28,7 +28,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('version'), '0.15.0');
|
||||
}
|
||||
|
||||
public function testMigrateKeys()
|
||||
public function testMigrateKeys(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -39,7 +39,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('expire'), 0);
|
||||
}
|
||||
|
||||
public function testMigrateWebhooks()
|
||||
public function testMigrateWebhooks(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -50,7 +50,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals(strlen($document->getAttribute('signatureKey')), 128);
|
||||
}
|
||||
|
||||
public function testMigrateUsers()
|
||||
public function testMigrateUsers(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -62,7 +62,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertFalse($document->getAttribute('phoneVerification'));
|
||||
}
|
||||
|
||||
public function testMigratePlatforms()
|
||||
public function testMigratePlatforms(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -77,7 +77,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getUpdatedAt(), 987654321);
|
||||
}
|
||||
|
||||
public function testMigrateFunctions()
|
||||
public function testMigrateFunctions(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -92,7 +92,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getUpdatedAt(), 987654321);
|
||||
}
|
||||
|
||||
public function testMigrateDeployments()
|
||||
public function testMigrateDeployments(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -104,7 +104,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getCreatedAt(), 123456789);
|
||||
}
|
||||
|
||||
public function testMigrateExecutions()
|
||||
public function testMigrateExecutions(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -116,7 +116,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getCreatedAt(), 123456789);
|
||||
}
|
||||
|
||||
public function testMigrateTeams()
|
||||
public function testMigrateTeams(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -128,7 +128,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getCreatedAt(), 123456789);
|
||||
}
|
||||
|
||||
public function testMigrateAudits()
|
||||
public function testMigrateAudits(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
@ -151,7 +151,7 @@ class MigrationV14Test extends MigrationTest
|
|||
$this->assertEquals($document->getAttribute('event'), 'databases.default.collections.movies.documents.avatar.create');
|
||||
}
|
||||
|
||||
public function testMigrateStats()
|
||||
public function testMigrateStats(): void
|
||||
{
|
||||
$document = $this->fixDocument(new Document([
|
||||
'$id' => 'appwrite',
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CNAMETest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var CNAME
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?CNAME $object = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -21,7 +18,7 @@ class CNAMETest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$this->assertEquals($this->object->isValid(''), false);
|
||||
$this->assertEquals($this->object->isValid(null), false);
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\Domain;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DomainTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Domain
|
||||
*/
|
||||
protected $domain = null;
|
||||
protected ?Domain $domain = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -22,7 +19,7 @@ class DomainTest extends TestCase
|
|||
$this->domain = null;
|
||||
}
|
||||
|
||||
public function testIsValid()
|
||||
public function testIsValid(): void
|
||||
{
|
||||
// Assertions
|
||||
$this->assertEquals(true, $this->domain->isValid('example.com'));
|
||||
|
|
|
@ -12,16 +12,14 @@
|
|||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
namespace Appwrite\Network\Validator;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\Email;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class EmailTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Email
|
||||
*/
|
||||
protected $email = null;
|
||||
protected ?Email $email = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -33,9 +31,8 @@ class EmailTest extends TestCase
|
|||
$this->email = null;
|
||||
}
|
||||
|
||||
public function testIsValid()
|
||||
public function testIsValid(): void
|
||||
{
|
||||
// Assertions
|
||||
$this->assertEquals(true, $this->email->isValid('email@domain.com'));
|
||||
$this->assertEquals(true, $this->email->isValid('firstname.lastname@domain.com'));
|
||||
$this->assertEquals(true, $this->email->isValid('email@subdomain.domain.com'));
|
||||
|
|
|
@ -12,16 +12,14 @@
|
|||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
namespace Appwrite\Network\Validator;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\Host;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class HostTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Host
|
||||
*/
|
||||
protected $host = null;
|
||||
protected ?Host $host = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
|
@ -33,7 +31,7 @@ class HostTest extends TestCase
|
|||
$this->host = null;
|
||||
}
|
||||
|
||||
public function testIsValid()
|
||||
public function testIsValid(): void
|
||||
{
|
||||
// Assertions
|
||||
$this->assertEquals($this->host->isValid('https://appwrite.io/link'), true);
|
||||
|
|
|
@ -12,71 +12,76 @@
|
|||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
namespace Appwrite\Network\Validator;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\IP;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class IPTest extends TestCase
|
||||
{
|
||||
protected ?IP $validator;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->validator = new IP();
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->validator = null;
|
||||
}
|
||||
|
||||
public function testIsValidIP()
|
||||
public function testIsValidIP(): void
|
||||
{
|
||||
$validator = new IP();
|
||||
|
||||
// Assertions
|
||||
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($validator->isValid(23.5), false);
|
||||
$this->assertEquals($validator->isValid('23.5'), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(true), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($validator->getType(), 'string');
|
||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
||||
$this->assertEquals($this->validator->isValid(null), false);
|
||||
$this->assertEquals($this->validator->isValid(true), false);
|
||||
$this->assertEquals($this->validator->isValid(false), false);
|
||||
$this->assertEquals($this->validator->getType(), 'string');
|
||||
}
|
||||
|
||||
public function testIsValidIPALL()
|
||||
public function testIsValidIPALL(): void
|
||||
{
|
||||
$validator = new IP(IP::ALL);
|
||||
$this->validator = new IP(IP::ALL);
|
||||
|
||||
// Assertions
|
||||
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($validator->isValid(23.5), false);
|
||||
$this->assertEquals($validator->isValid('23.5'), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(true), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
||||
$this->assertEquals($this->validator->isValid(null), false);
|
||||
$this->assertEquals($this->validator->isValid(true), false);
|
||||
$this->assertEquals($this->validator->isValid(false), false);
|
||||
}
|
||||
|
||||
public function testIsValidIPV4()
|
||||
public function testIsValidIPV4(): void
|
||||
{
|
||||
$validator = new IP(IP::V4);
|
||||
$this->validator = new IP(IP::V4);
|
||||
|
||||
// Assertions
|
||||
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), false);
|
||||
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($validator->isValid(23.5), false);
|
||||
$this->assertEquals($validator->isValid('23.5'), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(true), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), false);
|
||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), true);
|
||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
||||
$this->assertEquals($this->validator->isValid(null), false);
|
||||
$this->assertEquals($this->validator->isValid(true), false);
|
||||
$this->assertEquals($this->validator->isValid(false), false);
|
||||
}
|
||||
|
||||
public function testIsValidIPV6()
|
||||
public function testIsValidIPV6(): void
|
||||
{
|
||||
$validator = new IP(IP::V6);
|
||||
$this->validator = new IP(IP::V6);
|
||||
|
||||
// Assertions
|
||||
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($validator->isValid('109.67.204.101'), false);
|
||||
$this->assertEquals($validator->isValid(23.5), false);
|
||||
$this->assertEquals($validator->isValid('23.5'), false);
|
||||
$this->assertEquals($validator->isValid(null), false);
|
||||
$this->assertEquals($validator->isValid(true), false);
|
||||
$this->assertEquals($validator->isValid(false), false);
|
||||
$this->assertEquals($this->validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||
$this->assertEquals($this->validator->isValid('109.67.204.101'), false);
|
||||
$this->assertEquals($this->validator->isValid(23.5), false);
|
||||
$this->assertEquals($this->validator->isValid('23.5'), false);
|
||||
$this->assertEquals($this->validator->isValid(null), false);
|
||||
$this->assertEquals($this->validator->isValid(true), false);
|
||||
$this->assertEquals($this->validator->isValid(false), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\Origin;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class OriginTest extends TestCase
|
||||
{
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$validator = new Origin([
|
||||
[
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
namespace Appwrite\Network\Validator;
|
||||
namespace Tests\Unit\Network\Validators;
|
||||
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class URLTest extends TestCase
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\OpenSSL;
|
||||
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -15,7 +15,7 @@ class OpenSSLTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testEncryptionAndDecryption()
|
||||
public function testEncryptionAndDecryption(): void
|
||||
{
|
||||
$key = 'my-secret-key';
|
||||
$iv = '';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Stats;
|
||||
|
||||
use Appwrite\Stats\Stats;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -28,13 +28,13 @@ class StatsTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testNamespace()
|
||||
public function testNamespace(): void
|
||||
{
|
||||
$this->object->setNamespace('appwritetest.usage');
|
||||
$this->assertEquals('appwritetest.usage', $this->object->getNamespace());
|
||||
}
|
||||
|
||||
public function testParams()
|
||||
public function testParams(): void
|
||||
{
|
||||
$this->object
|
||||
->setParam('projectId', 'appwrite_test')
|
||||
|
@ -50,7 +50,7 @@ class StatsTest extends TestCase
|
|||
$this->assertEquals(null, $this->object->getParam('networkRequestSize'));
|
||||
}
|
||||
|
||||
public function testReset()
|
||||
public function testReset(): void
|
||||
{
|
||||
$this->object
|
||||
->setParam('projectId', 'appwrite_test')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Validator;
|
||||
|
||||
use Appwrite\Task\Validator\Cron;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -21,7 +21,7 @@ class CronTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$this->assertEquals($this->object->isValid('0 2 * * *'), true); // execute at 2am daily
|
||||
$this->assertEquals($this->object->isValid('0 5,17 * * *'), true); // execute twice a day
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Template;
|
||||
|
||||
use Appwrite\Template\Template;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -24,12 +24,12 @@ class TemplateTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testRender()
|
||||
public function testRender(): void
|
||||
{
|
||||
$this->assertEquals($this->object->render(), 'Hello WORLD');
|
||||
}
|
||||
|
||||
public function testParseURL()
|
||||
public function testParseURL(): void
|
||||
{
|
||||
$url = $this->object->parseURL('https://appwrite.io/demo');
|
||||
|
||||
|
@ -38,7 +38,7 @@ class TemplateTest extends TestCase
|
|||
$this->assertEquals($url['path'], '/demo');
|
||||
}
|
||||
|
||||
public function testUnParseURL()
|
||||
public function testUnParseURL(): void
|
||||
{
|
||||
$url = $this->object->parseURL('https://appwrite.io/demo');
|
||||
|
||||
|
@ -49,18 +49,18 @@ class TemplateTest extends TestCase
|
|||
$this->assertEquals($this->object->unParseURL($url), 'http://example.com/new');
|
||||
}
|
||||
|
||||
public function testMergeQuery()
|
||||
public function testMergeQuery(): void
|
||||
{
|
||||
$this->assertEquals($this->object->mergeQuery('key1=value1&key2=value2', ['key1' => 'value3', 'key4' => 'value4']), 'key1=value3&key2=value2&key4=value4');
|
||||
}
|
||||
|
||||
public function testFromCamelCaseToSnake()
|
||||
public function testFromCamelCaseToSnake(): void
|
||||
{
|
||||
$this->assertEquals('app_write', Template::fromCamelCaseToSnake('appWrite'));
|
||||
$this->assertEquals('app_write', Template::fromCamelCaseToSnake('App Write'));
|
||||
}
|
||||
|
||||
public function testFromCamelCaseToDash()
|
||||
public function testFromCamelCaseToDash(): void
|
||||
{
|
||||
$this->assertEquals('app-write', Template::fromCamelCaseToDash('appWrite'));
|
||||
$this->assertEquals('app-write', Template::fromCamelCaseToDash('App Write'));
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\URL;
|
||||
|
||||
use Appwrite\URL\URL;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class URLTest extends TestCase
|
||||
{
|
||||
public function testParse()
|
||||
public function testParse(): void
|
||||
{
|
||||
$url = URL::parse('https://appwrite.io:8080/path?query=string¶m=value');
|
||||
|
||||
|
@ -28,7 +28,7 @@ class URLTest extends TestCase
|
|||
$this->assertEquals('', $url['query']);
|
||||
}
|
||||
|
||||
public function testUnparse()
|
||||
public function testUnparse(): void
|
||||
{
|
||||
$url = URL::unparse([
|
||||
'scheme' => 'https',
|
||||
|
@ -88,7 +88,7 @@ class URLTest extends TestCase
|
|||
$this->assertEquals('https://eldad:fux@appwrite.io/#bottom', $url);
|
||||
}
|
||||
|
||||
public function testParseQuery()
|
||||
public function testParseQuery(): void
|
||||
{
|
||||
$result = URL::parseQuery('param1=value1¶m2=value2');
|
||||
|
||||
|
@ -96,7 +96,7 @@ class URLTest extends TestCase
|
|||
$this->assertEquals(['param1' => 'value1', 'param2' => 'value2'], $result);
|
||||
}
|
||||
|
||||
public function testUnParseQuery()
|
||||
public function testUnParseQuery(): void
|
||||
{
|
||||
$result = URL::unparseQuery(['param1' => 'value1', 'param2' => 'value2']);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Utopia\Database\Validator;
|
||||
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -21,7 +21,7 @@ class CustomIdTest extends TestCase
|
|||
{
|
||||
}
|
||||
|
||||
public function testValues()
|
||||
public function testValues(): void
|
||||
{
|
||||
$this->assertEquals($this->object->isValid('unique()'), true);
|
||||
$this->assertEquals($this->object->isValid('unique)'), false);
|
||||
|
|
28
tests/unit/Utopia/Lists.php
Normal file
28
tests/unit/Utopia/Lists.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Utopia;
|
||||
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class Lists extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->addRule('singles', [
|
||||
'type' => 'single',
|
||||
'default' => '',
|
||||
'array' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Lists';
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return 'lists';
|
||||
}
|
||||
}
|
31
tests/unit/Utopia/Nested.php
Normal file
31
tests/unit/Utopia/Nested.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Utopia;
|
||||
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class Nested extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->addRule('lists', [
|
||||
'type' => 'lists',
|
||||
'default' => '',
|
||||
])
|
||||
->addRule('single', [
|
||||
'type' => 'single',
|
||||
'default' => ''
|
||||
]);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Nested';
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return 'nested';
|
||||
}
|
||||
}
|
|
@ -1,33 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Tests;
|
||||
namespace Tests\Unit\Utopia;
|
||||
|
||||
use Exception;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Filters\V11;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Swoole\Http\Response as SwooleResponse;
|
||||
use Utopia\Database\Document;
|
||||
|
||||
class ResponseTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Response
|
||||
*/
|
||||
protected $object = null;
|
||||
protected ?Response $response = null;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->object = new Response(new SwooleResponse());
|
||||
$this->response = new Response(new SwooleResponse());
|
||||
$this->response->setModel(new Single());
|
||||
$this->response->setModel(new Lists());
|
||||
$this->response->setModel(new Nested());
|
||||
}
|
||||
|
||||
public function testSetFilter()
|
||||
public function testSetFilter(): void
|
||||
{
|
||||
$this->assertEquals($this->object->hasFilter(), false);
|
||||
$this->assertEquals($this->object->getFilter(), null);
|
||||
$this->assertEquals($this->response->hasFilter(), false);
|
||||
$this->assertEquals($this->response->getFilter(), null);
|
||||
|
||||
$filter = new V11();
|
||||
$this->object->setFilter($filter);
|
||||
$this->response->setFilter($filter);
|
||||
|
||||
$this->assertEquals($this->object->hasFilter(), true);
|
||||
$this->assertEquals($this->object->getFilter(), $filter);
|
||||
$this->assertEquals($this->response->hasFilter(), true);
|
||||
$this->assertEquals($this->response->getFilter(), $filter);
|
||||
}
|
||||
|
||||
public function testResponseModel(): void
|
||||
{
|
||||
$output = $this->response->output(new Document([
|
||||
'string' => 'lorem ipsum',
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
'hidden' => 'secret',
|
||||
]), 'single');
|
||||
|
||||
$this->assertArrayHasKey('string', $output);
|
||||
$this->assertArrayHasKey('integer', $output);
|
||||
$this->assertArrayHasKey('boolean', $output);
|
||||
$this->assertArrayNotHasKey('hidden', $output);
|
||||
}
|
||||
|
||||
public function testResponseModelRequired(): void
|
||||
{
|
||||
$output = $this->response->output(new Document([
|
||||
'string' => 'lorem ipsum',
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
]), 'single');
|
||||
|
||||
$this->assertArrayHasKey('string', $output);
|
||||
$this->assertArrayHasKey('integer', $output);
|
||||
$this->assertArrayHasKey('boolean', $output);
|
||||
$this->assertArrayHasKey('required', $output);
|
||||
$this->assertEquals('default', $output['required']);
|
||||
}
|
||||
|
||||
public function testResponseModelRequiredException(): void
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
$this->response->output(new Document([
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
]), 'single');
|
||||
}
|
||||
|
||||
public function testResponseModelLists(): void
|
||||
{
|
||||
$output = $this->response->output(new Document([
|
||||
'singles' => [
|
||||
new Document([
|
||||
'string' => 'lorem ipsum',
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
'hidden' => 'secret'
|
||||
])
|
||||
],
|
||||
'hidden' => 'secret',
|
||||
]), 'lists');
|
||||
|
||||
$this->assertArrayHasKey('singles', $output);
|
||||
$this->assertArrayNotHasKey('hidden', $output);
|
||||
$this->assertCount(1, $output['singles']);
|
||||
|
||||
$single = $output['singles'][0];
|
||||
$this->assertArrayHasKey('string', $single);
|
||||
$this->assertArrayHasKey('integer', $single);
|
||||
$this->assertArrayHasKey('boolean', $single);
|
||||
$this->assertArrayHasKey('required', $single);
|
||||
$this->assertArrayNotHasKey('hidden', $single);
|
||||
}
|
||||
|
||||
public function testResponseModelNested(): void
|
||||
{
|
||||
$output = $this->response->output(new Document([
|
||||
'lists' => new Document([
|
||||
'singles' => [
|
||||
new Document([
|
||||
'string' => 'lorem ipsum',
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
'hidden' => 'secret'
|
||||
])
|
||||
],
|
||||
'hidden' => 'secret',
|
||||
]),
|
||||
'single' => new Document([
|
||||
'string' => 'lorem ipsum',
|
||||
'integer' => 123,
|
||||
'boolean' => true,
|
||||
'hidden' => 'secret'
|
||||
]),
|
||||
'hidden' => 'secret',
|
||||
]), 'nested');
|
||||
|
||||
$this->assertArrayHasKey('lists', $output);
|
||||
$this->assertArrayHasKey('single', $output);
|
||||
$this->assertArrayNotHasKey('hidden', $output);
|
||||
$this->assertCount(1, $output['lists']['singles']);
|
||||
|
||||
|
||||
$single = $output['single'];
|
||||
$this->assertArrayHasKey('string', $single);
|
||||
$this->assertArrayHasKey('integer', $single);
|
||||
$this->assertArrayHasKey('boolean', $single);
|
||||
$this->assertArrayHasKey('required', $single);
|
||||
$this->assertArrayNotHasKey('hidden', $single);
|
||||
|
||||
$singleFromArray = $output['lists']['singles'][0];
|
||||
$this->assertArrayHasKey('string', $singleFromArray);
|
||||
$this->assertArrayHasKey('integer', $singleFromArray);
|
||||
$this->assertArrayHasKey('boolean', $singleFromArray);
|
||||
$this->assertArrayHasKey('required', $single);
|
||||
$this->assertArrayNotHasKey('hidden', $singleFromArray);
|
||||
}
|
||||
}
|
||||
|
|
43
tests/unit/Utopia/Single.php
Normal file
43
tests/unit/Utopia/Single.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Utopia;
|
||||
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class Single extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->addRule('string', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'example' => '5e5ea5c16897e',
|
||||
'required' => true
|
||||
])
|
||||
->addRule('integer', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'default' => 0,
|
||||
'example' => 1592981250,
|
||||
])
|
||||
->addRule('boolean', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'default' => true,
|
||||
'example' => true,
|
||||
])
|
||||
->addRule('required', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'default' => 'default',
|
||||
'required' => true
|
||||
]);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'Single';
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return 'single';
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue