mirror of
https://github.com/appwrite/appwrite
synced 2026-04-21 13:37:16 +00:00
1089 lines
45 KiB
PHP
1089 lines
45 KiB
PHP
<?php
|
|
|
|
use Ahc\Jwt\JWT;
|
|
use Appwrite\Auth\Validator\MockNumber;
|
|
use Appwrite\Event\Delete;
|
|
use Appwrite\Event\Mail;
|
|
use Appwrite\Extend\Exception;
|
|
use Appwrite\SDK\AuthType;
|
|
use Appwrite\SDK\ContentType;
|
|
use Appwrite\SDK\Deprecated;
|
|
use Appwrite\SDK\Method;
|
|
use Appwrite\SDK\Response as SDKResponse;
|
|
use Appwrite\Template\Template;
|
|
use Appwrite\Utopia\Database\Validator\Queries\Keys;
|
|
use Appwrite\Utopia\Response;
|
|
use PHPMailer\PHPMailer\PHPMailer;
|
|
use Utopia\Config\Config;
|
|
use Utopia\Database\Database;
|
|
use Utopia\Database\Document;
|
|
use Utopia\Database\Validator\UID;
|
|
use Utopia\Emails\Validator\Email;
|
|
use Utopia\Http\Http;
|
|
use Utopia\Locale\Locale;
|
|
use Utopia\System\System;
|
|
use Utopia\Validator\ArrayList;
|
|
use Utopia\Validator\Boolean;
|
|
use Utopia\Validator\Hostname;
|
|
use Utopia\Validator\Integer;
|
|
use Utopia\Validator\Nullable;
|
|
use Utopia\Validator\Range;
|
|
use Utopia\Validator\Text;
|
|
use Utopia\Validator\WhiteList;
|
|
|
|
Http::init()
|
|
->groups(['projects'])
|
|
->inject('project')
|
|
->action(function (Document $project) {
|
|
if ($project->getId() !== 'console') {
|
|
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN);
|
|
}
|
|
});
|
|
|
|
Http::get('/v1/projects/:projectId')
|
|
->desc('Get project')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.read')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'projects',
|
|
name: 'get',
|
|
description: '/docs/references/projects/get.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/service/all')
|
|
->desc('Update all service status')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->action(function () {
|
|
throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED, 'Bulk API no longer exists for services. Please change status individually.');
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/api/all')
|
|
->desc('Update all API status')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->action(function () {
|
|
throw new Exception(Exception::GENERAL_NOT_IMPLEMENTED, 'Bulk API no longer exists for services. Please change status individually.');
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/oauth2')
|
|
->desc('Update project OAuth2')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateOAuth2',
|
|
description: '/docs/references/projects/update-oauth2.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('provider', '', new WhiteList(\array_keys(Config::getParam('oAuthProviders')), true), 'Provider Name')
|
|
->param('appId', null, new Nullable(new Text(256)), 'Provider app ID. Max length: 256 chars.', true)
|
|
->param('secret', null, new Nullable(new text(512)), 'Provider secret key. Max length: 512 chars.', true)
|
|
->param('enabled', null, new Nullable(new Boolean()), 'Provider status. Set to \'false\' to disable new session creation.', true)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, string $provider, ?string $appId, ?string $secret, ?bool $enabled, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$providers = $project->getAttribute('oAuthProviders', []);
|
|
|
|
if ($appId !== null) {
|
|
$providers[$provider . 'Appid'] = $appId;
|
|
}
|
|
|
|
if ($secret !== null) {
|
|
$providers[$provider . 'Secret'] = $secret;
|
|
}
|
|
|
|
if ($enabled !== null) {
|
|
$providers[$provider . 'Enabled'] = $enabled;
|
|
}
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('oAuthProviders', $providers));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/session-alerts')
|
|
->desc('Update project sessions emails')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateSessionAlerts',
|
|
description: '/docs/references/projects/update-session-alerts.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('alerts', false, new Boolean(true), 'Set to true to enable session emails.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $alerts, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['sessionAlerts'] = $alerts;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/memberships-privacy')
|
|
->desc('Update project memberships privacy attributes')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateMembershipsPrivacy',
|
|
description: '/docs/references/projects/update-memberships-privacy.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('userName', true, new Boolean(true), 'Set to true to show userName to members of a team.')
|
|
->param('userEmail', true, new Boolean(true), 'Set to true to show email to members of a team.')
|
|
->param('mfa', true, new Boolean(true), 'Set to true to show mfa to members of a team.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $userName, bool $userEmail, bool $mfa, Response $response, Database $dbForPlatform) {
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
|
|
$auths['membershipsUserName'] = $userName;
|
|
$auths['membershipsUserEmail'] = $userEmail;
|
|
$auths['membershipsMfa'] = $mfa;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/limit')
|
|
->desc('Update project users limit')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthLimit',
|
|
description: '/docs/references/projects/update-auth-limit.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('limit', false, new Range(0, APP_LIMIT_USERS), 'Set the max number of users allowed in this project. Use 0 for unlimited.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['limit'] = $limit;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/duration')
|
|
->desc('Update project authentication duration')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthDuration',
|
|
description: '/docs/references/projects/update-auth-duration.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('duration', 31536000, new Range(0, 31536000), 'Project session length in seconds. Max length: 31536000 seconds.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, int $duration, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['duration'] = $duration;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/:method')
|
|
->desc('Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthStatus',
|
|
description: '/docs/references/projects/update-auth-status.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false)
|
|
->param('status', false, new Boolean(true), 'Set the status of this auth method.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, string $method, bool $status, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
$auth = Config::getParam('auth')[$method] ?? [];
|
|
$authKey = $auth['key'] ?? '';
|
|
$status = ($status === '1' || $status === 'true' || $status === 1 || $status === true);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths[$authKey] = $status;
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/password-history')
|
|
->desc('Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthPasswordHistory',
|
|
description: '/docs/references/projects/update-auth-password-history.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('limit', 0, new Range(0, APP_LIMIT_USER_PASSWORD_HISTORY), 'Set the max number of passwords to store in user history. User can\'t choose a new password that is already stored in the password history list. Max number of passwords allowed in history is' . APP_LIMIT_USER_PASSWORD_HISTORY . '. Default value is 0')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['passwordHistory'] = $limit;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/password-dictionary')
|
|
->desc('Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthPasswordDictionary',
|
|
description: '/docs/references/projects/update-auth-password-dictionary.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('enabled', false, new Boolean(false), 'Set whether or not to enable checking user\'s password against most commonly used passwords. Default is false.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['passwordDictionary'] = $enabled;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/personal-data')
|
|
->desc('Update personal data check')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updatePersonalDataCheck',
|
|
description: '/docs/references/projects/update-personal-data-check.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('enabled', false, new Boolean(false), 'Set whether or not to check a password for similarity with personal data. Default is false.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['personalDataCheck'] = $enabled;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/max-sessions')
|
|
->desc('Update project user sessions limit')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateAuthSessionsLimit',
|
|
description: '/docs/references/projects/update-auth-sessions-limit.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('limit', false, new Range(1, APP_LIMIT_USER_SESSIONS_MAX), 'Set the max number of users allowed in this project. Value allowed is between 1-' . APP_LIMIT_USER_SESSIONS_MAX . '. Default is ' . APP_LIMIT_USER_SESSIONS_DEFAULT)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, int $limit, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['maxSessions'] = $limit;
|
|
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/mock-numbers')
|
|
->desc('Update the mock numbers for the project')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateMockNumbers',
|
|
description: '/docs/references/projects/update-mock-numbers.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('numbers', '', new ArrayList(new MockNumber(), 10), 'An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, array $numbers, Response $response, Database $dbForPlatform) {
|
|
|
|
$uniqueNumbers = [];
|
|
foreach ($numbers as $number) {
|
|
if (isset($uniqueNumbers[$number['phone']])) {
|
|
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Duplicate phone numbers are not allowed.');
|
|
}
|
|
$uniqueNumbers[$number['phone']] = $number['otp'];
|
|
}
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
|
|
$auths['mockNumbers'] = $numbers;
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::delete('/v1/projects/:projectId')
|
|
->desc('Delete project')
|
|
->groups(['api', 'projects'])
|
|
->label('audits.event', 'projects.delete')
|
|
->label('audits.resource', 'project/{request.projectId}')
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'projects',
|
|
name: 'delete',
|
|
description: '/docs/references/projects/delete.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_NOCONTENT,
|
|
model: Response::MODEL_NONE,
|
|
)
|
|
],
|
|
contentType: ContentType::NONE
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->inject('response')
|
|
->inject('user')
|
|
->inject('dbForPlatform')
|
|
->inject('queueForDeletes')
|
|
->action(function (string $projectId, Response $response, Document $user, Database $dbForPlatform, Delete $queueForDeletes) {
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$queueForDeletes
|
|
->setProject($project)
|
|
->setType(DELETE_TYPE_DOCUMENT)
|
|
->setDocument($project);
|
|
|
|
if (!$dbForPlatform->deleteDocument('projects', $projectId)) {
|
|
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove project from DB');
|
|
}
|
|
|
|
$response->noContent();
|
|
});
|
|
|
|
// JWT Keys
|
|
|
|
Http::post('/v1/projects/:projectId/jwts')
|
|
->groups(['api', 'projects'])
|
|
->desc('Create JWT')
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'createJWT',
|
|
description: '/docs/references/projects/create-jwt.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_CREATED,
|
|
model: Response::MODEL_JWT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('scopes', [], new ArrayList(new WhiteList(array_keys(Config::getParam('projectScopes')), true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'List of scopes allowed for JWT key. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' scopes are allowed.')
|
|
->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, array $scopes, int $duration, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $duration, 0);
|
|
|
|
$response
|
|
->setStatusCode(Response::STATUS_CODE_CREATED)
|
|
->dynamic(new Document(['jwt' => API_KEY_DYNAMIC . '_' . $jwt->encode([
|
|
'projectId' => $project->getId(),
|
|
'scopes' => $scopes
|
|
])]), Response::MODEL_JWT);
|
|
});
|
|
|
|
// CUSTOM SMTP and Templates
|
|
Http::patch('/v1/projects/:projectId/smtp')
|
|
->desc('Update SMTP')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', [
|
|
new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'updateSmtp',
|
|
description: '/docs/references/projects/update-smtp.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
],
|
|
deprecated: new Deprecated(
|
|
since: '1.8.0',
|
|
replaceWith: 'projects.updateSMTP',
|
|
),
|
|
public: false,
|
|
),
|
|
new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'updateSMTP',
|
|
description: '/docs/references/projects/update-smtp.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
)
|
|
])
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('enabled', false, new Boolean(), 'Enable custom SMTP service')
|
|
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
|
|
->param('senderEmail', '', new Email(), 'Email of the sender', true)
|
|
->param('replyTo', '', new Email(), 'Reply to email', true)
|
|
->param('host', '', new HostName(), 'SMTP server host name', true)
|
|
->param('port', 587, new Integer(), 'SMTP server port', true)
|
|
->param('username', '', new Text(0, 0), 'SMTP server username', true)
|
|
->param('password', '', new Text(0, 0), 'SMTP server password', true)
|
|
->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $enabled, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
// Ensure required params for when enabling SMTP
|
|
if ($enabled) {
|
|
if (empty($senderName)) {
|
|
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Sender name is required when enabling SMTP.');
|
|
} elseif (empty($senderEmail)) {
|
|
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Sender email is required when enabling SMTP.');
|
|
} elseif (empty($host)) {
|
|
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Host is required when enabling SMTP.');
|
|
} elseif (empty($port)) {
|
|
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Port is required when enabling SMTP.');
|
|
}
|
|
}
|
|
|
|
// validate SMTP settings
|
|
if ($enabled) {
|
|
$mail = new PHPMailer(true);
|
|
$mail->isSMTP();
|
|
$mail->SMTPAuth = (!empty($username) && !empty($password));
|
|
$mail->Username = $username;
|
|
$mail->Password = $password;
|
|
$mail->Host = $host;
|
|
$mail->Port = $port;
|
|
$mail->SMTPSecure = $secure;
|
|
$mail->SMTPAutoTLS = false;
|
|
$mail->Timeout = 5;
|
|
|
|
try {
|
|
$valid = $mail->SmtpConnect();
|
|
|
|
if (!$valid) {
|
|
throw new Exception('Connection is not valid.');
|
|
}
|
|
} catch (Throwable $error) {
|
|
throw new Exception(Exception::PROJECT_SMTP_CONFIG_INVALID, $error->getMessage());
|
|
}
|
|
}
|
|
|
|
// Save SMTP settings
|
|
if ($enabled) {
|
|
$smtp = [
|
|
'enabled' => $enabled,
|
|
'senderName' => $senderName,
|
|
'senderEmail' => $senderEmail,
|
|
'replyTo' => $replyTo,
|
|
'host' => $host,
|
|
'port' => $port,
|
|
'username' => $username,
|
|
'password' => $password,
|
|
'secure' => $secure,
|
|
];
|
|
} else {
|
|
$smtp = [
|
|
'enabled' => false
|
|
];
|
|
}
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|
|
|
|
Http::post('/v1/projects/:projectId/smtp/tests')
|
|
->desc('Create SMTP test')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', [
|
|
new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'createSmtpTest',
|
|
description: '/docs/references/projects/create-smtp-test.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_NOCONTENT,
|
|
model: Response::MODEL_NONE,
|
|
)
|
|
],
|
|
deprecated: new Deprecated(
|
|
since: '1.8.0',
|
|
replaceWith: 'projects.createSMTPTest',
|
|
),
|
|
public: false,
|
|
),
|
|
new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'createSMTPTest',
|
|
description: '/docs/references/projects/create-smtp-test.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_NOCONTENT,
|
|
model: Response::MODEL_NONE,
|
|
)
|
|
]
|
|
)
|
|
])
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('emails', [], new ArrayList(new Email(), 10), 'Array of emails to send test email to. Maximum of 10 emails are allowed.')
|
|
->param('senderName', System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server'), new Text(255, 0), 'Name of the email sender')
|
|
->param('senderEmail', System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM), new Email(), 'Email of the sender')
|
|
->param('replyTo', '', new Email(), 'Reply to email', true)
|
|
->param('host', '', new HostName(), 'SMTP server host name')
|
|
->param('port', 587, new Integer(), 'SMTP server port', true)
|
|
->param('username', '', new Text(0, 0), 'SMTP server username', true)
|
|
->param('password', '', new Text(0, 0), 'SMTP server password', true)
|
|
->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->inject('queueForMails')
|
|
->inject('plan')
|
|
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails, array $plan) {
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$replyToEmail = !empty($replyTo) ? $replyTo : $senderEmail;
|
|
|
|
$subject = 'Custom SMTP email sample';
|
|
$template = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-smtp-test.tpl');
|
|
$template
|
|
->setParam('{{from}}', "{$senderName} ({$senderEmail})")
|
|
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})")
|
|
->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL)
|
|
->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR)
|
|
->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER)
|
|
->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD)
|
|
->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE)
|
|
->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL)
|
|
->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
|
|
|
|
foreach ($emails as $email) {
|
|
$queueForMails
|
|
->setSmtpHost($host)
|
|
->setSmtpPort($port)
|
|
->setSmtpUsername($username)
|
|
->setSmtpPassword($password)
|
|
->setSmtpSecure($secure)
|
|
->setSmtpReplyTo($replyTo)
|
|
->setSmtpSenderEmail($senderEmail)
|
|
->setSmtpSenderName($senderName)
|
|
->setRecipient($email)
|
|
->setName('')
|
|
->setBodyTemplate(__DIR__ . '/../../config/locale/templates/email-base-styled.tpl')
|
|
->setBody($template->render())
|
|
->setVariables([])
|
|
->setSubject($subject)
|
|
->trigger();
|
|
}
|
|
|
|
$response->noContent();
|
|
});
|
|
|
|
Http::get('/v1/projects/:projectId/templates/email')
|
|
->alias('/v1/projects/:projectId/templates/email/:type/:locale')
|
|
->desc('Get custom email template')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'getEmailTemplate',
|
|
description: '/docs/references/projects/get-email-template.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_EMAIL_TEMPLATE,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? [], true), 'Template type')
|
|
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', true, ['localeCodes'])
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->inject('locale')
|
|
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform, Locale $localeObject) {
|
|
$locale = $locale ?: $localeObject->default ?: $localeObject->fallback ?: System::getEnv('_APP_LOCALE', 'en');
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$templates = $project->getAttribute('templates', []);
|
|
$template = $templates['email.' . $type . '-' . $locale] ?? null;
|
|
|
|
$localeObj = new Locale($locale);
|
|
$localeObj->setFallback(System::getEnv('_APP_LOCALE', 'en'));
|
|
|
|
if (is_null($template)) {
|
|
/**
|
|
* different templates, different placeholders.
|
|
*/
|
|
$templateConfigs = [
|
|
'magicSession' => [
|
|
'file' => 'email-magic-url.tpl',
|
|
'placeholders' => ['optionButton', 'buttonText', 'optionUrl', 'clientInfo', 'securityPhrase']
|
|
],
|
|
'mfaChallenge' => [
|
|
'file' => 'email-mfa-challenge.tpl',
|
|
'placeholders' => ['description', 'clientInfo']
|
|
],
|
|
'otpSession' => [
|
|
'file' => 'email-otp.tpl',
|
|
'placeholders' => ['description', 'clientInfo', 'securityPhrase']
|
|
],
|
|
'sessionAlert' => [
|
|
'file' => 'email-session-alert.tpl',
|
|
'placeholders' => ['body', 'listDevice', 'listIpAddress', 'listCountry', 'footer']
|
|
],
|
|
];
|
|
|
|
// fallback to the base template.
|
|
$config = $templateConfigs[$type] ?? [
|
|
'file' => 'email-inner-base.tpl',
|
|
'placeholders' => ['buttonText', 'body', 'footer']
|
|
];
|
|
|
|
$templateString = file_get_contents(__DIR__ . '/../../config/locale/templates/' . $config['file']);
|
|
|
|
// We use `fromString` due to the replace above
|
|
$message = Template::fromString($templateString);
|
|
|
|
// Set type-specific parameters
|
|
foreach ($config['placeholders'] as $param) {
|
|
$escapeHtml = !in_array($param, ['clientInfo', 'body', 'footer', 'description']);
|
|
$message->setParam("{{{$param}}}", $localeObj->getText("emails.{$type}.{$param}"), escapeHtml: $escapeHtml);
|
|
}
|
|
|
|
$message
|
|
// common placeholders on all the templates
|
|
->setParam('{{hello}}', $localeObj->getText("emails.{$type}.hello"))
|
|
->setParam('{{thanks}}', $localeObj->getText("emails.{$type}.thanks"))
|
|
->setParam('{{signature}}', $localeObj->getText("emails.{$type}.signature"));
|
|
|
|
// `useContent: false` will strip new lines!
|
|
$message = $message->render(useContent: true);
|
|
|
|
$template = [
|
|
'message' => $message,
|
|
'subject' => $localeObj->getText('emails.' . $type . '.subject'),
|
|
'senderEmail' => '',
|
|
'senderName' => ''
|
|
];
|
|
}
|
|
|
|
$template['type'] = $type;
|
|
$template['locale'] = $locale;
|
|
|
|
$response->dynamic(new Document($template), Response::MODEL_EMAIL_TEMPLATE);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/templates/email')
|
|
->alias('/v1/projects/:projectId/templates/email/:type/:locale')
|
|
->desc('Update custom email templates')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'updateEmailTemplate',
|
|
description: '/docs/references/projects/update-email-template.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_EMAIL_TEMPLATE,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? [], true), 'Template type')
|
|
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', true, ['localeCodes'])
|
|
->param('subject', '', new Text(255), 'Email Subject')
|
|
->param('message', '', new Text(0), 'Template message')
|
|
->param('senderName', '', new Text(255, 0), 'Name of the email sender', true)
|
|
->param('senderEmail', '', new Email(), 'Email of the sender', true)
|
|
->param('replyTo', '', new Email(), 'Reply to email', true)
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->inject('locale')
|
|
->action(function (string $projectId, string $type, string $locale, string $subject, string $message, string $senderName, string $senderEmail, string $replyTo, Response $response, Database $dbForPlatform, Locale $localeObject) {
|
|
$locale = $locale ?: $localeObject->default ?: $localeObject->fallback ?: System::getEnv('_APP_LOCALE', 'en');
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$templates = $project->getAttribute('templates', []);
|
|
$templates['email.' . $type . '-' . $locale] = [
|
|
'senderName' => $senderName,
|
|
'senderEmail' => $senderEmail,
|
|
'subject' => $subject,
|
|
'replyTo' => $replyTo,
|
|
'message' => $message
|
|
];
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates));
|
|
|
|
$response->dynamic(new Document([
|
|
'type' => $type,
|
|
'locale' => $locale,
|
|
'senderName' => $senderName,
|
|
'senderEmail' => $senderEmail,
|
|
'subject' => $subject,
|
|
'replyTo' => $replyTo,
|
|
'message' => $message
|
|
]), Response::MODEL_EMAIL_TEMPLATE);
|
|
});
|
|
|
|
Http::delete('/v1/projects/:projectId/templates/email')
|
|
->alias('/v1/projects/:projectId/templates/email/:type/:locale')
|
|
->desc('Delete custom email template')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'templates',
|
|
name: 'deleteEmailTemplate',
|
|
description: '/docs/references/projects/delete-email-template.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_EMAIL_TEMPLATE,
|
|
)
|
|
],
|
|
contentType: ContentType::JSON
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? [], true), 'Template type')
|
|
->param('locale', '', fn ($localeCodes) => new WhiteList($localeCodes), 'Template locale', true, ['localeCodes'])
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->inject('locale')
|
|
->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForPlatform, Locale $localeObject) {
|
|
$locale = $locale ?: $localeObject->default ?: $localeObject->fallback ?: System::getEnv('_APP_LOCALE', 'en');
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$templates = $project->getAttribute('templates', []);
|
|
$template = $templates['email.' . $type . '-' . $locale] ?? null;
|
|
|
|
if (is_null($template)) {
|
|
throw new Exception(Exception::PROJECT_TEMPLATE_DEFAULT_DELETION);
|
|
}
|
|
|
|
unset($templates['email.' . $type . '-' . $locale]);
|
|
|
|
$project = $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates));
|
|
|
|
$response->dynamic(new Document([
|
|
'type' => $type,
|
|
'locale' => $locale,
|
|
'senderName' => $template['senderName'],
|
|
'senderEmail' => $template['senderEmail'],
|
|
'subject' => $template['subject'],
|
|
'replyTo' => $template['replyTo'],
|
|
'message' => $template['message']
|
|
]), Response::MODEL_EMAIL_TEMPLATE);
|
|
});
|
|
|
|
Http::patch('/v1/projects/:projectId/auth/session-invalidation')
|
|
->desc('Update invalidate session option of the project')
|
|
->groups(['api', 'projects'])
|
|
->label('scope', 'projects.write')
|
|
->label('sdk', new Method(
|
|
namespace: 'projects',
|
|
group: 'auth',
|
|
name: 'updateSessionInvalidation',
|
|
description: '/docs/references/projects/update-session-invalidation.md',
|
|
auth: [AuthType::ADMIN],
|
|
responses: [
|
|
new SDKResponse(
|
|
code: Response::STATUS_CODE_OK,
|
|
model: Response::MODEL_PROJECT,
|
|
)
|
|
]
|
|
))
|
|
->param('projectId', '', fn (Database $dbForPlatform) => new UID($dbForPlatform->getAdapter()->getMaxUIDLength()), 'Project unique ID.', false, ['dbForPlatform'])
|
|
->param('enabled', false, new Boolean(), 'Update authentication session invalidation status. Use this endpoint to enable or disable session invalidation on password change')
|
|
->inject('response')
|
|
->inject('dbForPlatform')
|
|
->action(function (string $projectId, bool $enabled, Response $response, Database $dbForPlatform) {
|
|
|
|
$project = $dbForPlatform->getDocument('projects', $projectId);
|
|
|
|
if ($project->isEmpty()) {
|
|
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
|
}
|
|
|
|
$auths = $project->getAttribute('auths', []);
|
|
$auths['invalidateSessions'] = $enabled;
|
|
$dbForPlatform->updateDocument('projects', $project->getId(), $project
|
|
->setAttribute('auths', $auths));
|
|
|
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
|
});
|