Merge pull request #1380 from appwrite/feat-storage-buckets

This commit is contained in:
Damodar Lohani 2022-02-16 13:45:25 +05:45 committed by GitHub
commit cecc99b04e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1737 changed files with 36691 additions and 1148 deletions

3
.env
View file

@ -20,6 +20,7 @@ _APP_DB_PORT=3306
_APP_DB_SCHEMA=appwrite
_APP_DB_USER=user
_APP_DB_PASS=password
_APP_STORAGE_DEVICE=Local
_APP_STORAGE_ANTIVIRUS=disabled
_APP_STORAGE_ANTIVIRUS_HOST=clamav
_APP_STORAGE_ANTIVIRUS_PORT=3310
@ -32,7 +33,7 @@ _APP_SMTP_PORT=1025
_APP_SMTP_SECURE=
_APP_SMTP_USERNAME=
_APP_SMTP_PASSWORD=
_APP_STORAGE_LIMIT=10000000
_APP_STORAGE_LIMIT=30000000
_APP_FUNCTIONS_TIMEOUT=900
_APP_FUNCTIONS_CONTAINERS=10
_APP_FUNCTIONS_CPUS=1

View file

@ -42,4 +42,4 @@ jobs:
if: always()
run: |
docker compose down -v
docker ps -aq | xargs docker rm --force
docker ps -aq | xargs docker rm --force

View file

@ -152,6 +152,15 @@ ENV _APP_SERVER=swoole \
_APP_STORAGE_ANTIVIRUS=enabled \
_APP_STORAGE_ANTIVIRUS_HOST=clamav \
_APP_STORAGE_ANTIVIRUS_PORT=3310 \
_APP_STORAGE_DEVICE=Local \
_APP_STORAGE_DEVICE_S3_ACCESS_KEY= \
_APP_STORAGE_DEVICE_S3_SECRET= \
_APP_STORAGE_DEVICE_S3_REGION= \
_APP_STORAGE_DEVICE_S3_BUCKET= \
_APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY= \
_APP_STORAGE_DEVICE_DO_SPACES_SECRET= \
_APP_STORAGE_DEVICE_DO_SPACES_REGION= \
_APP_STORAGE_DEVICE_DO_SPACES_BUCKET= \
_APP_REDIS_HOST=redis \
_APP_REDIS_PORT=6379 \
_APP_DB_HOST=mariadb \

View file

