Add encrypt param to varchar, text, mediumtext, longtext attribute and column create routes

- Add encrypt parameter to Varchar, Text, Mediumtext, Longtext attribute create routes
- Add encrypt parameter to Varchar, Text, Mediumtext, Longtext column create routes
- Add encrypt rule to AttributeVarchar, AttributeText, AttributeMediumtext, AttributeLongtext response models
- Add encrypt rule to ColumnVarchar, ColumnText, ColumnMediumtext, ColumnLongtext response models
- Add plan injection and validation for encrypt feature in all routes
- Add size validation for encrypt on varchar route (variable size)
- Add encrypt filter handling in all routes

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-16 08:38:00 +00:00
co-authored by abnegate
parent 05fd8197b9
commit b58ebdbd15
16 changed files with 142 additions and 0 deletions
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Action;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
@@ -15,6 +16,7 @@ use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Http\Http;
use Utopia\Validator\Boolean;
use Utopia\Validator\Nullable;
use Utopia\Validator\Text;
@@ -62,10 +64,12 @@ class Create extends Action
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -77,12 +81,23 @@ class Create extends Action
?bool $required,
?string $default,
bool $array,
bool $encrypt,
UtopiaResponse $response,
Database $dbForProject,
EventDatabase $queueForDatabase,
Event $queueForEvents,
array $plan,
Authorization $authorization
): void {
if (!Http::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.');
}
$filters = [];
if ($encrypt) {
$filters[] = 'encrypt';
}
$attribute = $this->createAttribute(
$databaseId,
$collectionId,
@@ -93,6 +108,7 @@ class Create extends Action
'required' => $required,
'default' => $default,
'array' => $array,
'filters' => $filters,
]),
$response,
$dbForProject,
@@ -101,6 +117,8 @@ class Create extends Action
$authorization
);
$attribute->setAttribute('encrypt', $encrypt);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
->dynamic($attribute, $this->getResponseModel());
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Action;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
@@ -15,6 +16,7 @@ use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Http\Http;
use Utopia\Validator\Boolean;
use Utopia\Validator\Nullable;
use Utopia\Validator\Text;
@@ -62,10 +64,12 @@ class Create extends Action
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -77,12 +81,23 @@ class Create extends Action
?bool $required,
?string $default,
bool $array,
bool $encrypt,
UtopiaResponse $response,
Database $dbForProject,
EventDatabase $queueForDatabase,
Event $queueForEvents,
array $plan,
Authorization $authorization
): void {
if (!Http::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.');
}
$filters = [];
if ($encrypt) {
$filters[] = 'encrypt';
}
$attribute = $this->createAttribute(
$databaseId,
$collectionId,
@@ -93,6 +108,7 @@ class Create extends Action
'required' => $required,
'default' => $default,
'array' => $array,
'filters' => $filters,
]),
$response,
$dbForProject,
@@ -101,6 +117,8 @@ class Create extends Action
$authorization
);
$attribute->setAttribute('encrypt', $encrypt);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
->dynamic($attribute, $this->getResponseModel());
@@ -4,6 +4,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attribu
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
use Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Attributes\Action;
use Appwrite\SDK\AuthType;
use Appwrite\SDK\Method;
@@ -15,6 +16,7 @@ use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Http\Http;
use Utopia\Validator\Boolean;
use Utopia\Validator\Nullable;
use Utopia\Validator\Text;
@@ -62,10 +64,12 @@ class Create extends Action
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -77,12 +81,23 @@ class Create extends Action
?bool $required,
?string $default,
bool $array,
bool $encrypt,
UtopiaResponse $response,
Database $dbForProject,
EventDatabase $queueForDatabase,
Event $queueForEvents,
array $plan,
Authorization $authorization
): void {
if (!Http::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.');
}
$filters = [];
if ($encrypt) {
$filters[] = 'encrypt';
}
$attribute = $this->createAttribute(
$databaseId,
$collectionId,
@@ -93,6 +108,7 @@ class Create extends Action
'required' => $required,
'default' => $default,
'array' => $array,
'filters' => $filters,
]),
$response,
$dbForProject,
@@ -101,6 +117,8 @@ class Create extends Action
$authorization
);
$attribute->setAttribute('encrypt', $encrypt);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
->dynamic($attribute, $this->getResponseModel());
@@ -16,6 +16,7 @@ use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Key;
use Utopia\Database\Validator\UID;
use Utopia\Http\Adapter\Swoole\Response as SwooleResponse;
use Utopia\Http\Http;
use Utopia\Validator;
use Utopia\Validator\Boolean;
use Utopia\Validator\Nullable;
@@ -66,10 +67,12 @@ class Create extends Action
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -82,18 +85,36 @@ class Create extends Action
?bool $required,
?string $default,
bool $array,
bool $encrypt,
UtopiaResponse $response,
Database $dbForProject,
EventDatabase $queueForDatabase,
Event $queueForEvents,
array $plan,
Authorization $authorization
): void {
if (!Http::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string ' . $this->getSDKGroup() . ' are not available on your plan. Please upgrade to create encrypted string ' . $this->getSDKGroup() . '.');
}
if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) {
throw new Exception(
Exception::GENERAL_BAD_REQUEST,
"Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters."
);
}
// Ensure default fits in the given size
$validator = new Text($size, 0);
if (!is_null($default) && !$validator->isValid($default)) {
throw new Exception($this->getInvalidValueException(), $validator->getDescription());
}
$filters = [];
if ($encrypt) {
$filters[] = 'encrypt';
}
$attribute = $this->createAttribute(
$databaseId,
$collectionId,
@@ -104,6 +125,7 @@ class Create extends Action
'required' => $required,
'default' => $default,
'array' => $array,
'filters' => $filters,
]),
$response,
$dbForProject,
@@ -112,6 +134,8 @@ class Create extends Action
$authorization
);
$attribute->setAttribute('encrypt', $encrypt);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_ACCEPTED)
->dynamic($attribute, $this->getResponseModel());
@@ -57,10 +57,12 @@ class Create extends LongtextCreate
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.', true)
->param('array', false, new Boolean(), 'Is column an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -57,10 +57,12 @@ class Create extends MediumtextCreate
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.', true)
->param('array', false, new Boolean(), 'Is column an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -57,10 +57,12 @@ class Create extends TextCreate
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.', true)
->param('array', false, new Boolean(), 'Is column an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -60,10 +60,12 @@ class Create extends VarcharCreate
->param('required', null, new Boolean(), 'Is column required?')
->param('default', null, new Nullable(new Text(0, 0)), 'Default value for column when not provided. Cannot be set when column is required.', true)
->param('array', false, new Boolean(), 'Is column an array?', true)
->param('encrypt', false, new Boolean(), 'Toggle encryption for the column. Encryption enhances security by not storing any plain text values in the database. However, encrypted columns cannot be queried.', true)
->inject('response')
->inject('dbForProject')
->inject('queueForDatabase')
->inject('queueForEvents')
->inject('plan')
->inject('authorization')
->callback($this->action(...));
}
@@ -18,6 +18,13 @@ class AttributeLongtext extends Attribute
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this attribute is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -18,6 +18,13 @@ class AttributeMediumtext extends Attribute
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this attribute is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -18,6 +18,13 @@ class AttributeText extends Attribute
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this attribute is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -24,6 +24,13 @@ class AttributeVarchar extends Attribute
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this attribute is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -18,6 +18,13 @@ class ColumnLongtext extends Column
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this column is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -18,6 +18,13 @@ class ColumnMediumtext extends Column
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this column is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -18,6 +18,13 @@ class ColumnText extends Column
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this column is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}
@@ -24,6 +24,13 @@ class ColumnVarchar extends Column
'required' => false,
'example' => 'default',
])
->addRule('encrypt', [
'type' => self::TYPE_BOOLEAN,
'description' => 'Defines whether this column is encrypted or not.',
'default' => false,
'required' => false,
'example' => false,
])
;
}