feat: initial commit

This commit is contained in:
Christy Jacob
2023-03-10 11:48:39 +05:30
parent e8c74d7204
commit 1092450d97
19 changed files with 572 additions and 13 deletions
+1
View File
@@ -169,6 +169,7 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/test && \
chmod +x /usr/local/bin/vars && \
chmod +x /usr/local/bin/worker-audits && \
chmod +x /usr/local/bin/worker-backups && \
chmod +x /usr/local/bin/worker-certificates && \
chmod +x /usr/local/bin/worker-databases && \
chmod +x /usr/local/bin/worker-deletes && \
+83
View File
@@ -1185,6 +1185,89 @@ $collections = [
],
],
'backups' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('backups'),
'name' => 'backups',
'attributes' => [
[
'$id' => ID::custom('projectInternalId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('projectId'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('name'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => true,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('description'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 1024,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('path'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 512,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => ID::custom('status'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 256,
'signed' => true,
'required' => true,
'default' => 'processing',
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => ID::custom('_key_project'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectInternalId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
]
],
],
'users' => [
'$collection' => ID::custom(Database::METADATA),
'$id' => ID::custom('users'),
+3 -3
View File
@@ -185,7 +185,7 @@ return [
[
'key' => 'web',
'name' => 'Console',
'version' => '0.0.1',
'version' => '0.0.3',
'url' => 'https://github.com/appwrite/sdk-for-console',
'package' => '',
'enabled' => true,
@@ -197,8 +197,8 @@ return [
'source' => \realpath(__DIR__ . '/../sdks/console-web'),
'gitUrl' => 'git@github.com:appwrite/sdk-for-console.git',
'gitBranch' => 'main',
'gitRepoName' => 'sdk-for-console',
'gitUserName' => 'appwrite',
'gitRepoName' => 'christyjacob4-appwrite-console',
'gitUserName' => '',
],
[
'key' => 'cli',
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+309 -3
View File
@@ -4,7 +4,8 @@ use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\Password;
use Appwrite\Event\Certificate;
use Appwrite\Event\Delete;
use Appwrite\Event\Validator\Event;
use Appwrite\Event\Event;
use Appwrite\Event\Validator\Event as EventValidator;
use Appwrite\Network\Validator\CNAME;
use Utopia\Validator\Domain as DomainValidator;
use Appwrite\Network\Validator\Origin;
@@ -659,7 +660,7 @@ App::post('/v1/projects/:projectId/webhooks')
->label('sdk.response.model', Response::MODEL_WEBHOOK)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
->param('events', null, new ArrayList(new EventValidator(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
->param('url', null, new URL(['http', 'https']), 'Webhook URL.')
->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.')
->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true)
@@ -782,7 +783,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
->param('projectId', '', new UID(), 'Project unique ID.')
->param('webhookId', '', new UID(), 'Webhook unique ID.')
->param('name', null, new Text(128), 'Webhook name. Max length: 128 chars.')
->param('events', null, new ArrayList(new Event(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
->param('events', null, new ArrayList(new EventValidator(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Events list. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' events are allowed.')
->param('url', null, new URL(['http', 'https']), 'Webhook URL.')
->param('security', false, new Boolean(true), 'Certificate verification, false for disabled or true for enabled.')
->param('httpUser', '', new Text(256), 'Webhook HTTP user. Max length: 256 chars.', true)
@@ -1538,3 +1539,308 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
$response->noContent();
});
/** Create CRUD endpoints for creating, getting, deleting and updating backups */
App::post('/v1/projects/:projectId/backups')
->desc('Create Backup')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createBackup')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_BACKUP)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('name', '', new Text(256), 'Backup name.')
->param('description', '', new Text(1024), 'Backup description.', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $name, string $description, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$backup = $dbForConsole->createDocument('backups', new Document([
'$id' => ID::unique(),
'projectId' => $project->getId(),
'projectInternalId' => $project->getInternalId(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'name' => $name,
'description' => $description,
'status' => 'pending',
]));
$event = new Event(Event::BACKUPS_QUEUE_NAME, Event::BACKUPS_CLASS_NAME);
$event
->setProject($project)
->setPayload([
'type' => 'backup',
'backupId' => $backup->getId(),
])
->trigger();
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic($backup, Response::MODEL_BACKUP);
});
App::get('/v1/projects/:projectId/backups')
->desc('List Backups')
->groups(['api', 'projects'])
->label('scope', 'projects.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'listBackups')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_BACKUP_LIST)
->param('projectId', '', new UID(), 'Project unique ID.')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$backups = $dbForConsole->find('backups', [
Query::equal('projectInternalId', [$project->getInternalId()]),
Query::limit(5000)
]);
$response->dynamic(new Document([
'backups' => $backups,
'total' => count($backups),
]), Response::MODEL_BACKUP_LIST);
});
App::get('/v1/projects/:projectId/backups/:backupId')
->desc('Get Backup')
->groups(['api', 'projects'])
->label('scope', 'projects.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'getBackup')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_BACKUP)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('backupId', '', new UID(), 'Backup unique ID.')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $backupId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$backup = $dbForConsole->findOne('backups', [
Query::equal('$id', [$backupId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($backup === false || $backup->isEmpty()) {
throw new Exception(Exception::BACKUP_NOT_FOUND);
}
$response->dynamic($backup, Response::MODEL_BACKUP);
});
App::delete('/v1/projects/:projectId/backups/:backupId')
->desc('Delete Backup')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'deleteBackup')
->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('backupId', '', new UID(), 'Backup unique ID.')
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $backupId, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$backup = $dbForConsole->findOne('backups', [
Query::equal('$id', [$backupId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($backup === false || $backup->isEmpty()) {
throw new Exception(Exception::BACKUP_NOT_FOUND);
}
if (!$dbForConsole->deleteDocument('backups', $backupId)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to delete backup from DB.');
}
$response->noContent();
});
App::patch('/v1/projects/:projectId/backups/:backupId')
->desc('Update Backup')
->groups(['api', 'projects'])
->label('scope', 'projects.write')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'projects')
->label('sdk.method', 'updateBackup')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_BACKUP)
->param('projectId', '', new UID(), 'Project unique ID.')
->param('backupId', '', new UID(), 'Backup unique ID.')
->param('name', null, new Text(256), 'Backup name.', true)
->param('description', null, new Text(1024), 'Backup description.', true)
->inject('response')
->inject('dbForConsole')
->action(function (string $projectId, string $backupId, ?string $name, ?string $description, ?string $schedule, ?int $keep, ?array $webhooks, Response $response, Database $dbForConsole) {
$project = $dbForConsole->getDocument('projects', $projectId);
if ($project->isEmpty()) {
throw new Exception(Exception::PROJECT_NOT_FOUND);
}
$backup = $dbForConsole->findOne('backups', [
Query::equal('$id', [$backupId]),
Query::equal('projectInternalId', [$project->getInternalId()]),
]);
if ($backup === false || $backup->isEmpty()) {
throw new Exception(Exception::BACKUP_NOT_FOUND);
}
$backup
->setAttribute('name', $name ?? $backup->getAttribute('name'))
->setAttribute('description', $description ?? $backup->getAttribute('description'));
if(!$dbForConsole->updateDocument('backups', $backup->getId(), $backup)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to update backup in DB.');
}
$response->dynamic($backup, Response::MODEL_BACKUP);
});
// App::post('/v1/projects/:projectId/backups/:backupId/restore')
// ->desc('Restore Backup')
// ->groups(['api', 'projects'])
// ->label('scope', 'projects.write')
// ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
// ->label('sdk.namespace', 'projects')
// ->label('sdk.method', 'restoreBackup')
// ->label('sdk.response.code', Response::STATUS_CODE_NOCONTENT)
// ->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
// ->param('projectId', '', new UID(), 'Project unique ID.')
// ->param('backupId', '', new UID(), 'Backup unique ID.')
// ->inject('response')
// ->inject('dbForConsole')
// ->action(function (string $projectId, string $backupId, Response $response, Database $dbForConsole) {
// $project = $dbForConsole->getDocument('projects', $projectId);
// if ($project->isEmpty()) {
// throw new Exception(Exception::PROJECT_NOT_FOUND);
// }
// $backup = $dbForConsole->findOne('backups', [
// Query::equal('_uid', [$backupId]),
// Query::equal('projectInternalId', [$project->getInternalId()]),
// ]);
// if ($backup === false || $backup->isEmpty()) {
// throw new Exception(Exception::BACKUP_NOT_FOUND);
// }
// $backupCollection = $dbForConsole->getCollection('backup_' . $backup->getId());
// $collections = $dbForConsole->listCollections();
// foreach ($collections as $collection) {
// if ($collection->getId() === 'backup_' . $backup->getId()) {
// continue;
// }
// $dbForConsole->deleteCollection($collection->getId());
// }
// $collections = $backupCollection->listCollections();
// foreach ($collections as $collection) {
// $dbForConsole->createCollection($collection->getId());
// $documents = $collection->find();
// foreach ($documents as $document) {
// $dbForConsole->createDocument($collection->getId(), $document->getArrayCopy());
// }
// }
// $response->noContent();
// });
// App::get('/v1/projects/:projectId/backups/:backupId/export')
// ->desc('Export Backup')
// ->groups(['api', 'projects'])
// ->label('scope', 'projects.write')
// ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
// ->label('sdk.namespace', 'projects')
// ->label('sdk.method', 'exportBackup')
// ->label('sdk.response.code', Response::STATUS_CODE_OK)
// ->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
// ->label('sdk.response.model', Response::MODEL_BACKUP)
// ->param('projectId', '', new UID(), 'Project unique ID.')
// ->param('backupId', '', new UID(), 'Backup unique ID.')
// ->inject('response')
// ->inject('dbForConsole')
// ->action(function (string $projectId, string $backupId, Response $response, Database $dbForConsole) {
// $project = $dbForConsole->getDocument('projects', $projectId);
// if ($project->isEmpty()) {
// throw new Exception(Exception::PROJECT_NOT_FOUND);
// }
// $backup = $dbForConsole->findOne('backups', [
// Query::equal('_uid', [$backupId]),
// Query::equal('projectInternalId', [$project->getInternalId()]),
// ]);
// if ($backup === false || $backup->isEmpty()) {
// throw new Exception(Exception::BACKUP_NOT_FOUND);
// }
// $backupCollection = $dbForConsole->getCollection('backup_' . $backup->getId());
// $collections = $backupCollection->listCollections();
// $export = [];
// foreach ($collections as $collection) {
// $documents = $collection->find();
// foreach ($documents as $document) {
// $export[$collection->getId()][] = $document->getArrayCopy();
// }
// }
// $response->json($export);
// });
+1
View File
@@ -114,6 +114,7 @@ const APP_STORAGE_FUNCTIONS = '/storage/functions';
const APP_STORAGE_BUILDS = '/storage/builds';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
const APP_STORAGE_BACKUPS = '/storage/backups';
const APP_STORAGE_CONFIG = '/storage/config';
const APP_STORAGE_READ_BUFFER = 20 * (1000 * 1000); //20MB other names `APP_STORAGE_MEMORY_LIMIT`, `APP_STORAGE_MEMORY_BUFFER`, `APP_STORAGE_READ_LIMIT`, `APP_STORAGE_BUFFER_LIMIT`
const APP_SOCIAL_TWITTER = 'https://twitter.com/appwrite';
+39
View File
@@ -0,0 +1,39 @@
<?php
use Appwrite\Event\Event;
use Appwrite\Resque\Worker;
use Utopia\Audit\Audit;
use Utopia\CLI\Console;
use Utopia\Database\Document;
require_once __DIR__ . '/../init.php';
Console::title('Backups V1 Worker');
Console::success(APP_NAME . ' backups worker v1 has started');
class BackupsV1 extends Worker
{
public function getName(): string
{
return "backups";
}
public function init(): void
{
}
public function run(): void
{
$context = $this->args['context'];
$project = $this->args['project'];
$backupId = $this->args['payload']['backupId'];
/** Create a database dump of all the tables in this project database */
$dbForProject = $this->getProjectDB($project->getId());
}
public function shutdown(): void
{
}
}
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
INTERVAL=1 QUEUE='v1-backups' APP_INCLUDE='/usr/src/code/app/workers/backups.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php
+28
View File
@@ -252,6 +252,34 @@ services:
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
appwrite-worker-backups:
entrypoint: worker-backups
<<: *x-logging
container_name: appwrite-worker-backups
image: appwrite-dev
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- mariadb
environment:
- _APP_ENV
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_DB_HOST
- _APP_DB_PORT
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG
appwrite-worker-webhooks:
entrypoint: worker-webhooks
<<: *x-logging
+3
View File
@@ -35,6 +35,9 @@ class Event
public const MESSAGING_QUEUE_NAME = 'v1-messaging';
public const MESSAGING_CLASS_NAME = 'MessagingV1';
public const BACKUPS_QUEUE_NAME = 'v1-backups';
public const BACKUPS_CLASS_NAME = 'BackupsV1';
protected string $queue = '';
protected string $class = '';
protected string $event = '';
+3
View File
@@ -170,6 +170,9 @@ class Exception extends \Exception
public const VARIABLE_NOT_FOUND = 'variable_not_found';
public const VARIABLE_ALREADY_EXISTS = 'variable_already_exists';
/** Backups */
public const BACKUP_NOT_FOUND = 'backup_not_found';
/** Platform */
public const PLATFORM_NOT_FOUND = 'platform_not_found';
+5
View File
@@ -30,6 +30,7 @@ use Appwrite\Utopia\Response\Model\AttributeEnum;
use Appwrite\Utopia\Response\Model\AttributeIP;
use Appwrite\Utopia\Response\Model\AttributeURL;
use Appwrite\Utopia\Response\Model\AttributeDatetime;
use Appwrite\Utopia\Response\Model\Backup;
use Appwrite\Utopia\Response\Model\BaseList;
use Appwrite\Utopia\Response\Model\Collection;
use Appwrite\Utopia\Response\Model\Database;
@@ -205,6 +206,8 @@ class Response extends SwooleResponse
public const MODEL_DOMAIN_LIST = 'domainList';
public const MODEL_VARIABLE = 'variable';
public const MODEL_VARIABLE_LIST = 'variableList';
public const MODEL_BACKUP = 'backup';
public const MODEL_BACKUP_LIST = 'backupList';
// Health
public const MODEL_HEALTH_STATUS = 'healthStatus';
@@ -274,6 +277,7 @@ class Response extends SwooleResponse
->setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE))
->setModel(new BaseList('Metric List', self::MODEL_METRIC_LIST, 'metrics', self::MODEL_METRIC, true, false))
->setModel(new BaseList('Variables List', self::MODEL_VARIABLE_LIST, 'variables', self::MODEL_VARIABLE))
->setModel(new BaseList('Backups List', self::MODEL_BACKUP_LIST, 'backups', self::MODEL_BACKUP))
// Entities
->setModel(new Database())
->setModel(new Collection())
@@ -288,6 +292,7 @@ class Response extends SwooleResponse
->setModel(new AttributeIP())
->setModel(new AttributeURL())
->setModel(new AttributeDatetime())
->setModel(new Backup())
->setModel(new Index())
->setModel(new ModelDocument())
->setModel(new Log())
@@ -0,0 +1,80 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class Backup extends Model
{
public function __construct()
{
$this
->addRule('$id', [
'type' => self::TYPE_STRING,
'description' => 'Bucket ID.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('$createdAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Bucket creation time in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$updatedAt', [
'type' => self::TYPE_DATETIME,
'description' => 'Bucket update date in ISO 8601 format.',
'default' => '',
'example' => self::TYPE_DATETIME_EXAMPLE,
])
->addRule('$permissions', [
'type' => self::TYPE_STRING,
'description' => 'Backup permissions. [Learn more about permissions](/docs/permissions).',
'default' => [],
'example' => ['read("any")'],
'array' => true,
])
->addRule('name', [
'type' => self::TYPE_STRING,
'description' => 'Bucket name.',
'default' => '',
'example' => 'Documents',
])
->addRule('description', [
'type' => self::TYPE_STRING,
'description' => 'Allowed file extensions.',
'default' => [],
'example' => 'This Backup was created on the 21st of March 2023',
'array' => false
])
->addRule('status', [
'type' => self::TYPE_STRING,
'description' => 'Status of the backup. One of pending, processing, created, failed.',
'default' => [],
'example' => 'pending',
'array' => false
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Backup';
}
/**
* Get Collection
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_BACKUP;
}
}