@ -6,6 +6,15 @@ use Utopia\Database\Database;
$providers = Config::getParam('providers', []);
$auth = Config::getParam('auth', []);
/**
* $collection => id of the parent collection where this will be inserted
* $id => id of this collection
* name => name of this collection
* project => whether or not this collection should be created per project
* attributes => list of attributes
* indexes => list of indexes
*/
$collections = [
'collections' => [
'$collection' => Database::METADATA,
@ -1558,196 +1567,6 @@ $collections = [
],
],
'files' => [
'$collection' => Database::METADATA,
'$id' => 'files',
'name' => 'Files',
'attributes' => [
[
'$id' => 'dateCreated',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'array' => false,
'$id' => 'bucketId',
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'name',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'path',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'signature',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'mimeType',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 127, // https://tools.ietf.org/html/rfc4288#section-4.2
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'sizeOriginal',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'sizeActual',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'algorithm',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 255,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'comment',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLVersion',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 64,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLCipher',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 64,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLTag',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLIV',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'search',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => '_key_bucket',
'type' => Database::INDEX_KEY,
'attributes' => ['bucketId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => '_key_search',
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [],
'orders' => [],
],
],
],
'functions' => [
'$collection' => Database::METADATA,
'$id' => 'functions',
@ -1981,6 +1800,28 @@ $collections = [
'array' => false,
'filters' => [],
],
[
'$id' => 'chunksTotal',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'chunksUploaded',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'search',
'type' => Database::VAR_STRING,
@ -2232,6 +2073,131 @@ $collections = [
],
],
'buckets' => [
'$collection' => Database::METADATA,
'$id' => 'buckets',
'name' => 'Buckets',
'attributes' => [
[
'$id' => 'dateCreated',
'type' => Database::VAR_INTEGER,
'format' => '',
'signed' => false,
'size' => 0,
'required' => false,
'array' => false,
'filters' => [],
],
[
'$id' => 'dateUpdated',
'type' => Database::VAR_INTEGER,
'size' => 0,
'format' => '',
'signed' => false,
'required' => false,
'array' => false,
'filters' => [],
],
[
'$id' => 'enabled',
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => 'name',
'type' => Database::VAR_STRING,
'signed' => true,
'size' => 128,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => 'permission',
'type' => Database::VAR_STRING,
'size' => 64,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'maximumFileSize',
'type' => Database::VAR_INTEGER,
'signed' => false,
'size' => 8,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => 'allowedFileExtensions',
'type' => Database::VAR_STRING,
'signed' => true,
'size' => 64,
'format' => '',
'filters' => [],
'required' => true,
'array' => true,
],
[
'$id' => 'encryption',
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => 'antivirus',
'type' => Database::VAR_BOOLEAN,
'signed' => true,
'size' => 0,
'format' => '',
'filters' => [],
'required' => true,
'array' => false,
],
[
'$id' => 'search',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => '_fulltext_name',
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['name'],
'lengths' => [1024],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => '_key_search',
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [2048],
'orders' => [Database::ORDER_ASC],
],
]
],
'stats' => [
'$collection' => Database::METADATA,
'$id' => 'stats',
@ -2367,6 +2333,228 @@ $collections = [
],
]
],
'files' => [
'$collection' => 'buckets',
'$id' => 'files',
'$name' => 'Files',
'attributes' => [
[
'$id' => 'dateCreated',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'array' => false,
'$id' => 'bucketId',
'type' => Database::VAR_STRING,
'format' => '',
'size' => Database::LENGTH_KEY,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'name',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'path',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'signature',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'mimeType',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 127, // https://tools.ietf.org/html/rfc4288#section-4.2
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'metadata',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384, // https://tools.ietf.org/html/rfc4288#section-4.2
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['json'],
],
[
'$id' => 'sizeOriginal',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 8,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'sizeActual',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 8,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'algorithm',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 255,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'comment',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLVersion',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 64,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLCipher',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 64,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLTag',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'openSSLIV',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'chunksTotal',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'chunksUploaded',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'search',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
],
'indexes' => [
[
'$id' => '_key_search',
'type' => Database::INDEX_FULLTEXT,
'attributes' => ['search'],
'lengths' => [2048],
'orders' => [Database::ORDER_ASC],
],
[
'$id' => '_key_bucket',
'type' => Database::INDEX_KEY,
'attributes' => ['bucketId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
],
]
],
];
return $collections;

View file

@ -192,6 +192,21 @@ return [
'model' => Response::MODEL_FILE,
'note' => '',
],
'storage.buckets.create' => [
'description' => 'This event triggers when a storage bucket is created.',
'model' => Response::MODEL_BUCKET,
'note' => '',
],
'storage.buckets.update' => [
'description' => 'This event triggers when a storage bucket is updated.',
'model' => Response::MODEL_BUCKET,
'note' => '',
],
'storage.buckets.delete' => [
'description' => 'This event triggers when a storage bucket is deleted.',
'model' => Response::MODEL_BUCKET,
'note' => '',
],
'users.create' => [
'description' => 'This event triggers when a user is created from the users API.',
'model' => Response::MODEL_USER,

View file

@ -28,6 +28,8 @@ $admins = [
'documents.write',
'files.read',
'files.write',
'buckets.read',
'buckets.write',
'users.read',
'users.write',
'collections.read',

View file

@ -43,6 +43,12 @@ return [ // List of publicly visible scopes
'files.write' => [
'description' => 'Access to create, update, and delete your project\'s storage files',
],
'buckets.read' => [
'description' => 'Access to read your project\'s storage buckets',
],
'buckets.write' => [
'description' => 'Access to create, update, and delete your project\'s storage buckets',
],
'functions.read' => [
'description' => 'Access to read your project\'s functions and code tags',
],

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

View file

@ -420,6 +420,78 @@ return [
'question' => '',
'filter' => ''
],
[
'name' => '_APP_STORAGE_DEVICE',
'description' => 'Select default storage device. The default value is \'Local\'. List of supported adapters are \'Local\', \'S3\' and \'DOSpaces\'.',
'introduction' => '0.13.0',
'default' => 'Local',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_S3_ACCESS_KEY',
'description' => 'AWS S3 storage access key. Required when the storage adapter is set to S3. You can get your access key from your AWS console',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_S3_SECRET',
'description' => 'AWS S3 storage secret key. Required when the storage adapter is set to S3. You can get your secret key from your AWS console.',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_S3_REGION',
'description' => 'AWS S3 storage region. Required when storage adapter is set to S3. You can find your region info for your bucket from AWS console.',
'introduction' => '0.13.0',
'default' => 'us-eas-1',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_S3_BUCKET',
'description' => 'AWS S3 storage bucket. Required when storage adapter is set to S3. You can create buckets in your AWS console.',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY',
'description' => 'DigitalOcean spaces access key. Required when the storage adapter is set to DOSpaces. You can get your access key from your DigitalOcean console.',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_DO_SPACES_SECRET',
'description' => 'DigitalOcean spaces secret key. Required when the storage adapter is set to DOSpaces. You can get your secret key from your DigitalOcean console.',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_DO_SPACES_REGION',
'description' => 'DigitalOcean spaces region. Required when storage adapter is set to DOSpaces. You can find your region info for your space from DigitalOcean console.',
'introduction' => '0.13.0',
'default' => 'us-eas-1',
'required' => false,
'question' => '',
],
[
'name' => '_APP_STORAGE_DEVICE_DO_SPACES_BUCKET',
'description' => 'DigitalOcean spaces bucket. Required when storage adapter is set to DOSpaces. You can create spaces in your DigitalOcean console.',
'introduction' => '0.13.0',
'default' => '',
'required' => false,
'question' => '',
],
],
],
[

View file

@ -452,11 +452,15 @@ App::post('/v1/functions/:functionId/tags')
->inject('response')
->inject('dbForProject')
->inject('usage')
->action(function ($functionId, $command, $file, $request, $response, $dbForProject, $usage) {
/** @var Appwrite\Utopia\Request $request */
->inject('deviceFunctions')
->inject('deviceLocal')
->action(function ($functionId, $command, $file, $request, $response, $dbForProject, $usage, $deviceFunctions, $deviceLocal) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $usage */
/** @var Utopia\Storage\Device $deviceFunctions */
/** @var Utopia\Storage\Device $deviceLocal */
$function = $dbForProject->getDocument('functions', $functionId);
@ -465,9 +469,8 @@ App::post('/v1/functions/:functionId/tags')
}
$file = $request->getFiles('code');
$device = Storage::getDevice('functions');
$fileExt = new FileExt([FileExt::TYPE_GZIP]);
$fileSize = new FileSize(App::getEnv('_APP_STORAGE_LIMIT', 0));
$fileSizeValidator = new FileSize(App::getEnv('_APP_STORAGE_LIMIT', 0));
$upload = new Upload();
if (empty($file)) {
@ -475,42 +478,102 @@ App::post('/v1/functions/:functionId/tags')
}
// Make sure we handle a single file and multiple files the same way
$file['name'] = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name'];
$file['tmp_name'] = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name'];
$file['size'] = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
$fileName = (\is_array($file['name']) && isset($file['name'][0])) ? $file['name'][0] : $file['name'];
$fileTmpName = (\is_array($file['tmp_name']) && isset($file['tmp_name'][0])) ? $file['tmp_name'][0] : $file['tmp_name'];
$fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size'];
if (!$fileExt->isValid($file['name'])) { // Check if file type is allowed
throw new Exception('File type not allowed', 400);
}
if (!$fileSize->isValid($file['size'])) { // Check if file size is exceeding allowed limit
$contentRange = $request->getHeader('content-range');
$tagId = $dbForProject->getId();
$chunk = 1;
$chunks = 1;
if (!empty($contentRange)) {
$start = $request->getContentRangeStart();
$end = $request->getContentRangeEnd();
$fileSize = $request->getContentRangeSize();
$tagId = $request->getHeader('x-appwrite-id', $tagId);
if(is_null($start) || is_null($end) || is_null($fileSize)) {
throw new Exception('Invalid content-range header', 400);
}
if ($end === $fileSize) {
//if it's a last chunks the chunk size might differ, so we set the $chunks and $chunk to notify it's last chunk
$chunks = $chunk = -1;
} else {
// Calculate total number of chunks based on the chunk size i.e ($rangeEnd - $rangeStart)
$chunks = (int) ceil($fileSize / ($end + 1 - $start));
$chunk = (int) ($start / ($end + 1 - $start)) + 1;
}
}
if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit
throw new Exception('File size not allowed', 400);
}
if (!$upload->isValid($file['tmp_name'])) {
if (!$upload->isValid($fileTmpName)) {
throw new Exception('Invalid file', 403);
}
// Save to storage
$size = $device->getFileSize($file['tmp_name']);
$path = $device->getPath(\uniqid().'.'.\pathinfo($file['name'], PATHINFO_EXTENSION));
$fileSize ??= $deviceLocal->getFileSize($fileTmpName);
$path = $deviceFunctions->getPath($tagId.'.'.\pathinfo($fileName, PATHINFO_EXTENSION));
if (!$device->upload($file['tmp_name'], $path)) { // TODO deprecate 'upload' and replace with 'move'
$tag = $dbForProject->getDocument('tags', $tagId);
if(!$tag->isEmpty()) {
$chunks = $tag->getAttribute('chunksTotal', 1);
if($chunk == -1) {
$chunk = $chunks;
}
}
$chunksUploaded = $deviceFunctions->upload($fileTmpName, $path, $chunk, $chunks);
if (empty($chunksUploaded)) {
throw new Exception('Failed moving file', 500);
}
$tagId = $dbForProject->getId();
$tag = $dbForProject->createDocument('tags', new Document([
'$id' => $tagId,
'$read' => [],
'$write' => [],
'functionId' => $function->getId(),
'dateCreated' => time(),
'command' => $command,
'path' => $path,
'size' => $size,
'search' => implode(' ', [$tagId, $command]),
]));
if($chunksUploaded === $chunks) {
$fileSize = $deviceFunctions->getFileSize($path);
if ($tag->isEmpty()) {
$tag = $dbForProject->createDocument('tags', new Document([
'$id' => $tagId,
'$read' => [],
'$write' => [],
'functionId' => $function->getId(),
'dateCreated' => time(),
'command' => $command,
'path' => $path,
'size' => $fileSize,
'search' => implode(' ', [$tagId, $command]),
]));
} else {
$tag = $dbForProject->updateDocument('tags', $tagId, $tag->setAttribute('size', $fileSize));
}
} else {
if($tag->isEmpty()) {
$tag = $dbForProject->createDocument('tags', new Document([
'$id' => $tagId,
'$read' => [],
'$write' => [],
'functionId' => $function->getId(),
'dateCreated' => time(),
'command' => $command,
'path' => $path,
'size' => 0,
'chunksTotal' => $chunks,
'chunksUploaded' => $chunksUploaded,
'search' => implode(' ', [$tagId, $command]),
]));
} else {
$tag = $dbForProject->updateDocument('tags', $tagId, $tag->setAttribute('chunksUploaded', $chunksUploaded));
}
}
$usage
->setParam('storage', $tag->getAttribute('size', 0))
@ -629,10 +692,12 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
->inject('response')
->inject('dbForProject')
->inject('usage')
->action(function ($functionId, $tagId, $response, $dbForProject, $usage) {
->inject('deviceFunctions')
->action(function ($functionId, $tagId, $response, $dbForProject, $usage, $deviceFunctions) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $usage */
/** @var Utopia\Storage\Device $deviceFunctions */
$function = $dbForProject->getDocument('functions', $functionId);
@ -650,9 +715,7 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
throw new Exception('Tag not found', 404);
}
$device = Storage::getDevice('functions');
if ($device->delete($tag->getAttribute('path', ''))) {
if ($deviceFunctions->delete($tag->getAttribute('path', ''))) {
if (!$dbForProject->deleteDocument('tags', $tag->getId())) {
throw new Exception('Failed to remove tag from DB', 500);
}

View file

@ -358,11 +358,12 @@ App::get('/v1/health/stats') // Currently only used internally
->label('docs', false)
->inject('response')
->inject('register')
->action(function ($response, $register) {
->inject('deviceFiles')
->action(function ($response, $register, $deviceFiles) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Registry\Registry $register */
/** @var Utopia\Storage\Device $deviceFiles */
$device = Storage::getDevice('files');
$cache = $register->get('cache');
$cacheStats = $cache->info();
@ -370,9 +371,9 @@ App::get('/v1/health/stats') // Currently only used internally
$response
->json([
'storage' => [
'used' => Storage::human($device->getDirectorySize($device->getRoot().'/')),
'partitionTotal' => Storage::human($device->getPartitionTotalSpace()),
'partitionFree' => Storage::human($device->getPartitionFreeSpace()),
'used' => Storage::human($deviceFiles->getDirectorySize($deviceFiles->getRoot().'/')),
'partitionTotal' => Storage::human($deviceFiles->getPartitionTotalSpace()),
'partitionFree' => Storage::human($deviceFiles->getPartitionFreeSpace()),
],
'cache' => [
'uptime' => $cacheStats['uptime_in_seconds'] ?? 0,

View file

@ -114,6 +114,9 @@ App::post('/v1/projects')
$adapter->setup();
foreach ($collections as $key => $collection) {
if(($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
}
$attributes = [];
$indexes = [];

File diff suppressed because it is too large Load diff

View file

@ -185,7 +185,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons
->addHeader('Server', 'Appwrite')
->addHeader('X-Content-Type-Options', 'nosniff')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, X-Appwrite-ID, Content-Range, Range, Cache-Control, Expires, Pragma')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $refDomain)
->addHeader('Access-Control-Allow-Credentials', 'true')
@ -303,7 +303,7 @@ App::options(function ($request, $response) {
$response
->addHeader('Server', 'Appwrite')
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, X-Appwrite-ID, Content-Range, Range, Cache-Control, Expires, Pragma, X-Fallback-Cookies')
->addHeader('Access-Control-Expose-Headers', 'X-Fallback-Cookies')
->addHeader('Access-Control-Allow-Origin', $origin)
->addHeader('Access-Control-Allow-Credentials', 'true')
@ -400,6 +400,7 @@ App::error(function ($error, $utopia, $request, $response, $layout, $project, $l
case 404: // Error allowed publicly
case 409: // Error allowed publicly
case 412: // Error allowed publicly
case 416: // Error allowed publicly
case 429: // Error allowed publicly
case 501: // Error allowed publicly
case 503: // Error allowed publicly

View file

@ -6,9 +6,11 @@ use Utopia\App;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Database\Document;
use Utopia\Storage\Device\DOSpaces;
use Utopia\Database\Validator\Authorization;
use Utopia\Exception;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Storage;
App::init(function ($utopia, $request, $response, $project, $user, $events, $audits, $usage, $deletes, $database, $dbForProject, $mode) {
@ -26,9 +28,6 @@ App::init(function ($utopia, $request, $response, $project, $user, $events, $aud
/** @var Appwrite\Event\Event $functions */
/** @var Utopia\Database\Database $dbForProject */
Storage::setDevice('files', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
Storage::setDevice('functions', new Local(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()));
$route = $utopia->match($request);
if ($project->isEmpty() && $route->getLabel('abuse-limit', 0) > 0) { // Abuse limit requires an active project scope

View file

@ -315,6 +315,36 @@ App::get('/console/storage')
->setParam('body', $page);
});
App::get('/console/storage/bucket')
->groups(['web', 'console'])
->label('permission', 'public')
->label('scope', 'console')
->param('id', '', new UID(), 'Bucket unique ID.')
->inject('response')
->inject('layout')
->action(function ($id, $response, $layout) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\View $layout */
$page = new View(__DIR__.'/../../views/console/storage/bucket.phtml');
$page
->setParam('home', App::getEnv('_APP_HOME', 0))
->setParam('fileLimit', App::getEnv('_APP_STORAGE_LIMIT', 0))
->setParam('fileLimitHuman', Storage::human(App::getEnv('_APP_STORAGE_LIMIT', 0)))
;
$layout
->setParam('title', APP_NAME.' - Storage Buckets')
->setParam('body', $page)
;
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Expires', 0)
->addHeader('Pragma', 'no-cache')
;
});
App::get('/console/users')
->groups(['web', 'console'])
->label('permission', 'public')

View file

@ -13,6 +13,7 @@ use Utopia\Config\Config;
use Utopia\Database\Validator\Authorization;
use Utopia\Audit\Audit;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Swoole\Files;
use Appwrite\Utopia\Request;
@ -21,7 +22,7 @@ use Utopia\Logger\Log\User;
$http = new Server("0.0.0.0", App::getEnv('PORT', 80));
$payloadSize = max(4000000 /* 4mb */, App::getEnv('_APP_STORAGE_LIMIT', 10000000 /* 10mb */));
$payloadSize = 6 * (1024 * 1024); // 6MB
$http
->set([
@ -109,10 +110,12 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
}
foreach ($collections as $key => $collection) {
if(($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
}
if(!$dbForConsole->getCollection($key)->isEmpty()) {
continue;
}
Console::success('[Setup] - Creating collection: ' . $collection['$id'] . '...');
$attributes = [];
@ -141,8 +144,61 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
}
$dbForConsole->createCollection($key, $attributes, $indexes);
}
if($dbForConsole->getDocument('buckets', 'default')->isEmpty()) {
Console::success('[Setup] - Creating default bucket...');
$dbForConsole->createDocument('buckets', new Document([
'$id' => 'default',
'$collection' => 'buckets',
'dateCreated' => \time(),
'dateUpdated' => \time(),
'name' => 'Default',
'permission' => 'file',
'maximumFileSize' => (int) App::getEnv('_APP_STORAGE_LIMIT', 0), // 10MB
'allowedFileExtensions' => [],
'enabled' => true,
'encryption' => true,
'antivirus' => true,
'$read' => ['role:all'],
'$write' => ['role:all'],
'search' => 'buckets Default',
]));
Console::success('[Setup] - Creating files collection for default bucket...');
$files = $collections['files'] ?? [];
if(empty($files)) {
throw new Exception('Files collection is not configured.');
}
$attributes = [];
$indexes = [];
foreach ($files['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => $attribute['$id'],
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
]);
}
foreach ($files['indexes'] as $index) {
$indexes[] = new Document([
'$id' => $index['$id'],
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$dbForConsole->createCollection('bucket_' . 'default', $attributes, $indexes);
}
Console::success('[Setup] - Server database init completed...');
});

View file

@ -49,6 +49,10 @@ use Swoole\Database\PDOPool;
use Swoole\Database\RedisConfig;
use Swoole\Database\RedisPool;
use Utopia\Database\Query;
use Utopia\Storage\Storage;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\DOSpaces;
const APP_NAME = 'Appwrite';
const APP_DOMAIN = 'appwrite.io';
@ -60,6 +64,9 @@ const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 12;
const APP_LIMIT_COUNT = 5000;
const APP_LIMIT_USERS = 10000;
const APP_LIMIT_ANTIVIRUS = 20000000; //20MB
const APP_LIMIT_ENCRYPTION = 20000000; //20MB
const APP_LIMIT_COMPRESSION = 20000000; //20MB
const APP_CACHE_BUSTER = 201;
const APP_VERSION_STABLE = '0.13.0';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
@ -74,6 +81,7 @@ const APP_STORAGE_FUNCTIONS = '/storage/functions';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
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';
const APP_SOCIAL_TWITTER_HANDLE = 'appwrite';
const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
@ -106,6 +114,7 @@ const DELETE_TYPE_ABUSE = 'abuse';
const DELETE_TYPE_CERTIFICATES = 'certificates';
const DELETE_TYPE_USAGE = 'usage';
const DELETE_TYPE_REALTIME = 'realtime';
const DELETE_TYPE_BUCKETS = 'buckets';
// Mail Types
const MAIL_TYPE_VERIFICATION = 'verification';
const MAIL_TYPE_MAGIC_SESSION = 'magicSession';
@ -116,6 +125,8 @@ const APP_AUTH_TYPE_SESSION = 'Session';
const APP_AUTH_TYPE_JWT = 'JWT';
const APP_AUTH_TYPE_KEY = 'Key';
const APP_AUTH_TYPE_ADMIN = 'Admin';
// Response related
const MAX_OUTPUT_CHUNK_SIZE = 2*1024*1024; // 2MB
$register = new Registry();
@ -781,6 +792,53 @@ App::setResource('dbForConsole', function($db, $cache) {
return $database;
}, ['db', 'cache']);
App::setResource('deviceLocal', function() {
return new Local();
});
App::setResource('deviceFiles', function($project) {
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
case Storage::DEVICE_LOCAL:default:
return new Local(APP_STORAGE_UPLOADS . '/app-' . $project->getId());
case Storage::DEVICE_S3:
$s3AccessKey = App::getEnv('_APP_STORAGE_DEVICE_S3_ACCESS_KEY', '');
$s3SecretKey = App::getEnv('_APP_STORAGE_DEVICE_S3_SECRET', '');
$s3Region = App::getEnv('_APP_STORAGE_DEVICE_S3_REGION', '');
$s3Bucket = App::getEnv('_APP_STORAGE_DEVICE_S3_BUCKET', '');
$s3Acl = 'private';
return new S3(APP_STORAGE_UPLOADS . '/app-' . $project->getId(), $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY', '');
$doSpacesSecretKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_SECRET', '');
$doSpacesRegion = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_REGION', '');
$doSpacesBucket = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_BUCKET', '');
$doSpacesAcl = 'private';
return new DOSpaces(APP_STORAGE_UPLOADS . '/app-' . $project->getId(), $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
}
}, ['project']);
App::setResource('deviceFunctions', function($project) {
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
case Storage::DEVICE_LOCAL:default:
return new Local(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId());
case Storage::DEVICE_S3:
$s3AccessKey = App::getEnv('_APP_STORAGE_DEVICE_S3_ACCESS_KEY', '');
$s3SecretKey = App::getEnv('_APP_STORAGE_DEVICE_S3_SECRET', '');
$s3Region = App::getEnv('_APP_STORAGE_DEVICE_S3_REGION', '');
$s3Bucket = App::getEnv('_APP_STORAGE_DEVICE_S3_BUCKET', '');
$s3Acl = 'private';
return new S3(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId(), $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY', '');
$doSpacesSecretKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_SECRET', '');
$doSpacesRegion = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_REGION', '');
$doSpacesBucket = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_BUCKET', '');
$doSpacesAcl = 'private';
return new DOSpaces(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId(), $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
}
}, ['project']);
App::setResource('mode', function($request) {
/** @var Appwrite\Utopia\Request $request */

View file

@ -30,7 +30,7 @@ $cli
$production = ($git) ? (Console::confirm('Type "Appwrite" to push code to production git repos') == 'Appwrite') : false;
$message = ($git) ? Console::confirm('Please enter your commit message:') : '';
if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', 'latest'])) {
if(!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', 'latest'])) {
throw new Exception('Unknown version given');
}

View file

@ -36,7 +36,15 @@ use Utopia\Database\Validator\Authorization;
* database.collections.{collectionId}.documents.delete
*
* Storage
*
*
* storage.buckets.create
* storage.buckets.read
* storage.buckets.update
* storage.buckets.delete
* storage.files.create
* storage.files.read
* storage.files.update
* storage.files.delete
* storage.buckets.{bucketId}.files.create
* storage.buckets.{bucketId}.files.read
* storage.buckets.{bucketId}.files.update
@ -61,7 +69,9 @@ use Utopia\Database\Validator\Authorization;
* Counters
*
* users.count
* storage.buckets.count
* storage.files.count
* storage.buckets.{bucketId}.files.count
* database.collections.count
* database.documents.count
* database.collections.{collectionId}.documents.count
@ -142,6 +152,30 @@ $cli
'table' => 'appwrite_usage_database_documents_delete',
'groupBy' => 'collectionId',
],
'storage.buckets.create' => [
'table' => 'appwrite_usage_storage_buckets_create',
],
'storage.buckets.read' => [
'table' => 'appwrite_usage_storage_buckets_read',
],
'storage.buckets.update' => [
'table' => 'appwrite_usage_storage_buckets_update',
],
'storage.buckets.delete' => [
'table' => 'appwrite_usage_storage_buckets_delete',
],
'storage.files.create' => [
'table' => 'appwrite_usage_storage_files_create',
],
'storage.files.read' => [
'table' => 'appwrite_usage_storage_files_read',
],
'storage.files.update' => [
'table' => 'appwrite_usage_storage_files_update',
],
'storage.files.delete' => [
'table' => 'appwrite_usage_storage_files_delete',
],
'storage.buckets.bucketId.files.create' => [
'table' => 'appwrite_usage_storage_files_create',
'groupBy' => 'bucketId',
@ -370,17 +404,17 @@ $cli
// Get total storage
$dbForProject->setNamespace('_project_' . $projectId);
$storageTotal = $dbForProject->sum('files', 'sizeOriginal') + $dbForProject->sum('tags', 'size');
$storageTotal = $dbForProject->sum('tags', 'size');
$time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes
$id = \md5($time . '_30m_storage.total'); //Construct unique id for each metric using time, period and metric
$id = \md5($time . '_30m_storage.tags.total'); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'period' => '30m',
'time' => $time,
'metric' => 'storage.total',
'metric' => 'storage.tags.total',
'value' => $storageTotal,
'type' => 1,
]));
@ -393,14 +427,14 @@ $cli
}
$time = (int) (floor(time() / 86400) * 86400); // Time rounded to nearest day
$id = \md5($time . '_1d_storage.total'); //Construct unique id for each metric using time, period and metric
$id = \md5($time . '_1d_storage.tags.total'); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'period' => '1d',
'time' => $time,
'metric' => 'storage.total',
'metric' => 'storage.tags.total',
'value' => $storageTotal,
'type' => 1,
]));
@ -414,21 +448,30 @@ $cli
$collections = [
'users' => [
'namespace' => 'internal',
'namespace' => '',
],
'collections' => [
'metricPrefix' => 'database',
'namespace' => 'internal',
'namespace' => '',
'subCollections' => [ // Some collections, like collections and later buckets have child collections that need counting
'documents' => [
'namespace' => 'external',
'namespace' => '',
],
],
],
'files' => [
'buckets' => [
'metricPrefix' => 'storage',
'namespace' => 'internal',
],
'namespace' => '',
'subCollections' => [
'files' => [
'namespace' => '',
'collectionPrefix' => 'bucket_',
'sum' => [
'field' => 'sizeOriginal'
]
],
]
]
];
foreach ($collections as $collection => $options) {
@ -486,6 +529,7 @@ $cli
$latestParent = null;
$subCollectionCounts = []; //total project level count of sub collections
$subCollectionTotals = []; //total project level sum of sub collections
do { // Loop over all the parent collection document for each sub collection
$dbForProject->setNamespace("_project_{$projectId}");
@ -500,7 +544,7 @@ $cli
foreach ($parents as $parent) {
foreach ($subCollections as $subCollection => $subOptions) { // Sub collection counts, like database.collections.collectionId.documents.count
$dbForProject->setNamespace("_project_{$projectId}");
$count = $dbForProject->count($parent->getId());
$count = $dbForProject->count(($subOptions['collectionPrefix'] ?? '') . $parent->getId());
$subCollectionCounts[$subCollection] = ($subCollectionCounts[$subCollection] ?? 0) + $count; // Project level counts for sub collections like database.documents.count
@ -546,6 +590,55 @@ $cli
$document->setAttribute('value', $count)
);
}
// check if sum calculation is required
$sum = $subOptions['sum'] ?? [];
if(empty($sum)) {
continue;
}
$dbForProject->setNamespace("_project_{$projectId}");
$total = (int) $dbForProject->sum(($subOptions['collectionPrefix'] ?? '') . $parent->getId(), $sum['field']);
$subCollectionTotals[$subCollection] = ($ssubCollectionTotals[$subCollection] ?? 0) + $total; // Project level sum for sub collections like storage.total
$dbForProject->setNamespace("_project_{$projectId}");
$metric = empty($metricPrefix) ? "{$collection}.{$parent->getId()}.{$subCollection}.total" : "{$metricPrefix}.{$collection}.{$parent->getId()}.{$subCollection}.total";
$time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes
$id = \md5($time . '_30m_' . $metric); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'time' => $time,
'period' => '30m',
'metric' => $metric,
'value' => $total,
'type' => 1,
]));
} else {
$dbForProject->updateDocument('stats', $document->getId(),
$document->setAttribute('value', $total));
}
$time = (int) (floor(time() / 86400) * 86400); // Time rounded to nearest day
$id = \md5($time . '_1d_' . $metric); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'time' => $time,
'period' => '1d',
'metric' => $metric,
'value' => $total,
'type' => 1,
]));
} else {
$dbForProject->updateDocument('stats', $document->getId(),
$document->setAttribute('value', $total));
}
}
}
} while (!empty($parents));
@ -598,7 +691,50 @@ $cli
);
}
}
} catch (\Exception $e) {
/**
* Inserting project level sums for sub collections like storage.total
*/
foreach ($subCollectionTotals as $subCollection => $count) {
$dbForProject->setNamespace("_project_{$projectId}");
$metric = empty($metricPrefix) ? "{$subCollection}.total" : "{$metricPrefix}.{$subCollection}.total";
$time = (int) (floor(time() / 1800) * 1800); // Time rounded to nearest 30 minutes
$id = \md5($time . '_30m_' . $metric); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'time' => $time,
'period' => '30m',
'metric' => $metric,
'value' => $count,
'type' => 1,
]));
} else {
$dbForProject->updateDocument('stats', $document->getId(),
$document->setAttribute('value', $count));
}
$time = (int) (floor(time() / 86400) * 86400); // Time rounded to nearest day
$id = \md5($time . '_1d_' . $metric); //Construct unique id for each metric using time, period and metric
$document = $dbForProject->getDocument('stats', $id);
if ($document->isEmpty()) {
$dbForProject->createDocument('stats', new Document([
'$id' => $id,
'time' => $time,
'period' => '1d',
'metric' => $metric,
'value' => $count,
'type' => 1,
]));
} else {
$dbForProject->updateDocument('stats', $document->getId(),
$document->setAttribute('value', $count));
}
}
} catch (\Exception$e) {
Console::warning("Failed to save database counters data for project {$collection}: {$e->getMessage()}");
}
}

View file

@ -0,0 +1,497 @@
<?php
$home = $this->getParam('home', '');
$fileLimit = $this->getParam('fileLimit', 0);
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
?>
<div
data-service="storage.getBucket"
data-param-bucket-id="{{router.params.id}}"
data-scope="sdk"
data-event="load,storage.updateBucket"
data-name="project-bucket">
<div class="cover">
<h1 class="zone xl margin-bottom-large">
<a data-ls-attrs="href=/console/storage?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Storage</a>
<br />
<span data-ls-bind="{{project-bucket.name}}">&nbsp;&nbsp;</span>
</h1>
</div>
<div data-ui-modal class="modal width-large box close" data-button-hide="on" data-open-event="open-json">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h2>JSON View</h2>
<div class="margin-bottom">
<input type="hidden" data-ls-bind="{{project-bucket}}" data-forms-code />
</div>
<button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</div>
<div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
<li data-state="/console/storage/bucket?id={{router.params.id}}&project={{router.params.project}}">
<h2 class="margin-bottom">Files</h2>
<form class="box padding-small margin-bottom search"
data-service="storage.listFiles"
data-event="submit"
data-param-bucket-id="{{router.params.id}}"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset=""
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-success="state"
data-success-param-state-keys="search,offset">
<div class="row thin responsive">
<div class="col span-10">
<input name="search" id="searchFiles" type="search" autocomplete="off" placeholder="Search" class="margin-bottom-no" data-ls-bind="{{router.params.search}}">
</div>
<div class="col span-2 desktops-only">
<button class="fill" title="Search" aria-label="Search">Search</button>
</div>
</div>
</form>
<div
data-service="storage.listFiles"
data-event="load,storage.createFile,storage.updateFile,storage.deleteFile"
data-param-bucket-id="{{router.params.id}}"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset="{{router.params.offset}}"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files">
<div data-ls-if="0 == {{project-files.sum}}" class="box margin-bottom">
<h3 class="margin-bottom-small text-bold">No Files Found</h3>
<p class="margin-bottom-no">Upload your first file to get started</p>
</div>
<div data-ls-if="0 != {{project-files.sum}}">
<div class="margin-bottom-small text-align-end text-size-small text-fade"><span data-ls-bind="{{project-files.sum}}"></span> files found</div>
<div class="box margin-bottom">
<table class="vertical">
<thead>
<tr>
<th width="40"></th>
<th>Filename</th>
<th width="140">Type</th>
<th width="100">Size</th>
<th width="120">Created</th>
</tr>
</thead>
<tbody data-ls-loop="project-files.files" data-ls-as="file">
<tr>
<td class="hide">
<img src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/buckets/{{router.params.id}}/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
</td>
<td data-title="Name: " class="text-one-liner" data-ls-attrs="title={{file.name}}" >
<div data-ui-modal class="box modal sticky-footer width-large close" data-button-text="{{file.name}}" data-button-class="link" data-button-element="span">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Update File</h1>
<hr />
<div class="row responsive modalize">
<div class="col span-8">
<form class="strip"
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Storage File"
data-service="storage.updateFile"
data-event="file-update-{{file.$id}}"
data-scope="sdk"
data-success="alert,trigger"
data-success-param-alert-text="File updated successfully"
data-success-param-trigger-events="storage.updateFile"
data-failure="alert"
data-failure-param-alert-text="Failed to update file"
data-failure-param-alert-classname="error">
<label for="files-fileId">File ID</label>
<div class="input-copy">
<input data-forms-copy type="text" data-ls-attrs="id=file-id-{{file.$id}}" name="fileId" disabled data-ls-bind="{{file.$id}}" />
</div>
<input type="hidden" data-ls-attrs="id=file-bucketId-{{file.$id}}" name="bucketId" data-ls-bind="{{file.bucketId}}">
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-read-{{file.$id}}" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-write-{{file.$id}}" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</form>
<form class="strip"
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Delete File"
data-service="storage.deleteFile"
data-scope="sdk"
data-event="file-delete-{{file.$id}}"
data-confirm="Are you sure you want to delete this file?"
data-success="alert,trigger"
data-success-param-alert-text="Deleted file successfully"
data-success-param-trigger-events="storage.deleteFile"
data-failure="alert"
data-failure-param-alert-text="Failed to delete file"
data-failure-param-alert-classname="error">
<input type="hidden" name="bucketId" data-ls-bind="{{file.bucketId}}" />
<input type="hidden" name="fileId" data-ls-bind="{{file.$id}}" />
</form>
</div>
<div data-ls-if="{{file.chunksTotal}} == {{file.chunksUploaded}}" class="col span-4 text-size-small">
<div class="margin-bottom-small">File Preview</div>
<div class="margin-bottom-small">
<img src="" class="file-preview" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/buckets/{{router.params.id}}/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
</div>
<div class="margin-bottom-tiny">
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/buckets/{{router.params.id}}/files/{{file.$id}}/view?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> New Window <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom-small">
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/buckets/{{router.params.id}}/files/{{file.$id}}/download?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Download <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom-tiny">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Type: <span data-ls-bind="{{file.mimeType}}"></span>
</div>
<div class="margin-bottom-tiny">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Size: <span data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</div>
<div class="margin-bottom">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Created at: <span data-ls-bind="{{file.dateCreated|dateText}}"></span>
</div>
</div>
</div>
<footer>
<button class="link pull-end text-danger" data-ls-ui-trigger="file-delete-{{file.$id}},modal-close">Delete File</button>
<button type="button" data-ls-if="{{file.chunksTotal}} == {{file.chunksUploaded}}" data-ls-ui-trigger="file-update-{{file.$id}},modal-close">Update</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse desktops-only-inline tablets-only-inline">Cancel</button>
</footer>
</div>
</td>
<td data-title="Type: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.mimeType}}"></span>
</td>
<td data-title="Size: ">
<div data-ls-if="{{file.chunksTotal}} == {{file.chunksUploaded}}" >
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</div>
<span class="text-fade text-size-small" data-ls-if="{{file.chunksTotal}} != {{file.chunksUploaded}}">incomplete</span>
</td>
<td data-title="Created: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="pull-end text-align-center paging">
<form
data-service="storage.listFiles"
data-event="submit"
data-param-search="{{router.params.search}}"
data-param-bucket-id="{{router.params.id}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-sum="{{project-files.sum}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
</form>
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-files.sum|pageTotal}}"></span>
<form
data-service="storage.listFiles"
data-event="submit"
data-param-bucket-id="{{router.params.id}}"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-files.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
</form>
</div>
<div data-ui-modal class="box modal sticky-footer close" data-button-text="Add File">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Upload File</h1>
<form
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Create Storage File"
data-service="storage.createFile"
data-event="submit"
data-scope="sdk"
data-loading="Uploading File..."
data-success="alert,trigger,reset"
data-success-param-alert-text="File uploaded successfully"
data-success-param-trigger-events="storage.createFile"
data-failure="alert"
data-failure-param-alert-text="Failed to upload file"
data-failure-param-alert-classname="error">
<input type="hidden" name="bucketId" id="files-bucketId" data-ls-bind="{{router.params.id}}">
<label for="fileId">File ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="storage.getFile"
required
maxlength="36"
name="fileId"
id="fileId" />
<label for="file-read">File</label>
<input type="file" name="file" id="file-file" size="1" required>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['role:all'])); ?>" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</footer>
</form>
</div>
</div>
</li>
<li data-state="/console/storage/bucket/usage?id={{router.params.id}}&project={{router.params.project}}">
<form
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
data-service="storage.getBucketUsage"
data-event="submit"
data-name="usage"
data-param-bucket-id="{{router.params.id}}"
data-param-range="90d">
<button class="tick">90d</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
<form
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
data-service="storage.getBucketUsage"
data-event="submit"
data-name="usage"
data-param-bucket-id="{{router.params.id}}">
<button class="tick">30d</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
<form
class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
data-service="storage.getBucketUsage"
data-event="submit"
data-name="usage"
data-param-bucket-id="{{router.params.id}}"
data-param-range="24h">
<button class="tick">24h</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
<h2>Usage</h2>
<div data-service="storage.getBucketUsage" data-event="load" data-name="usage" data-param-bucket-id="{{router.params.id}}">
<h3 class="margin-bottom-tiny">Files</h3>
<p class="text-fade">Count of files over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-show-y-axis="true" data-forms-chart="Files=filesCount" data-height="140" />
</div>
</div>
</div>
<ul class="chart-notes margin-bottom-large">
<li>Files </li>
</ul>
<h3 class="margin-bottom-tiny">Operations</h3>
<p class="text-fade">Count of files create, read, update and delete operations over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-show-y-axis="true" data-forms-chart="Create=filesCreate,Read=filesRead,Updated=filesUpdate,Deleted=filesDelete" data-colors="create,read,update,delete" data-height="140" />
</div>
</div>
</div>
<ul class="chart-notes crud margin-bottom-large">
<li>Create</li>
<li>Read</li>
<li>Update</li>
<li>Delete</li>
</ul>
</div>
</li>
<li data-state="/console/storage/bucket/settings?id={{router.params.id}}&project={{router.params.project}}">
<h2>Settings</h2>
<div class="row responsive margin-top-negative">
<div class="col span-8 margin-bottom">
<form
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Storage Bucket"
data-service="storage.updateBucket"
data-scope="sdk"
data-event="submit"
data-param-bucket-id="{{router.params.id}}"
data-success="alert,trigger"
data-success-param-alert-text="Updated bucket successfully"
data-success-param-trigger-events="storage.updateBucket"
data-failure="alert"
data-failure-param-alert-text="Failed to update bucket"
data-failure-param-alert-classname="error">
<label>&nbsp;</label>
<div class="box">
<label for="bucket-name">Name</label>
<input name="name" id="bucket-name" type="text" autocomplete="off" data-ls-bind="{{project-bucket.name}}" data-forms-text-direction required placeholder="Bucket Name" maxlength="128" />
<label for="bucket-maximum-file-size">Maximum File Size (bytes) <span class="tooltip small" data-tooltip="Limit file size allowed in the bucket."><i class="icon-info-circled"></i></span></label>
<input name="maximumFileSize" id="bucket-maximum-file-size" type="number" autocomplete="off" data-ls-bind="{{project-bucket.maximumFileSize}}" min="1" data-cast-to="integer" />
<div class="margin-bottom">
<input name="enabled" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.enabled}}" /> &nbsp; Enabled <span class="tooltip" data-tooltip="Mark whether bucket is enabled"><i class="icon-info-circled"></i></span>
</div>
<div class="margin-bottom">
<input name="encryption" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.encryption}}" /> &nbsp; Encryption <span class="tooltip" data-tooltip="Mark whether bucket is encrypted"><i class="icon-info-circled"></i></span>
</div>
<div class="margin-bottom">
<input name="antivirus" type="hidden" data-forms-switch data-cast-to="boolean" data-ls-bind="{{project-bucket.antivirus}}" /> &nbsp; Anti Virus <span class="tooltip" data-tooltip="Mark whether anti virus scanning is enabled"><i class="icon-info-circled"></i></span>
</div>
<label for="bucket-allowedFileExtensions">Allowed File Extensions</label>
<input type="hidden" id="bucket-allowedFileExtensions" name="allowedFileExtensions" data-forms-tags data-cast-to="json" data-ls-bind="{{project-bucket.allowedFileExtensions}}" placeholder="Allowed file extensions (pdf, mp4)" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Leave empty to allow all.</div>
<label class="margin-bottom-small">Permissions</label>
<p class="text-fade text-size-small">Choose the permissions model for this bucket.</p>
<hr class="margin-top-small" />
<div class="row">
<div class="col span-1"><input name="permission" value="bucket" type="radio" class="margin-top-tiny" data-ls-bind="{{project-bucket.permission}}" /></div>
<div class="col span-11">
<b>Bucket Level</b>
<p class="text-fade margin-top-tiny">With Bucket Level permissions, you assign permissions only once in the bucket.</p>
<p class="text-fade margin-top-tiny">In this permission level permissions assigned to bucket takes the precedence and file permissions are ignored</p>
<div data-ls-if="{{project-bucket.permission}} == 'bucket'">
<label for="bucket-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
<input type="hidden" id="bucket-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-bucket.$permissions.read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="bucket-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="bucket-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-bucket.$permissions.write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</div>
</div>
</div>
<div class="row">
<div class="col span-1"><input name="permission" value="file" type="radio" class="margin-top-no" data-ls-bind="{{project-bucket.permission}}" /></div>
<div class="col span-11">
<b>File Level</b>
<p class="text-fade margin-top-tiny">With File Level permissions, you have granular access control over every file. Users will only be able to access files for which they have explicit permissions.</p>
<p class="text-fade margin-top-tiny">In this permission level file permissions take precedence and bucket permissions are ignored.</p>
</div>
</div>
<hr class="margin-top-no" />
<button>Update</button>
</form>
</div>
</div>
<div class="col span-4 sticky-top">
<label>Bucket ID</label>
<div class="input-copy margin-bottom">
<input id="id" type="text" autocomplete="off" placeholder="" data-ls-bind="{{project-bucket.$id}}" disabled data-forms-copy class="margin-bottom-no" />
</div>
<ul class="margin-bottom-large text-fade text-size-small">
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Last Updated: <span data-ls-bind="{{project-bucket.dateUpdated|dateText}}"></span></li>
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{project-bucket.dateCreated|dateText}}"></span></li>
</ul>
<form name="storage.deleteBucket" class="margin-bottom"
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Delete Storage Bucket"
data-service="storage.deleteBucket"
data-event="submit"
data-param-bucket-id="{{router.params.id}}"
data-confirm="Are you sure you want to delete this bucket?"
data-success="alert,trigger,redirect"
data-success-param-alert-text="Bucket deleted successfully"
data-success-param-trigger-events="storage.deleteBucket"
data-success-param-redirect-url="/console/storage?project={{router.params.project}}"
data-failure="alert"
data-failure-param-alert-text="Failed to delete bucket"
data-failure-param-alert-classname="error">
<button type="submit" class="danger fill">Delete Bucket</button>
</form>
</div>
</div>
</li>
</ul>
</div>
</div>

