mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Improve endpoint quality
This commit is contained in:
@@ -1,144 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Project\Http\Project\SMTP\Credentials;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Throwable;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Emails\Validator\Email;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Hostname;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'updateProjectSMTPCredentials';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/project/smtp/credentials')
|
||||
->httpAlias('/v1/projects/:projectId/smtp')
|
||||
->desc('Update project SMTP details')
|
||||
->groups(['api', 'project'])
|
||||
->label('scope', 'project.write')
|
||||
->label('event', 'smtp.*.update')
|
||||
->label('audits.event', 'project.smtp.update')
|
||||
->label('audits.resource', 'project.smtp/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'project',
|
||||
group: 'smtp',
|
||||
name: 'updateSMTPCredentials',
|
||||
description: <<<EOT
|
||||
Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN, AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
],
|
||||
))
|
||||
->param('senderName', '', new Text(256), 'Name of the email sender')
|
||||
->param('senderEmail', '', 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')
|
||||
->param('username', '', new Text(256), 'SMTP server username', true)
|
||||
->param('password', '', new Text(256), 'SMTP server password', true)
|
||||
->param('secure', '', new WhiteList(['tls', 'ssl'], true), 'Does SMTP server use secure connection', true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Enable custom SMTP service', optional: true, deprecated: true) // Backwards compatibility
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('project')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
||||
public function action(
|
||||
string $senderName,
|
||||
string $senderEmail,
|
||||
string $replyTo,
|
||||
string $host,
|
||||
int $port,
|
||||
string $username,
|
||||
string $password,
|
||||
string $secure,
|
||||
?bool $enabled, // Backwards compatibility
|
||||
Response $response,
|
||||
Database $dbForPlatform,
|
||||
Document $project,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
// Backwards compatibility
|
||||
if (!\is_null($enabled) && $enabled === false) {
|
||||
$smtp = $project->getAttribute('smtp', []);
|
||||
|
||||
$smtp['enabled'] = $enabled;
|
||||
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)));
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate SMTP settings
|
||||
$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());
|
||||
}
|
||||
|
||||
$smtp = [
|
||||
'enabled' => true,
|
||||
'senderName' => $senderName,
|
||||
'senderEmail' => $senderEmail,
|
||||
'replyTo' => $replyTo,
|
||||
'host' => $host,
|
||||
'port' => $port,
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
'secure' => $secure,
|
||||
];
|
||||
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)));
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Project\Http\Project\SMTP\Status;
|
||||
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'updateProjectSMTPStatus';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/project/smtp/status')
|
||||
->desc('Update project SMTP status')
|
||||
->groups(['api', 'project'])
|
||||
->label('scope', 'project.write')
|
||||
->label('event', 'smtp.*.update')
|
||||
->label('audits.event', 'project.smtp.update')
|
||||
->label('audits.resource', 'project.smtp/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'project',
|
||||
group: 'smtp',
|
||||
name: 'updateSMTPStatus',
|
||||
description: <<<EOT
|
||||
Update the status of a SMTP. Use this endpoint to enable or disable ability to configure custom email sender in your project.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN, AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
],
|
||||
))
|
||||
->param('enabled', null, new Boolean(), 'SMTP status.')
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('project')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(
|
||||
bool $enabled,
|
||||
Response $response,
|
||||
Database $dbForPlatform,
|
||||
Document $project,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
$smtp = $project->getAttribute('smtp', []);
|
||||
|
||||
$smtp['enabled'] = $enabled;
|
||||
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $project->setAttribute('smtp', $smtp)));
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Project\Http\Project\SMTP;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Throwable;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Emails\Validator\Email;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Hostname;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class Update extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
{
|
||||
return 'updateProjectSMTP';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_PATCH)
|
||||
->setHttpPath('/v1/project/smtp')
|
||||
->httpAlias('/v1/projects/:projectId/smtp')
|
||||
->desc('Update project SMTP configuration')
|
||||
->groups(['api', 'project'])
|
||||
->label('scope', 'project.write')
|
||||
->label('event', 'smtp.*.update')
|
||||
->label('audits.event', 'project.smtp.update')
|
||||
->label('audits.resource', 'project.smtp/{response.$id}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'project',
|
||||
group: 'smtp',
|
||||
name: 'updateSMTP',
|
||||
description: <<<EOT
|
||||
Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN, AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_OK,
|
||||
model: Response::MODEL_PROJECT,
|
||||
)
|
||||
],
|
||||
))
|
||||
->param('host', '', new Nullable(new Hostname()), 'SMTP server hostname (domain)', optional: true)
|
||||
->param('port', 587, new Nullable(new Integer()), 'SMTP server port', optional: true)
|
||||
->param('username', '', new Nullable(new Text(256)), 'SMTP server username. Leave empty for no authorization.', optional: true)
|
||||
->param('password', '', new Nullable(new Text(256)), 'SMTP server password. Leave empty for no authorization. This property is stored securely and cannot be read in future (write-only).', optional: true)
|
||||
->param('senderEmail', '', new Nullable(new Email()), 'Email address shown in inbox as the sender of the email.', optional: true)
|
||||
->param('senderName', '', new Nullable(new Text(256)), 'Name shown in inbox as the sender of the email.', optional: true)
|
||||
->param('replyToEmail', '', new Nullable(new Email()), 'Email used when user replies to the email.', optional: true)
|
||||
->param('replyToName', '', new Nullable(new Text(256)), 'Name used when user replies to the email.', optional: true)
|
||||
->param('secure', '', new Nullable(new WhiteList(['tls', 'ssl'], true)), 'Configures if communication with SMTP server is encrypted. Allowed values are: tls, ssl. Leave empty for no encryption.', optional: true)
|
||||
->param('enabled', null, new Nullable(new Boolean()), 'Enable or disable custom SMTP. Custom SMTP is useful for branding purposes, but also allows use of custom email templates.', optional: true)
|
||||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('project')
|
||||
->inject('authorization')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
|
||||
public function action(
|
||||
?string $host,
|
||||
?int $port,
|
||||
?string $username,
|
||||
?string $password,
|
||||
?string $senderEmail,
|
||||
?string $senderName,
|
||||
?string $replyToEmail,
|
||||
?string $replyToName,
|
||||
?string $secure,
|
||||
?bool $enabled,
|
||||
Response $response,
|
||||
Database $dbForPlatform,
|
||||
Document $project,
|
||||
Authorization $authorization
|
||||
): void {
|
||||
// Fetch current configuration
|
||||
$smtp = $project->getAttribute('smtp', []);
|
||||
|
||||
// Apply changes
|
||||
$keys = ['host', 'port', 'username', 'password', 'senderEmail', 'senderName', 'replyToEmail', 'replyToName', 'secure', 'enabled'];
|
||||
foreach ($keys as $key) {
|
||||
if (!\is_null(${$key})) {
|
||||
$smtp[$key] = ${$key};
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure required fields are set
|
||||
$requiredKeys = ['host', 'port', 'senderEmail'];
|
||||
foreach ($requiredKeys as $key) {
|
||||
if (empty($smtp[$key])) {
|
||||
throw new \Exception('"' . $key . '" is required. Please provide a value.');
|
||||
}
|
||||
}
|
||||
|
||||
// Validate SMTP credentials
|
||||
if($smtp['enabled'] === true) {
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->isSMTP();
|
||||
|
||||
$mail->Host = $smtp['host'] ?? '';
|
||||
$mail->Port = $smtp['port'] ?? '';
|
||||
$mail->SMTPSecure = $smtp['secure'] ?? '';
|
||||
$mail->setFrom($smtp['senderEmail'], $smtp['senderName'] ?? '');
|
||||
|
||||
if(!empty($smtp['username'] ?? '')) {
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $smtp['username'];
|
||||
$mail->Password = $smtp['password'] ?? '';
|
||||
}
|
||||
|
||||
if(!empty($smtp['replyToEmail'] ?? '')) {
|
||||
$mail->addReplyTo($smtp['replyToEmail'], $smtp['replyToName'] ?? '');
|
||||
}
|
||||
|
||||
$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 configuration
|
||||
$updates = new Document([
|
||||
'smtp' => $smtp,
|
||||
]);
|
||||
|
||||
$project = $authorization->skip(fn () => $dbForPlatform->updateDocument('projects', $project->getId(), $updates));
|
||||
|
||||
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ use Appwrite\Platform\Modules\Project\Http\Project\Platforms\XList as ListPlatfo
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\Protocols\Status\Update as UpdateProjectProtocolStatus;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\Services\Status\Update as UpdateProjectServiceStatus;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\SMTP\Credentials\Update as UpdateSMTPCredentials;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\SMTP\Status\Update as UpdateSMTPStatus;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\SMTP\Tests\Create as CreateSMTPTest;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\Variables\Create as CreateVariable;
|
||||
use Appwrite\Platform\Modules\Project\Http\Project\Variables\Delete as DeleteVariable;
|
||||
@@ -50,7 +49,6 @@ class Http extends Service
|
||||
|
||||
// SMTP
|
||||
$this->addAction(UpdateSMTPCredentials::getName(), new UpdateSMTPCredentials());
|
||||
$this->addAction(UpdateSMTPStatus::getName(), new UpdateSMTPStatus());
|
||||
$this->addAction(CreateSMTPTest::getName(), new CreateSMTPTest());
|
||||
|
||||
// Variables
|
||||
|
||||
@@ -247,7 +247,13 @@ class Project extends Model
|
||||
'default' => '',
|
||||
'example' => 'john@appwrite.io',
|
||||
])
|
||||
->addRule('smtpReplyTo', [
|
||||
->addRule('smtpReplyToName', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'SMTP reply to name',
|
||||
'default' => '',
|
||||
'example' => 'Support Team',
|
||||
])
|
||||
->addRule('smtpReplyToEmail', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'SMTP reply to email',
|
||||
'default' => '',
|
||||
@@ -271,12 +277,15 @@ class Project extends Model
|
||||
'default' => '',
|
||||
'example' => 'emailuser',
|
||||
])
|
||||
/*
|
||||
We intentionally do not expose SMTP password - it's write-only property.
|
||||
->addRule('smtpPassword', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'SMTP server password',
|
||||
'default' => '',
|
||||
'example' => 'securepassword',
|
||||
])
|
||||
*/
|
||||
->addRule('smtpSecure', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'SMTP server secure protocol',
|
||||
@@ -409,7 +418,8 @@ class Project extends Model
|
||||
$document->setAttribute('smtpEnabled', $smtp['enabled'] ?? false);
|
||||
$document->setAttribute('smtpSenderEmail', $smtp['senderEmail'] ?? '');
|
||||
$document->setAttribute('smtpSenderName', $smtp['senderName'] ?? '');
|
||||
$document->setAttribute('smtpReplyTo', $smtp['replyTo'] ?? '');
|
||||
$document->setAttribute('smtpReplyToEmail', $smtp['replyToEmail'] ?? '');
|
||||
$document->setAttribute('smtpReplyToName', $smtp['replyToName'] ?? '');
|
||||
$document->setAttribute('smtpHost', $smtp['host'] ?? '');
|
||||
$document->setAttribute('smtpPort', $smtp['port'] ?? '');
|
||||
$document->setAttribute('smtpUsername', $smtp['username'] ?? '');
|
||||
|
||||
Reference in New Issue
Block a user