View file

@ -1,8 +1,3 @@
<?php
$home = $this->getParam('home', '');
$fileLimit = $this->getParam('fileLimit', 0);
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
?>
<div class="cover">
<h1 class="zone xl margin-bottom-large">
<a data-ls-attrs="href=/console/home?project={{router.params.project}}" class="back text-size-small link-return-animation--start"><i class="icon-left-open"></i> Home</a>
@ -15,320 +10,204 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
<li data-state="/console/storage?project={{router.params.project}}">
<h2 class="margin-bottom">Files</h2>
<h2>Buckets</h2>
<form class="box padding-small margin-bottom search"
data-service="storage.listFiles"
data-event="submit"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset=""
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-success="state"
data-success-param-state-keys="search,offset">
<div class="row thin responsive">
<div class="col span-10">
<input name="search" id="searchFiles" type="search" autocomplete="off" placeholder="Search" class="margin-bottom-no" data-ls-bind="{{router.params.search}}">
</div>
<div class="col span-2 desktops-only">
<button class="fill" title="Search" aria-label="Search">Search</button>
</div>
</div>
</form>
<div
data-service="storage.listFiles"
data-event="load,storage.createFile,storage.updateFile,storage.deleteFile"
<div class="margin-top"
data-service="storage.listBuckets"
data-event="load,storage.createBucket,storage.updateBucket,storage.deleteBucket"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset="{{router.params.offset}}"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files">
data-name="project-buckets">
<div data-ls-if="0 == {{project-files.sum}}" class="box margin-bottom">
<h3 class="margin-bottom-small text-bold">No Files Found</h3>
<div data-ls-if="(!{{project-buckets.sum}})" class="box dashboard margin-bottom">
<div class="margin-bottom-small margin-top-small margin-end margin-start">
<h3 class="margin-bottom-small text-bold">No Buckets Found</h3>
<p class="margin-bottom-no">Upload your first file to get started</p>
<p class="margin-bottom-no">You haven't created any buckets for your project yet.</p>
</div>
</div>
<div data-ls-if="0 != {{project-files.sum}}">
<div class="margin-bottom-small text-align-end text-size-small text-fade"><span data-ls-bind="{{project-files.sum}}"></span> files found</div>
<div data-ls-if="0 != {{project-buckets.sum}}">
<ul data-ls-loop="project-buckets.buckets" data-ls-as="bucket" data-ls-append="" class="tiles cell-3 margin-bottom-small">
<li class="margin-bottom">
<a data-ls-attrs="href=/console/storage/bucket?id={{bucket.$id}}&project={{router.params.project}}" class="box">
<div data-ls-bind="{{bucket.name}}" class="text-one-liner margin-bottom text-bold">&nbsp;</div>
<div class="box margin-bottom">
<table class="vertical">
<thead>
<tr>
<th width="40"></th>
<th>Filename</th>
<th width="140">Type</th>
<th width="100">Size</th>
<th width="120">Created</th>
</tr>
</thead>
<tbody data-ls-loop="project-files.files" data-ls-as="file">
<tr>
<td class="hide">
<img src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="pull-start avatar" width="30" height="30" loading="lazy" />
</td>
<td data-title="Name: " class="text-one-liner" data-ls-attrs="title={{file.name}}" >
<div data-ui-modal class="box modal sticky-footer width-large close" data-button-text="{{file.name}}" data-button-class="link" data-button-element="span">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Update File</h1>
<hr />
<div class="row responsive modalize">
<div class="col span-8">
<form class="strip"
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Storage File"
data-service="storage.updateFile"
data-event="file-update-{{file.$id}}"
data-scope="sdk"
data-success="alert,trigger"
data-success-param-alert-text="File updated successfully"
data-success-param-trigger-events="storage.updateFile"
data-failure="alert"
data-failure-param-alert-text="Failed to update file"
data-failure-param-alert-classname="error">
<label for="files-fileId">File ID</label>
<div class="input-copy">
<input data-forms-copy type="text" data-ls-attrs="id=file-id-{{file.$id}}" name="fileId" disabled data-ls-bind="{{file.$id}}" />
</div>
<input type="hidden" data-ls-attrs="id=file-folderId-{{file.$id}}" name="folderId" data-cast-to="integer" value="1">
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-read-{{file.$id}}" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-write-{{file.$id}}" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</form>
<form class="strip"
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Delete File"
data-service="storage.deleteFile"
data-scope="sdk"
data-event="file-delete-{{file.$id}}"
data-confirm="Are you sure you want to delete this file?"
data-success="alert,trigger"
data-success-param-alert-text="Deleted file successfully"
data-success-param-trigger-events="storage.deleteFile"
data-failure="alert"
data-failure-param-alert-text="Failed to delete file"
data-failure-param-alert-classname="error">
<input type="hidden" name="fileId" data-ls-bind="{{file.$id}}" />
</form>
</div>
<div class="col span-4 text-size-small">
<div class="margin-bottom-small">File Preview</div>
<div class="margin-bottom-small">
<img src="" class="file-preview" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
</div>
<div class="margin-bottom-tiny">
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/view?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> New Window <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom-small">
<a href="" data-ls-attrs="href={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/download?project={{router.params.project}}&mode=admin" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Download <i class="icon-link-ext"></i></a>
</div>
<div class="margin-bottom-tiny">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Type: <span data-ls-bind="{{file.mimeType}}"></span>
</div>
<div class="margin-bottom-tiny">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Size: <span data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</div>
<div class="margin-bottom">
<i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Created at: <span data-ls-bind="{{file.dateCreated|dateText}}"></span>
</div>
</div>
</div>
<footer>
<button class="link pull-end text-danger" data-ls-ui-trigger="file-delete-{{file.$id}},modal-close">Delete File</button>
<button type="button" data-ls-ui-trigger="file-update-{{file.$id}},modal-close">Update</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse desktops-only-inline tablets-only-inline">Cancel</button>
</footer>
</div>
</td>
<td data-title="Type: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.mimeType}}"></span>
</td>
<td data-title="Size: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileSize}}"></span>
<span class="text-fade text-size-small" data-ls-bind="{{file.sizeOriginal|humanFileUnit}}"></span>
</td>
<td data-title="Created: ">
<span class="text-fade text-size-small" data-ls-bind="{{file.dateCreated|dateText}}"></span>
</td>
</tr>
</tbody>
</table>
</div>
<i class="icon-right-open"></i>
</a>
</li>
</ul>
</div>
<div class="pull-end text-align-center paging">
<form
data-service="storage.listFiles"
data-service="storage.listBuckets"
data-event="submit"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-name="project-buckets"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-sum="{{project-files.sum}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-sum="{{project-buckets.sum}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
</form>
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-files.sum|pageTotal}}"></span>
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-buckets.sum|pageTotal}}"></span>
<form
data-service="storage.listFiles"
data-service="storage.listBuckets"
data-event="submit"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-files"
data-name="project-buckets"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-files.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-buckets.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
</form>
</div>
<div data-ui-modal class="box modal sticky-footer close" data-button-text="Add File">
<div data-ui-modal class="modal close box sticky-footer" data-button-text="Add Bucket">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Upload File</h1>
<h1>New Bucket</h1>
<form
data-analytics
data-analytics-activity
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Create Storage File"
data-service="storage.createFile"
data-analytics-label="Create Storage Bucket"
data-service="storage.createBucket"
data-event="submit"
data-scope="sdk"
data-loading="Uploading File..."
data-success="alert,trigger,reset"
data-success-param-alert-text="File uploaded successfully"
data-success-param-trigger-events="storage.createFile"
data-success="alert,reset,redirect,trigger"
data-success-param-alert-text="Bucket created successfully"
data-success-param-redirect-url="/console/storage/bucket/settings?id={{serviceData.$id}}&project={{router.params.project}}"
data-success-param-trigger-events="storage.createBucket"
data-failure="alert"
data-failure-param-alert-text="Failed to upload file"
data-failure-param-alert-text="Failed to create bucket"
data-failure-param-alert-classname="error">
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="integer" value="1">
<label for="fileId">File ID</label>
<label for="bucket-id">Bucket ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="storage.getFile"
data-validator="storage.getBucket"
required
maxlength="36"
pattern="^[a-zA-Z0-9][a-zA-Z0-9._-]{1,36}$"
name="fileId"
id="fileId" />
name="bucketId"
id="bucketId" />
<label for="file-read">File</label>
<input type="file" name="file" id="file-file" size="1" required>
<label for="bucket-name">Name</label>
<input type="text" class="full-width" id="bucket-name" name="name" required autocomplete="off" maxlength="128" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
<input type="hidden" id="bucket-permission" name="permission" required value="bucket" />
<input type="hidden" id="bucket-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
<input type="hidden" id="bucket-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['role:all'])); ?>" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<hr />
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</form>
</div>
</div>
</li>
<li data-state="/console/storage/usage?project={{router.params.project}}">
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
</li>
<li data-state="/console/storage/usage?project={{router.params.project}}">
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
data-service="storage.getUsage"
data-event="submit"
data-name="usage"
data-param-range="90d">
<button class="tick">90d</button>
</form>
<button class="tick">90d</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
data-service="storage.getUsage"
data-event="submit"
data-name="usage">
<button class="tick">30d</button>
</form>
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
data-service="storage.getUsage"
data-event="submit"
data-name="usage">
<button class="tick">30d</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
data-service="storage.getUsage"
data-event="submit"
data-name="usage"
data-param-range="24h">
<button class="tick">24h</button>
</form>
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
data-service="storage.getUsage"
data-event="submit"
data-name="usage"
data-param-range="24h">
<button class="tick">24h</button>
</form>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
<h2>Usage</h2>
<h2>Usage</h2>
<div
data-service="storage.getUsage"
data-event="load"
data-name="usage">
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Total Files=files" data-height="140" data-show-y-axis="true" />
<div
data-service="storage.getUsage"
data-event="load"
data-name="usage">
<h3 class="margin-bottom-tiny">Objects</h3>
<p class="text-fade">Count of buckets, files and total storage used over time</p>
<div class="box">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-show-y-axis="true" data-forms-chart="Total Files=filesCount,Total Buckets=bucketsCount" data-height="140" />
</div>
</div>
</div>
</div>
<ul class="chart-notes margin-bottom-large">
<li>Total Files <span data-ls-bind="({{usage.files|statsGetLast|statsTotal}})"></span></li>
</ul>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Total Storage=storage" data-height="140" data-show-y-axis="true" />
<ul class="chart-notes margin-top-small margin-bottom-large">
<li>Total Files</li>
<li>Total Buckets</li>
<!-- <li>Total Storage <span data-ls-bind="({{usage.filesStorage|statsGetLast|statsTotal}})"></span></li> -->
</ul>
<!-- CRUDS class for graph fixed colors, use color codes from Docs for CRUD operations -->
<h3 class="margin-bottom-tiny">Buckets</h3>
<p class="text-fade">Count of bucket create, read, update and delete operations over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no crud margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Buckets create=bucketsCreate,Buckets read=bucketsRead,Buckets update=bucketsUpdate,Buckets delete=bucketsDelete" data-show-y-axis="true" data-colors="create,read,update,delete" data-height="140" />
</div>
</div>
</div>
</div>
<ul class="chart-notes margin-bottom-large">
<li>Total Storage (<span data-ls-bind="{{usage.storage|statsGetLast|humanFileSize}}"></span> <span data-ls-bind="{{usage.storage|statsGetLast|humanFileUnit}}"></span>)</li>
</ul>
</div>
</li>
</ul>
<ul class="chart-notes crud margin-bottom-large">
<li class="green">Create</li>
<li class="green">Read</li>
<li class="green">Update</li>
<li class="green">Delete</li>
</ul>
<h3 class="margin-bottom-tiny">Files</h3>
<p class="text-fade">Count of file create, read, update and delete operations over time</p>
<div class="box margin-bottom-small">
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
<div class="chart background-image-no border-no crud margin-bottom-no">
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Files create=filesCreate,Files read=filesRead,Files update=filesUpdate,Files delete=filesDelete" data-show-y-axis="true" data-colors="create,read,update,delete" data-height="140" />
</div>
</div>
</div>
<ul class="chart-notes crud margin-bottom-large">
<li class="green">Create</li>
<li class="green">Read</li>
<li class="green">Update</li>
<li class="green">Delete</li>
</ul>
</div>
</li>
</ul>
</div>
</div>

View file

@ -1,11 +1,15 @@
<?php
use Utopia\App;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Appwrite\Resque\Worker;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Device\DOSpaces;
use Utopia\Storage\Storage;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\CLI\Console;
@ -56,6 +60,9 @@ class DeletesV1 extends Worker
case DELETE_TYPE_TEAMS:
$this->deleteMemberships($document, $projectId);
break;
case DELETE_TYPE_BUCKETS:
$this->deleteBucket($document, $projectId);
break;
default:
Console::error('No lazy delete operation available for document of type: ' . $document->getCollection());
break;
@ -448,4 +455,34 @@ class DeletesV1 extends Worker
Console::info("No certificate files found for {$domain}");
}
}
protected function deleteBucket(Document $document, string $projectId)
{
$bucketId = $document->getId();
$dbForProject = $this->getProjectDB($projectId);
$dbForProject->deleteCollection('bucket_' . $bucketId);
$device = new Local(APP_STORAGE_UPLOADS.'/app-'.$projectId);
switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) {
case Storage::DEVICE_S3:
$s3AccessKey = App::getEnv('_APP_STORAGE_DEVICE_S3_ACCESS_KEY', '');
$s3SecretKey = App::getEnv('_APP_STORAGE_DEVICE_S3_SECRET', '');
$s3Region = App::getEnv('_APP_STORAGE_DEVICE_S3_REGION', '');
$s3Bucket = App::getEnv('_APP_STORAGE_DEVICE_S3_BUCKET', '');
$s3Acl = 'private';
$device = new S3(APP_STORAGE_UPLOADS . '/app-' . $projectId, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl);
break;
case Storage::DEVICE_DO_SPACES:
$doSpacesAccessKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY', '');
$doSpacesSecretKey = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_SECRET', '');
$doSpacesRegion = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_REGION', '');
$doSpacesBucket = App::getEnv('_APP_STORAGE_DEVICE_DO_SPACES_BUCKET', '');
$doSpacesAcl = 'private';
$device = new DOSpaces(APP_STORAGE_UPLOADS . '/app-' . $projectId, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl);
break;
}
$device->deletePath($bucketId);
}
}

View file

@ -53,7 +53,7 @@
"utopia-php/preloader": "0.2.*",
"utopia-php/domains": "1.1.*",
"utopia-php/swoole": "0.3.*",
"utopia-php/storage": "0.5.*",
"utopia-php/storage": "0.7.*",
"utopia-php/websocket": "0.1.0",
"utopia-php/image": "0.5.*",
@ -66,8 +66,14 @@
"adhocore/jwt": "1.1.2",
"slickdeals/statsd": "3.1.0"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/appwrite/sdk-generator"
}
],
"require-dev": {
"appwrite/sdk-generator": "0.17.1",
"appwrite/sdk-generator": "dev-feat-preps-for-0.13",
"phpunit/phpunit": "9.5.10",
"swoole/ide-helper": "4.8.3",
"textalk/websocket": "1.5.5",

39
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ab493f0a7f01a1105f8bc5caaf9b928b",
"content-hash": "0a0bb53e6a5daeb3afde139b8199da3b",
"packages": [
{
"name": "adhocore/jwt",
@ -2636,20 +2636,20 @@
},
{
"name": "utopia-php/storage",
"version": "0.5.1",
"version": "0.6.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/storage.git",
"reference": "e672aa3fc2a8ba689aff65f68ff29f1d608223b8"
"reference": "ad628025be3b3e0818ea1e6cb701cc08a1c52344"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/e672aa3fc2a8ba689aff65f68ff29f1d608223b8",
"reference": "e672aa3fc2a8ba689aff65f68ff29f1d608223b8",
"url": "https://api.github.com/repos/utopia-php/storage/zipball/ad628025be3b3e0818ea1e6cb701cc08a1c52344",
"reference": "ad628025be3b3e0818ea1e6cb701cc08a1c52344",
"shasum": ""
},
"require": {
"php": ">=7.4",
"php": ">=8.0",
"utopia-php/framework": "0.*.*"
},
"require-dev": {
@ -2682,9 +2682,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/storage/issues",
"source": "https://github.com/utopia-php/storage/tree/0.5.1"
"source": "https://github.com/utopia-php/storage/tree/0.6.0"
},
"time": "2021-12-13T15:17:14+00:00"
"time": "2022-01-31T06:29:51+00:00"
},
{
"name": "utopia-php/swoole",
@ -3083,17 +3083,11 @@
},
{
"name": "appwrite/sdk-generator",
"version": "0.17.1",
"version": "dev-feat-preps-for-0.13",
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator.git",
"reference": "3542c6ed0f808b6a9f6735a8aad7ccda961bea29"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/3542c6ed0f808b6a9f6735a8aad7ccda961bea29",
"reference": "3542c6ed0f808b6a9f6735a8aad7ccda961bea29",
"shasum": ""
"url": "https://github.com/appwrite/sdk-generator",
"reference": "96735eef25d5a98d0582bb4925b42db593c974f8"
},
"require": {
"ext-curl": "*",
@ -3113,7 +3107,6 @@
"Appwrite\\Spec\\": "src/Spec"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@ -3124,11 +3117,7 @@
}
],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"support": {
"issues": "https://github.com/appwrite/sdk-generator/issues",
"source": "https://github.com/appwrite/sdk-generator/tree/0.17.1"
},
"time": "2022-01-07T12:55:37+00:00"
"time": "2022-01-30T07:29:08+00:00"
},
{
"name": "composer/pcre",
@ -6644,7 +6633,9 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"appwrite/sdk-generator": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {

View file

@ -112,6 +112,15 @@ services:
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
- _APP_STORAGE_DEVICE
- _APP_STORAGE_DEVICE_S3_ACCESS_KEY
- _APP_STORAGE_DEVICE_S3_SECRET
- _APP_STORAGE_DEVICE_S3_REGION
- _APP_STORAGE_DEVICE_S3_BUCKET
- _APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DEVICE_DO_SPACES_SECRET
- _APP_STORAGE_DEVICE_DO_SPACES_REGION
- _APP_STORAGE_DEVICE_DO_SPACES_BUCKET
- _APP_SMTP_HOST
- _APP_SMTP_PORT
- _APP_SMTP_SECURE
@ -254,6 +263,15 @@ services:
- _APP_DB_SCHEMA
- _APP_DB_USER
- _APP_DB_PASS
- _APP_STORAGE_DEVICE
- _APP_STORAGE_DEVICE_S3_ACCESS_KEY
- _APP_STORAGE_DEVICE_S3_SECRET
- _APP_STORAGE_DEVICE_S3_REGION
- _APP_STORAGE_DEVICE_S3_BUCKET
- _APP_STORAGE_DEVICE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DEVICE_DO_SPACES_SECRET
- _APP_STORAGE_DEVICE_DO_SPACES_REGION
- _APP_STORAGE_DEVICE_DO_SPACES_BUCKET
- _APP_LOGGING_PROVIDER
- _APP_LOGGING_CONFIG

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createAnonymousSession(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createJWT(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createMagicURLSession(
"[USER_ID]",
"email@example.com",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createOAuth2Session(
this,
"amazon",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createRecovery(
"email@example.com",
"https://example.com"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createSession(
"email@example.com",
"password"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.createVerification(
"https://example.com"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,50 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.create(
"[USER_ID]",
"email@example.com",
"password",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.deleteSession(
"[SESSION_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.deleteSessions(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.delete(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,47 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.getLogs(
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.getPrefs(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.getSession(
"[SESSION_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.getSessions(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.get(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updateEmail(
"email@example.com",
"password"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updateMagicURLSession(
"[USER_ID]",
"[SECRET]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updateName(
"[NAME]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updatePassword(
"password",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updatePrefs(
mapOf( "a" to "b" )
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,51 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updateRecovery(
"[USER_ID]",
"[SECRET]",
"password",
"password"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Account account = new Account(client);
account.updateVerification(
"[USER_ID]",
"[SECRET]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getBrowser(
"aa",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getCreditCard(
"amex",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getFavicon(
"https://example.com"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getFlag(
"af",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getImage(
"https://example.com",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,47 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getInitials(
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Avatars
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Avatars avatars = new Avatars(client);
avatars.getQR(
"[TEXT]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,50 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Database
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Database database = new Database(client);
database.createDocument(
"[COLLECTION_ID]",
"[DOCUMENT_ID]",
mapOf( "a" to "b" ),
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Database
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Database database = new Database(client);
database.deleteDocument(
"[COLLECTION_ID]",
"[DOCUMENT_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Database
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Database database = new Database(client);
database.getDocument(
"[COLLECTION_ID]",
"[DOCUMENT_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Database
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Database database = new Database(client);
database.listDocuments(
"[COLLECTION_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,50 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Database
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Database database = new Database(client);
database.updateDocument(
"[COLLECTION_ID]",
"[DOCUMENT_ID]",
mapOf( "a" to "b" ),
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Functions
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);
functions.createExecution(
"[FUNCTION_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Functions
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);
functions.getExecution(
"[FUNCTION_ID]",
"[EXECUTION_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Functions
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Functions functions = new Functions(client);
functions.listExecutions(
"[FUNCTION_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getContinents(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getCountriesEU(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getCountriesPhones(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getCountries(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getCurrencies(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.getLanguages(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,46 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Locale
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Locale locale = new Locale(client);
locale.get(new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
});
}
}

View file

@ -0,0 +1,50 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.createFile(
"[BUCKET_ID]",
"[FILE_ID]",
File("./path-to-files/image.jpg"),
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.deleteFile(
"[BUCKET_ID]",
"[FILE_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.getFileDownload(
"[BUCKET_ID]",
"[FILE_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.getFilePreview(
"[BUCKET_ID]",
"[FILE_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.getFileView(
"[BUCKET_ID]",
"[FILE_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.getFile(
"[BUCKET_ID]",
"[FILE_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.listFiles(
"[BUCKET_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Storage
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Storage storage = new Storage(client);
storage.updateFile(
"[BUCKET_ID]",
"[FILE_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,51 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.createMembership(
"[TEAM_ID]",
"email@example.com",
listOf(),
"https://example.com",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.create(
"[TEAM_ID]",
"[NAME]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.deleteMembership(
"[TEAM_ID]",
"[MEMBERSHIP_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.delete(
"[TEAM_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.getMembership(
"[TEAM_ID]",
"[MEMBERSHIP_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.getMemberships(
"[TEAM_ID]",
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,48 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.get(
"[TEAM_ID]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,47 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.list(
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,50 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.updateMembershipRoles(
"[TEAM_ID]",
"[MEMBERSHIP_ID]",
listOf()
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,51 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.updateMembershipStatus(
"[TEAM_ID]",
"[MEMBERSHIP_ID]",
"[USER_ID]",
"[SECRET]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,49 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Teams
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Client client = new Client(getApplicationContext())
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2"); // Your project ID
Teams teams = new Teams(client);
teams.update(
"[TEAM_ID]",
"[NAME]"
new Continuation<Object>() {
@NotNull
@Override
public CoroutineContext getContext() {
return EmptyCoroutineContext.INSTANCE;
}
@Override
public void resumeWith(@NotNull Object o) {
String json = "";
try {
if (o instanceof Result.Failure) {
Result.Failure failure = (Result.Failure) o;
throw failure.exception;
} else {
Response response = (Response) o;
json = response.body().string();
}
} catch (Throwable th) {
Log.e("ERROR", th.toString());
}
}
}
);
}
}

View file

@ -0,0 +1,24 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val client = Client(applicationContext)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val account = Account(client)
GlobalScope.launch {
val response = account.createAnonymousSession()
val json = response.body?.string()
}
}
}

View file

@ -0,0 +1,24 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val client = Client(applicationContext)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val account = Account(client)
GlobalScope.launch {
val response = account.createJWT()
val json = response.body?.string()
}
}
}

View file

@ -0,0 +1,27 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val client = Client(applicationContext)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val account = Account(client)
GlobalScope.launch {
val response = account.createMagicURLSession(
userId = "[USER_ID]",
email = "email@example.com",
)
val json = response.body?.string()
}
}
}

View file

@ -0,0 +1,27 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val client = Client(applicationContext)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val account = Account(client)
GlobalScope.launch {
account.createOAuth2Session(
activity = this@MainActivity,
provider = "amazon",
)
}
}
}

View file

@ -0,0 +1,27 @@
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import io.appwrite.Client
import io.appwrite.services.Account
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val client = Client(applicationContext)
.setEndpoint("https://[HOSTNAME_OR_IP]/v1") // Your API Endpoint
.setProject("5df5acd0d48c2") // Your project ID
val account = Account(client)
GlobalScope.launch {
val response = account.createRecovery(
email = "email@example.com",
url = "https://example.com"
)
val json = response.body?.string()
}
}
}

Some files were not shown because too many files have changed in this diff Show more