Merge branch 'dev' into fix-dashboard-tooltip
This commit is contained in:
commit
1138752d65
3
.env
3
.env
|
@ -1,5 +1,6 @@
|
||||||
_APP_ENV=production
|
_APP_ENV=production
|
||||||
_APP_ENV=development
|
_APP_ENV=development
|
||||||
|
_APP_LOCALE=en
|
||||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||||
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
||||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io
|
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=security@appwrite.io
|
||||||
|
@ -16,7 +17,7 @@ _APP_DB_PORT=3306
|
||||||
_APP_DB_SCHEMA=appwrite
|
_APP_DB_SCHEMA=appwrite
|
||||||
_APP_DB_USER=user
|
_APP_DB_USER=user
|
||||||
_APP_DB_PASS=password
|
_APP_DB_PASS=password
|
||||||
_APP_STORAGE_ANTIVIRUS=enabled
|
_APP_STORAGE_ANTIVIRUS=disabled
|
||||||
_APP_STORAGE_ANTIVIRUS_HOST=clamav
|
_APP_STORAGE_ANTIVIRUS_HOST=clamav
|
||||||
_APP_STORAGE_ANTIVIRUS_PORT=3310
|
_APP_STORAGE_ANTIVIRUS_PORT=3310
|
||||||
_APP_INFLUXDB_HOST=influxdb
|
_APP_INFLUXDB_HOST=influxdb
|
||||||
|
|
11
CHANGES.md
11
CHANGES.md
|
@ -1,7 +1,18 @@
|
||||||
# Version 0.8.0 (Not Released Yet)
|
# Version 0.8.0 (Not Released Yet)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
- Anonymous login
|
- Anonymous login
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
- Fixed default value for HTTPS force option
|
||||||
|
|
||||||
|
## Breaking Changes (Read before upgrading!)
|
||||||
|
|
||||||
|
- Introdcues rate limits for:
|
||||||
|
- Team invite (10 requests in every 60 minutes per IP address)
|
||||||
|
|
||||||
# Version 0.7.2
|
# Version 0.7.2
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
|
@ -68,6 +68,7 @@ ARG VERSION=dev
|
||||||
|
|
||||||
ENV _APP_SERVER=swoole \
|
ENV _APP_SERVER=swoole \
|
||||||
_APP_ENV=production \
|
_APP_ENV=production \
|
||||||
|
_APP_LOCALE=en \
|
||||||
_APP_DOMAIN=localhost \
|
_APP_DOMAIN=localhost \
|
||||||
_APP_DOMAIN_TARGET=localhost \
|
_APP_DOMAIN_TARGET=localhost \
|
||||||
_APP_HOME=https://appwrite.io \
|
_APP_HOME=https://appwrite.io \
|
||||||
|
|
|
@ -70,6 +70,15 @@ $environments = [
|
||||||
'logo' => 'python.png',
|
'logo' => 'python.png',
|
||||||
'supports' => [System::X86, System::PPC, System::ARM],
|
'supports' => [System::X86, System::PPC, System::ARM],
|
||||||
],
|
],
|
||||||
|
'python-3.9' => [
|
||||||
|
'name' => 'Python',
|
||||||
|
'version' => '3.9',
|
||||||
|
'base' => 'python:3.9-alpine',
|
||||||
|
'image' => 'appwrite/env-python-3.9:1.0.0',
|
||||||
|
'build' => '/usr/src/code/docker/environments/python-3.9',
|
||||||
|
'logo' => 'python.png',
|
||||||
|
'supports' => [System::X86, System::PPC, System::ARM],
|
||||||
|
],
|
||||||
'deno-1.2' => [
|
'deno-1.2' => [
|
||||||
'name' => 'Deno',
|
'name' => 'Deno',
|
||||||
'version' => '1.2',
|
'version' => '1.2',
|
||||||
|
@ -97,6 +106,15 @@ $environments = [
|
||||||
'logo' => 'deno.png',
|
'logo' => 'deno.png',
|
||||||
'supports' => [System::X86, System::PPC, System::ARM],
|
'supports' => [System::X86, System::PPC, System::ARM],
|
||||||
],
|
],
|
||||||
|
'deno-1.8' => [
|
||||||
|
'name' => 'Deno',
|
||||||
|
'version' => '1.8',
|
||||||
|
'base' => 'hayd/deno:alpine-1.8.2',
|
||||||
|
'image' => 'appwrite/env-deno-1.8:1.0.0',
|
||||||
|
'build' => '/usr/src/code/docker/environments/deno-1.8',
|
||||||
|
'logo' => 'deno.png',
|
||||||
|
'supports' => [System::X86, System::PPC, System::ARM],
|
||||||
|
],
|
||||||
'dart-2.10' => [
|
'dart-2.10' => [
|
||||||
'name' => 'Dart',
|
'name' => 'Dart',
|
||||||
'version' => '2.10',
|
'version' => '2.10',
|
||||||
|
@ -106,6 +124,15 @@ $environments = [
|
||||||
'logo' => 'dart.png',
|
'logo' => 'dart.png',
|
||||||
'supports' => [System::X86],
|
'supports' => [System::X86],
|
||||||
],
|
],
|
||||||
|
'dart-2.12' => [
|
||||||
|
'name' => 'Dart',
|
||||||
|
'version' => '2.12',
|
||||||
|
'base' => 'google/dart:2.12',
|
||||||
|
'image' => 'appwrite/env-dart-2.12:1.0.0',
|
||||||
|
'build' => '/usr/src/code/docker/environments/dart-2.12',
|
||||||
|
'logo' => 'dart.png',
|
||||||
|
'supports' => [System::X86],
|
||||||
|
],
|
||||||
'dotnet-3.1' => [
|
'dotnet-3.1' => [
|
||||||
'name' => '.NET',
|
'name' => '.NET',
|
||||||
'version' => '3.1',
|
'version' => '3.1',
|
||||||
|
|
|
@ -84,17 +84,17 @@ return [
|
||||||
],
|
],
|
||||||
'database.documents.create' => [
|
'database.documents.create' => [
|
||||||
'description' => 'This event triggers when a database document is created.',
|
'description' => 'This event triggers when a database document is created.',
|
||||||
'model' => Response::MODEL_ANY,
|
'model' => Response::MODEL_DOCUMENT,
|
||||||
'note' => '',
|
'note' => '',
|
||||||
],
|
],
|
||||||
'database.documents.update' => [
|
'database.documents.update' => [
|
||||||
'description' => 'This event triggers when a database document is updated.',
|
'description' => 'This event triggers when a database document is updated.',
|
||||||
'model' => Response::MODEL_ANY,
|
'model' => Response::MODEL_DOCUMENT,
|
||||||
'note' => '',
|
'note' => '',
|
||||||
],
|
],
|
||||||
'database.documents.delete' => [
|
'database.documents.delete' => [
|
||||||
'description' => 'This event triggers when a database document is deleted.',
|
'description' => 'This event triggers when a database document is deleted.',
|
||||||
'model' => Response::MODEL_ANY,
|
'model' => Response::MODEL_DOCUMENT,
|
||||||
'note' => '',
|
'note' => '',
|
||||||
],
|
],
|
||||||
'storage.files.create' => [
|
'storage.files.create' => [
|
||||||
|
|
|
@ -15,6 +15,14 @@ return [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => '_APP_LOCALE',
|
||||||
|
'description' => 'Set your Appwrite\'s locale. By default, the locale is set to \'en\'.',
|
||||||
|
'introduction' => '',
|
||||||
|
'default' => 'en',
|
||||||
|
'required' => false,
|
||||||
|
'question' => '',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'name' => '_APP_OPTIONS_ABUSE',
|
'name' => '_APP_OPTIONS_ABUSE',
|
||||||
'description' => 'Allows you to disable abuse checks and API rate limiting. By default, set to \'enabled\'. To cancel the abuse checking, set to \'disabled\'. It is not recommended to disable this check-in a production environment.',
|
'description' => 'Allows you to disable abuse checks and API rate limiting. By default, set to \'enabled\'. To cancel the abuse checking, set to \'disabled\'. It is not recommended to disable this check-in a production environment.',
|
||||||
|
@ -27,7 +35,7 @@ return [
|
||||||
'name' => '_APP_OPTIONS_FORCE_HTTPS',
|
'name' => '_APP_OPTIONS_FORCE_HTTPS',
|
||||||
'description' => 'Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'disabled\'. To enable, set to \'enabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
'description' => 'Allows you to force HTTPS connection to your API. This feature redirects any HTTP call to HTTPS and adds the \'Strict-Transport-Security\' header to all HTTP responses. By default, set to \'disabled\'. To enable, set to \'enabled\'. This feature will work only when your ports are set to default 80 and 443.',
|
||||||
'introduction' => '',
|
'introduction' => '',
|
||||||
'default' => 'enabled',
|
'default' => 'disabled',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
@ -309,9 +317,9 @@ return [
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => '_APP_STORAGE_ANTIVIRUS',
|
'name' => '_APP_STORAGE_ANTIVIRUS',
|
||||||
'description' => 'This variable allows you to disable the internal anti-virus scans. This value is set to \'enabled\' by default, to cancel the scans set the value to \'disabled\'. When disabled, it\'s recommended to turn off the ClamAV container for better resource usage.',
|
'description' => 'This variable allows you to disable the internal anti-virus scans. This value is set to \'disabled\' by default, to enable the scans set the value to \'enabled\'. Before enabling, you must add the ClamAV service and depend on it on main Appwrite service.',
|
||||||
'introduction' => '',
|
'introduction' => '',
|
||||||
'default' => 'enabled',
|
'default' => 'disabled',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
@ -381,7 +389,7 @@ return [
|
||||||
'name' => '_APP_FUNCTIONS_ENVS',
|
'name' => '_APP_FUNCTIONS_ENVS',
|
||||||
'description' => 'This option allows you to limit the available environments for cloud functions. This option is very useful for low-cost servers to safe disk space.\n\nTo enable/activate this option, pass a list of allowed environments separated by a comma.\n\nCurrently, supported environments are: ' . \implode(', ', \array_keys(Config::getParam('providers'))),
|
'description' => 'This option allows you to limit the available environments for cloud functions. This option is very useful for low-cost servers to safe disk space.\n\nTo enable/activate this option, pass a list of allowed environments separated by a comma.\n\nCurrently, supported environments are: ' . \implode(', ', \array_keys(Config::getParam('providers'))),
|
||||||
'introduction' => '0.7.0',
|
'introduction' => '0.7.0',
|
||||||
'default' => 'node-14.5,deno-1.6,php-7.4,python-3.8,ruby-3.0,dotnet-5.0',
|
'default' => 'node-14.5,deno-1.8,php-7.4,python-3.9,ruby-3.0,dotnet-5.0',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'question' => '',
|
'question' => '',
|
||||||
],
|
],
|
||||||
|
|
|
@ -6,10 +6,10 @@ use Utopia\Exception;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Validator\Assoc;
|
use Utopia\Validator\Assoc;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Validator\Host;
|
use Appwrite\Network\Validator\Host;
|
||||||
use Utopia\Validator\URL;
|
use Appwrite\Network\Validator\URL;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
|
|
|
@ -14,7 +14,7 @@ use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\HexColor;
|
use Utopia\Validator\HexColor;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\URL;
|
use Appwrite\Network\Validator\URL;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
|
||||||
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
|
$avatarCallback = function ($type, $code, $width, $height, $quality, $response) {
|
||||||
|
|
|
@ -294,7 +294,7 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||||
->label('sdk.description', '/docs/references/database/create-document.md')
|
->label('sdk.description', '/docs/references/database/create-document.md')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_ANY)
|
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||||
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
|
||||||
|
@ -401,7 +401,7 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||||
|
|
||||||
$response
|
$response
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||||
->dynamic($data, Response::MODEL_ANY)
|
->dynamic($data, Response::MODEL_DOCUMENT)
|
||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->label('sdk.description', '/docs/references/database/get-document.md')
|
->label('sdk.description', '/docs/references/database/get-document.md')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_ANY)
|
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||||
->param('documentId', null, new UID(), 'Document unique ID.')
|
->param('documentId', null, new UID(), 'Document unique ID.')
|
||||||
->inject('response')
|
->inject('response')
|
||||||
|
@ -494,7 +494,7 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
throw new Exception('No document found', 404);
|
throw new Exception('No document found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->dynamic($document, Response::MODEL_ANY);
|
$response->dynamic($document, Response::MODEL_DOCUMENT);
|
||||||
});
|
});
|
||||||
|
|
||||||
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
|
@ -508,7 +508,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->label('sdk.description', '/docs/references/database/update-document.md')
|
->label('sdk.description', '/docs/references/database/update-document.md')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_ANY)
|
->label('sdk.response.model', Response::MODEL_DOCUMENT)
|
||||||
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
|
||||||
->param('documentId', null, new UID(), 'Document unique ID.')
|
->param('documentId', null, new UID(), 'Document unique ID.')
|
||||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||||
|
@ -566,7 +566,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->setParam('data', $data->getArrayCopy())
|
->setParam('data', $data->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->dynamic($data, Response::MODEL_ANY);
|
$response->dynamic($data, Response::MODEL_DOCUMENT);
|
||||||
});
|
});
|
||||||
|
|
||||||
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
|
@ -614,7 +614,7 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
}
|
}
|
||||||
|
|
||||||
$events
|
$events
|
||||||
->setParam('payload', $response->output($document, Response::MODEL_ANY))
|
->setParam('payload', $response->output($document, Response::MODEL_DOCUMENT))
|
||||||
;
|
;
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
|
|
|
@ -6,7 +6,7 @@ use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Validator\URL;
|
use Appwrite\Network\Validator\URL;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Domains\Domain;
|
use Utopia\Domains\Domain;
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Exception;
|
use Utopia\Exception;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
use Utopia\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\Host;
|
use Appwrite\Network\Validator\Host;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
|
@ -261,6 +261,7 @@ App::post('/v1/teams/:teamId/memberships')
|
||||||
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
|
||||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||||
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
||||||
|
->label('abuse-limit', 10)
|
||||||
->param('teamId', '', new UID(), 'Team unique ID.')
|
->param('teamId', '', new UID(), 'Team unique ID.')
|
||||||
->param('email', '', new Email(), 'New team member email.')
|
->param('email', '', new Email(), 'New team member email.')
|
||||||
->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use Utopia\App;
|
||||||
use Utopia\Exception;
|
use Utopia\Exception;
|
||||||
use Utopia\Validator\Assoc;
|
use Utopia\Validator\Assoc;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Validator\Email;
|
use Appwrite\Network\Validator\Email;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
|
|
|
@ -314,7 +314,7 @@ App::setResource('layout', function($locale) {
|
||||||
}, ['locale']);
|
}, ['locale']);
|
||||||
|
|
||||||
App::setResource('locale', function() {
|
App::setResource('locale', function() {
|
||||||
return new Locale('en');
|
return new Locale(App::getEnv('_APP_LOCALE', 'en'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Queues
|
// Queues
|
||||||
|
|
|
@ -520,7 +520,7 @@ $maxCells = 10;
|
||||||
|
|
||||||
<div data-ls-loop="project-collections.collections" data-ls-as="project" data-ls-key="$index2" class="tiles cell-3 margin-bottom-negative">
|
<div data-ls-loop="project-collections.collections" data-ls-as="project" data-ls-key="$index2" class="tiles cell-3 margin-bottom-negative">
|
||||||
<div class="margin-bottom" data-ls-if="{{project.$id}} != {{router.params.id}}">
|
<div class="margin-bottom" data-ls-if="{{project.$id}} != {{router.params.id}}">
|
||||||
<input type="radio" name="list" data-ls-attrs="value={{project.$id}},id={{project.$id}}" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
|
<input type="radio" data-ls-attrs="value={{project.$id}},id=[{{rule.$id}}].{{project.$id}},name=[{{rule.$id}}].list" data-ls-bind="{{rule.list|firstElement}}" data-cast-to="array" required />
|
||||||
<label data-ls-attrs="for={{project.$id}}"data-ls-bind="{{project.name}}"></label>
|
<label data-ls-attrs="for={{project.$id}}"data-ls-bind="{{project.name}}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -52,10 +52,11 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mariadb
|
||||||
- redis
|
- redis
|
||||||
- clamav
|
# - clamav
|
||||||
- influxdb
|
- influxdb
|
||||||
environment:
|
environment:
|
||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
|
- _APP_LOCALE
|
||||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||||
- _APP_CONSOLE_WHITELIST_IPS
|
- _APP_CONSOLE_WHITELIST_IPS
|
||||||
- _APP_SYSTEM_EMAIL_NAME
|
- _APP_SYSTEM_EMAIL_NAME
|
||||||
|
@ -351,14 +352,14 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-redis:/data:rw
|
- appwrite-redis:/data:rw
|
||||||
|
|
||||||
clamav:
|
# clamav:
|
||||||
image: appwrite/clamav:1.2.0
|
# image: appwrite/clamav:1.2.0
|
||||||
container_name: appwrite-clamav
|
# container_name: appwrite-clamav
|
||||||
restart: unless-stopped
|
# restart: unless-stopped
|
||||||
networks:
|
# networks:
|
||||||
- appwrite
|
# - appwrite
|
||||||
volumes:
|
# volumes:
|
||||||
- appwrite-uploads:/storage/uploads
|
# - appwrite-uploads:/storage/uploads
|
||||||
|
|
||||||
influxdb:
|
influxdb:
|
||||||
image: influxdb:1.8-alpine
|
image: influxdb:1.8-alpine
|
||||||
|
|
|
@ -71,10 +71,11 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mariadb
|
||||||
- redis
|
- redis
|
||||||
- clamav
|
# - clamav
|
||||||
- influxdb
|
- influxdb
|
||||||
environment:
|
environment:
|
||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
|
- _APP_LOCALE
|
||||||
- _APP_SYSTEM_EMAIL_NAME
|
- _APP_SYSTEM_EMAIL_NAME
|
||||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
|
@ -413,13 +414,13 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-redis:/data:rw
|
- appwrite-redis:/data:rw
|
||||||
|
|
||||||
clamav:
|
# clamav:
|
||||||
image: appwrite/clamav:1.2.0
|
# image: appwrite/clamav:1.2.0
|
||||||
container_name: appwrite-clamav
|
# container_name: appwrite-clamav
|
||||||
networks:
|
# networks:
|
||||||
- appwrite
|
# - appwrite
|
||||||
volumes:
|
# volumes:
|
||||||
- appwrite-uploads:/storage/uploads
|
# - appwrite-uploads:/storage/uploads
|
||||||
|
|
||||||
influxdb:
|
influxdb:
|
||||||
image: influxdb:1.8-alpine
|
image: influxdb:1.8-alpine
|
||||||
|
|
|
@ -9,6 +9,9 @@ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||||
echo 'Deno 1.6...'
|
echo 'Deno 1.6...'
|
||||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-deno-1.6:1.0.0 ./docker/environments/deno-1.6/ --push
|
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-deno-1.6:1.0.0 ./docker/environments/deno-1.6/ --push
|
||||||
|
|
||||||
|
echo 'Deno 1.8...'
|
||||||
|
docker buildx build --platform linux/amd64,linux/386 -t appwrite/env-deno-1.8:1.0.0 ./docker/environments/deno-1.8/ --push
|
||||||
|
|
||||||
echo 'Node 14.5...'
|
echo 'Node 14.5...'
|
||||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le -t appwrite/env-node-14.5:1.0.0 ./docker/environments/node-14.5/ --push
|
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le -t appwrite/env-node-14.5:1.0.0 ./docker/environments/node-14.5/ --push
|
||||||
|
|
||||||
|
@ -24,6 +27,9 @@ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64
|
||||||
echo 'Python 3.8...'
|
echo 'Python 3.8...'
|
||||||
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-python-3.8:1.0.0 ./docker/environments/python-3.8/ --push
|
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-python-3.8:1.0.0 ./docker/environments/python-3.8/ --push
|
||||||
|
|
||||||
|
echo 'Python 3.9...'
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-python-3.9:1.0.0 ./docker/environments/python-3.9/ --push
|
||||||
|
|
||||||
echo 'Ruby 2.7...'
|
echo 'Ruby 2.7...'
|
||||||
docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-ruby-2.7:1.0.2 ./docker/environments/ruby-2.7/ --push
|
docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -t appwrite/env-ruby-2.7:1.0.2 ./docker/environments/ruby-2.7/ --push
|
||||||
|
|
||||||
|
@ -33,6 +39,9 @@ docker buildx build --platform linux/amd64,linux/arm64,linux/386,linux/ppc64le -
|
||||||
echo 'Dart 2.10...'
|
echo 'Dart 2.10...'
|
||||||
docker buildx build --platform linux/amd64 -t appwrite/env-dart-2.10:1.0.0 ./docker/environments/dart-2.10/ --push
|
docker buildx build --platform linux/amd64 -t appwrite/env-dart-2.10:1.0.0 ./docker/environments/dart-2.10/ --push
|
||||||
|
|
||||||
|
echo 'Dart 2.12...'
|
||||||
|
docker buildx build --platform linux/amd64 -t appwrite/env-dart-2.12:1.0.0 ./docker/environments/dart-2.12/ --push
|
||||||
|
|
||||||
echo '.NET 3.1...'
|
echo '.NET 3.1...'
|
||||||
docker buildx build --platform linux/amd64,linux/arm64 -t appwrite/env-dotnet-3.1:1.0.0 ./docker/environments/dotnet-3.1/ --push
|
docker buildx build --platform linux/amd64,linux/arm64 -t appwrite/env-dotnet-3.1:1.0.0 ./docker/environments/dotnet-3.1/ --push
|
||||||
|
|
||||||
|
|
9
docker/environments/dart-2.12/Dockerfile
Normal file
9
docker/environments/dart-2.12/Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FROM google/dart:2.12
|
||||||
|
|
||||||
|
LABEL maintainer="team@appwrite.io"
|
||||||
|
|
||||||
|
RUN apt-get update -y && apt-get install -y tar
|
||||||
|
|
||||||
|
WORKDIR /usr/local/src/
|
||||||
|
|
||||||
|
ENV PUB_CACHE=/usr/local/src/.appwrite
|
11
docker/environments/deno-1.8/Dockerfile
Normal file
11
docker/environments/deno-1.8/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM hayd/deno:alpine-1.8.3
|
||||||
|
|
||||||
|
LABEL maintainer="team@appwrite.io"
|
||||||
|
|
||||||
|
RUN apk add tar
|
||||||
|
|
||||||
|
RUN mkdir /usr/local/src
|
||||||
|
|
||||||
|
WORKDIR /usr/local/src/
|
||||||
|
|
||||||
|
ENV DENO_DIR=/usr/local/src/.appwrite
|
11
docker/environments/python-3.9/Dockerfile
Normal file
11
docker/environments/python-3.9/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM python:3.9-alpine
|
||||||
|
|
||||||
|
LABEL maintainer="team@appwrite.io"
|
||||||
|
|
||||||
|
RUN apk add tar
|
||||||
|
|
||||||
|
RUN mkdir /usr/local/src
|
||||||
|
|
||||||
|
WORKDIR /usr/local/src/
|
||||||
|
|
||||||
|
ENV PYTHONPATH "${PYTHONPATH}:/usr/local/src/.appwrite"
|
|
@ -11,6 +11,7 @@ void main() async {
|
||||||
.setEndpoint('http://[HOSTNAME_OR_IP]/v1') // Make sure your endpoint is accessible
|
.setEndpoint('http://[HOSTNAME_OR_IP]/v1') // Make sure your endpoint is accessible
|
||||||
.setProject('5ff3379a01d25') // Your project ID
|
.setProject('5ff3379a01d25') // Your project ID
|
||||||
.setKey('cd868c7af8bdc893b4...93b7535db89')
|
.setKey('cd868c7af8bdc893b4...93b7535db89')
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
|
|
||||||
Users users = Users(client);
|
Users users = Users(client);
|
||||||
|
|
||||||
|
@ -23,6 +24,21 @@ void main() async {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error handling
|
||||||
|
The Appwrite Dart SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Users users = Users(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await users.create(email: ‘email@example.com’,password: ‘password’, name: ‘name’);
|
||||||
|
print(response.data);
|
||||||
|
} on AppwriteException catch(e) {
|
||||||
|
//show message to user or do other operation based on error as required
|
||||||
|
print(e.message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -10,6 +10,7 @@ client
|
||||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
.setProject('5df5acd0d48c2') // Your project ID
|
.setProject('5df5acd0d48c2') // Your project ID
|
||||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -41,6 +42,7 @@ client
|
||||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
.setProject('5df5acd0d48c2') // Your project ID
|
.setProject('5df5acd0d48c2') // Your project ID
|
||||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
let promise = users.create('email@example.com', 'password');
|
let promise = users.create('email@example.com', 'password');
|
||||||
|
@ -52,6 +54,19 @@ promise.then(function (response) {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite Deno SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
let users = new sdk.Users(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await users.create('email@example.com', 'password');
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -14,6 +14,7 @@ static async Task Main(string[] args)
|
||||||
.setEndpoint('http://[HOSTNAME_OR_IP]/v1') // Make sure your endpoint is accessible
|
.setEndpoint('http://[HOSTNAME_OR_IP]/v1') // Make sure your endpoint is accessible
|
||||||
.setProject('5ff3379a01d25') // Your project ID
|
.setProject('5ff3379a01d25') // Your project ID
|
||||||
.setKey('cd868c7af8bdc893b4...93b7535db89')
|
.setKey('cd868c7af8bdc893b4...93b7535db89')
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
var users = Users(client);
|
var users = Users(client);
|
||||||
|
@ -28,6 +29,21 @@ static async Task Main(string[] args)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite .NET SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var users = Users(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var request = await users.create('email@example.com', 'password', 'name');
|
||||||
|
var response = await request.Content.ReadAsStringAsync();
|
||||||
|
Console.WriteLine(response);
|
||||||
|
} catch (AppwriteException e) {
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -58,7 +58,7 @@ Client client = Client();
|
||||||
client
|
client
|
||||||
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
|
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
|
||||||
.setProject('5e8cf4f46b5e8') // Your project ID
|
.setProject('5e8cf4f46b5e8') // Your project ID
|
||||||
.setSelfSigned() // Remove in production
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ Client client = Client();
|
||||||
client
|
client
|
||||||
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
|
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
|
||||||
.setProject('5e8cf4f46b5e8') // Your project ID
|
.setProject('5e8cf4f46b5e8') // Your project ID
|
||||||
.setSelfSigned() // Remove in production
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,6 +106,21 @@ Response user = await account
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite Flutter SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Users users = Users(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await users.create(email: ‘email@example.com’,password: ‘password’, name: ‘name’);
|
||||||
|
print(response.data);
|
||||||
|
} on AppwriteException catch(e) {
|
||||||
|
//show message to user or do other operation based on error as required
|
||||||
|
print(e.message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-flutter)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-flutter)
|
||||||
|
|
|
@ -12,6 +12,7 @@ client
|
||||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
.setProject('5df5acd0d48c2') // Your project ID
|
.setProject('5df5acd0d48c2') // Your project ID
|
||||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ client
|
||||||
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
.setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
.setProject('5df5acd0d48c2') // Your project ID
|
.setProject('5df5acd0d48c2') // Your project ID
|
||||||
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
let users = new sdk.Users(client);
|
let users = new sdk.Users(client);
|
||||||
|
@ -52,6 +54,19 @@ promise.then(function (response) {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite Node SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```js
|
||||||
|
let users = new sdk.Users(client);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await users.create('email@example.com', 'password');
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e.message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -10,6 +10,7 @@ $client
|
||||||
->setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
->setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
->setProject('5df5acd0d48c2') // Your project ID
|
->setProject('5df5acd0d48c2') // Your project ID
|
||||||
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
->setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ $client
|
||||||
->setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
->setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint
|
||||||
->setProject('5df5acd0d48c2') // Your project ID
|
->setProject('5df5acd0d48c2') // Your project ID
|
||||||
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
->setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
|
||||||
|
->setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
$users = new Users($client);
|
$users = new Users($client);
|
||||||
|
@ -40,6 +42,19 @@ $users = new Users($client);
|
||||||
$result = $users->create('email@example.com', 'password');
|
$result = $users->create('email@example.com', 'password');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite PHP SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```php
|
||||||
|
$users = new Users($client);
|
||||||
|
try {
|
||||||
|
$result = $users->create('email@example.com', 'password');
|
||||||
|
} catch(AppwriteException $error) {
|
||||||
|
echo $error->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -13,6 +13,7 @@ client = Client()
|
||||||
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
|
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
|
||||||
.set_project('5df5acd0d48c2') # Your project ID
|
.set_project('5df5acd0d48c2') # Your project ID
|
||||||
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
|
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
|
||||||
|
.set_self_signed() # Use only on dev mode with a self-signed SSL cert
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ client = Client()
|
||||||
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
|
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
|
||||||
.set_project('5df5acd0d48c2') # Your project ID
|
.set_project('5df5acd0d48c2') # Your project ID
|
||||||
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
|
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
|
||||||
|
.set_self_signed() # Use only on dev mode with a self-signed SSL cert
|
||||||
)
|
)
|
||||||
|
|
||||||
users = Users(client)
|
users = Users(client)
|
||||||
|
@ -43,6 +45,17 @@ users = Users(client)
|
||||||
result = users.create('email@example.com', 'password')
|
result = users.create('email@example.com', 'password')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite Python SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```python
|
||||||
|
users = Users(client)
|
||||||
|
try:
|
||||||
|
result = users.create('email@example.com', 'password')
|
||||||
|
except AppwriteException as e:
|
||||||
|
print(e.message)
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
|
@ -12,6 +12,7 @@ client
|
||||||
.set_endpoint(ENV["APPWRITE_ENDPOINT"]) # Your API Endpoint
|
.set_endpoint(ENV["APPWRITE_ENDPOINT"]) # Your API Endpoint
|
||||||
.set_project(ENV["APPWRITE_PROJECT"]) # Your project ID
|
.set_project(ENV["APPWRITE_PROJECT"]) # Your project ID
|
||||||
.set_key(ENV["APPWRITE_SECRET"]) # Your secret API key
|
.set_key(ENV["APPWRITE_SECRET"]) # Your secret API key
|
||||||
|
.setSelfSigned() # Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ client
|
||||||
.set_endpoint(ENV["APPWRITE_ENDPOINT"]) # Your API Endpoint
|
.set_endpoint(ENV["APPWRITE_ENDPOINT"]) # Your API Endpoint
|
||||||
.set_project(ENV["APPWRITE_PROJECT"]) # Your project ID
|
.set_project(ENV["APPWRITE_PROJECT"]) # Your project ID
|
||||||
.set_key(ENV["APPWRITE_SECRET"]) # Your secret API key
|
.set_key(ENV["APPWRITE_SECRET"]) # Your secret API key
|
||||||
|
.setSelfSigned() # Use only on dev mode with a self-signed SSL cert
|
||||||
;
|
;
|
||||||
|
|
||||||
users = Appwrite::Users.new(client);
|
users = Appwrite::Users.new(client);
|
||||||
|
@ -41,6 +43,19 @@ users = Appwrite::Users.new(client);
|
||||||
result = users.create(email: 'email@example.com', password: 'password');
|
result = users.create(email: 'email@example.com', password: 'password');
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
The Appwrite Ruby SDK raises `Appwrite::Exception` object with `message`, `code` and `response` properties. You can handle any errors by catching `Appwrite::Exception` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
users = Appwrite::Users.new(client);
|
||||||
|
|
||||||
|
begin
|
||||||
|
result = users.create(email: 'email@example.com', password: 'password');
|
||||||
|
rescue Appwrite::Exception => error
|
||||||
|
puts error.message
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
### Learn more
|
### Learn more
|
||||||
You can use followng resources to learn more and get help
|
You can use followng resources to learn more and get help
|
||||||
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-server)
|
||||||
|
|
63
docs/sdks/web/GETTING_STARTED.md
Normal file
63
docs/sdks/web/GETTING_STARTED.md
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Add your Web Platform
|
||||||
|
For you to init your SDK and interact with Appwrite services you need to add a web platform to your project. To add a new platform, go to your Appwrite console, choose the project you created in the step before and click the 'Add Platform' button.
|
||||||
|
|
||||||
|
From the options, choose to add a **Web** platform and add your client app hostname. By adding your hostname to your project platform you are allowing cross-domain communication between your project and the Appwrite API.
|
||||||
|
|
||||||
|
### Init your SDK
|
||||||
|
Initialize your SDK code with your project ID which can be found in your project settings page.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Init your Web SDK
|
||||||
|
const appwrite = new Appwrite();
|
||||||
|
|
||||||
|
appwrite
|
||||||
|
.setEndpoint('http://localhost/v1') // Your Appwrite Endpoint
|
||||||
|
.setProject('455x34dfkj') // Your project ID
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
|
;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Make Your First Request
|
||||||
|
Once your SDK object is set, access any of the Appwrite services and choose any request to send. Full documentation for any service method you would like to use can be found in your SDK documentation or in the API References section.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Register User
|
||||||
|
appwrite
|
||||||
|
.account.create('me@example.com', 'password', 'Jane Doe')
|
||||||
|
.then(function (response) {
|
||||||
|
console.log(response);
|
||||||
|
}, function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Example
|
||||||
|
```js
|
||||||
|
// Init your Web SDK
|
||||||
|
const appwrite = new Appwrite();
|
||||||
|
|
||||||
|
appwrite
|
||||||
|
.setEndpoint('http://localhost/v1') // Your Appwrite Endpoint
|
||||||
|
.setProject('455x34dfkj')
|
||||||
|
.setSelfSigned() // Use only on dev mode with a self-signed SSL cert
|
||||||
|
;
|
||||||
|
|
||||||
|
// Register User
|
||||||
|
appwrite
|
||||||
|
.account.create('me@example.com', 'password', 'Jane Doe')
|
||||||
|
.then(function (response) {
|
||||||
|
console.log(response);
|
||||||
|
}, function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Learn more
|
||||||
|
You can use followng resources to learn more and get help
|
||||||
|
- 🚀 [Getting Started Tutorial](https://appwrite.io/docs/getting-started-for-flutter)
|
||||||
|
- 📜 [Appwrite Docs](https://appwrite.io/docs)
|
||||||
|
- 💬 [Discord Community](https://appwrite.io/discord)
|
||||||
|
- 🚂 [Appwrite Flutter Playground](https://github.com/appwrite/playground-for-flutter)
|
|
@ -1,45 +0,0 @@
|
||||||
# Running in Production
|
|
||||||
|
|
||||||
This tutorial will cover some basic concepts and best practices for running a production Appwrite server. This tutorial assumes you have some basic knowledge of Docker and Docker Compose command-line tools.
|
|
||||||
|
|
||||||
## Error Reporting
|
|
||||||
|
|
||||||
By default, Appwrite installation comes with error debugging turned on, We do this to help new users solve issues and report problems while still in development mode.
|
|
||||||
|
|
||||||
In production, it is highly recommended to turn error reporting off. To do so, you have to change the Appwrite container environment variable **_APP_ENV** value from **development** to **production**.
|
|
||||||
|
|
||||||
## Enable Encryption
|
|
||||||
|
|
||||||
By default, the Appwrite setup doesn’t come with a uniquely generated encryption key. This key is used to store your files and sensitive data like webhook passwords or API keys in a safe way. To take advantage of this feature, you must generate a unique key and set it as the value of the **_APP_OPENSSL_KEY_V1** environment variable.
|
|
||||||
|
|
||||||
Make sure to keep this key in a safe place and never make it publicly accessible. There are many [online resources]([https://www.freecodecamp.org/news/how-to-securely-store-api-keys-4ff3ea19ebda/](https://www.freecodecamp.org/news/how-to-securely-store-api-keys-4ff3ea19ebda/)) with methods of keeping your secret keys safe in your servers.
|
|
||||||
|
|
||||||
## Limit Access to your Console
|
|
||||||
|
|
||||||
By default, anyone can signup for your Appwrite server, create projects, and use your computing power. While this is great for testing around or running your Appwrite service in a network isolated environment, it is highly not recommended for public production use.
|
|
||||||
|
|
||||||
We are providing three different methods to limit access to your Appwrite console. You can either set a list of [IPs]([https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_ips](https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_ips)), [email address]([https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_emails](https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_emails)) or [email domains]([https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_domains](https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#_app_console_whitelist_domains)) which users are allowed to signup from. You can choose one or multiple restriction methods to apply.
|
|
||||||
|
|
||||||
## Scaling
|
|
||||||
|
|
||||||
Appwrite was built with scalability in mind. Appwrite can potentially scale horizontally infinitely with no known limitations.
|
|
||||||
|
|
||||||
Appwrite uses a few containers to run, where each container has its job. Most of the Appwrite containers are stateless, and in order to scale them, all you need is run multiple instances of them and setup a load balancer in front of them.
|
|
||||||
|
|
||||||
If you decide to set up a load balancer for a specific container, make sure that the containers that are trying to communicate with it are accessing it through a load balancer and not directly. All connections between Appwrite different containers are set using Docker environment variables.
|
|
||||||
|
|
||||||
There are three Appwrite containers that do keep their state are the MariaDB, Redis, and InfluxDB containers that are used for storing data, cache, and stats (in this order). To scale them out, all you need to do is set up a standard cluster (same as you would with any other app using these technologies) according to your needs and performance.
|
|
||||||
|
|
||||||
## Sending Emails
|
|
||||||
|
|
||||||
Sending emails is hard. There are a lot of SPAM rules and configurations to master in order to set a functional SMTP server. The SMTP server that comes packaged with Appwrite is great for development but needs some work done to function well against SPAM filters. You can find some guidelines in this [tutorial]([https://www.digitalocean.com/community/tutorials/how-to-use-an-spf-record-to-prevent-spoofing-improve-e-mail-reliability](https://www.digitalocean.com/community/tutorials/how-to-use-an-spf-record-to-prevent-spoofing-improve-e-mail-reliability)).
|
|
||||||
|
|
||||||
Another **easier option** is to use an ‘SMTP as a service’ product like [Sendgrid]([https://sendgrid.com/](https://sendgrid.com/)) or [Mailgun]([https://www.mailgun.com/](https://www.mailgun.com/)). You can change Appwrite SMTP settings and credentials to any 3rd party provider you like who support SMTP integration using our [Docker environment variables]([https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#smtp](https://github.com/appwrite/appwrite/blob/master/docs/tutorials/environment-variables.md#smtp)). Most services offer a decent free tier to get started with.
|
|
||||||
|
|
||||||
## Backups
|
|
||||||
|
|
||||||
Backups are highly recommended for any production environment. Currently, there is not built-in script we provide to do this automatically. To be able to backup your Appwrite server data, stats, and files you will need to do the following.
|
|
||||||
|
|
||||||
1. Create a script to backups and restore your MariaDB Appwrite schema. Note that trying to backup MariaDB using a docker volume backup can result in a corrupted copy of your data. It is recommended to use MariaDB or MySQL built-in tools for this.
|
|
||||||
2. Create a script to backups and restore your InfluxDB stats. If you don’t care much about your server stats, you can skip this.
|
|
||||||
3. Create a script to backup Appwrite storage volume. There are many [online resources]([https://blog.ssdnodes.com/blog/docker-backup-volumes/](https://blog.ssdnodes.com/blog/docker-backup-volumes/)) explaining different ways to backup a docker volume. When running on multiple servers, it is very recommended to use an attachable storage point. Some cloud providers offer integrated backups to such attachable mount like GCP, AWS, DigitalOcean, and the list continues.
|
|
9665
package-lock.json
generated
9665
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
@ -3,14 +3,19 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"repository": "public",
|
"repository": "public",
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run gulp:less && npm run gulp:import && npm run gulp:build",
|
||||||
|
"gulp:less": "gulp less",
|
||||||
|
"gulp:import": "gulp import",
|
||||||
|
"gulp:build": "gulp build"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"yargs-parser": ">=20.2.0",
|
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-clean-css": "^4.3.0",
|
"gulp-clean-css": "^4.3.0",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-jsmin": "^0.1.5",
|
"gulp-jsmin": "^0.1.5",
|
||||||
"gulp-less": "^4.0.1",
|
"gulp-less": "^4.0.1",
|
||||||
"jest": "^26.4.2",
|
"ls-service-form2json": "^1.0.0",
|
||||||
"ls-service-form2json": "^1.0.0"
|
"yargs-parser": "^20.2.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
public/dist/scripts/app-all.js
vendored
6
public/dist/scripts/app-all.js
vendored
|
@ -2211,9 +2211,11 @@ match=text.match(new RegExp(regex,'gi'))
|
||||||
if(!match){return fail}
|
if(!match){return fail}
|
||||||
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
||||||
return(date.getTime()/1000)}
|
return(date.getTime()/1000)}
|
||||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,to));return value;}
|
||||||
|
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||||
return value;}
|
return value;}
|
||||||
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if(name.startsWith('[')){let splitName=name.split('.');if(splitName.length>1&&splitName[0].endsWith(']')){name=splitName[splitName.length-1];}}
|
||||||
|
if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
||||||
ref=json[name];}
|
ref=json[name];}
|
||||||
else{if(!Array.isArray(json[name])){json[name]=[];}
|
else{if(!Array.isArray(json[name])){json[name]=[];}
|
||||||
json[name].push({});ref=json[name][json[name].length-1];}}
|
json[name].push({});ref=json[name][json[name].length-1];}}
|
||||||
|
|
6
public/dist/scripts/app.js
vendored
6
public/dist/scripts/app.js
vendored
|
@ -256,9 +256,11 @@ match=text.match(new RegExp(regex,'gi'))
|
||||||
if(!match){return fail}
|
if(!match){return fail}
|
||||||
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
for(i=0,len=match.length;i<len;i++){if(!process(match[i])){return fail}}
|
||||||
return(date.getTime()/1000)}
|
return(date.getTime()/1000)}
|
||||||
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
return{format:format,strtotime:strtotime}}(),true);})(window);(function(window){"use strict";window.ls.container.set('env',function(){return APP_ENV;},true);})(window);(function(window){"use strict";window.ls.container.set('form',function(){function cast(value,to){if(value&&Array.isArray(value)&&to!=='array'){value=value.map(element=>cast(element,to));return value;}
|
||||||
|
switch(to){case'int':case'integer':value=parseInt(value);break;case'numeric':value=Number(value);break;case'string':value=value.toString();break;case'json':value=(value)?JSON.parse(value):[];break;case'array':value=(value&&value.constructor&&value.constructor===Array)?value:[value];break;case'array-empty':value=[];break;case'bool':case'boolean':value=(value==='false')?false:value;value=!!value;break;}
|
||||||
return value;}
|
return value;}
|
||||||
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
function toJson(element,json){json=json||{};let name=element.getAttribute('name');let type=element.getAttribute('type');let castTo=element.getAttribute('data-cast-to');let ref=json;if(name&&'FORM'!==element.tagName){if(name.startsWith('[')){let splitName=name.split('.');if(splitName.length>1&&splitName[0].endsWith(']')){name=splitName[splitName.length-1];}}
|
||||||
|
if('FIELDSET'===element.tagName){if(castTo==='object'){if(json[name]===undefined){json[name]={};}
|
||||||
ref=json[name];}
|
ref=json[name];}
|
||||||
else{if(!Array.isArray(json[name])){json[name]=[];}
|
else{if(!Array.isArray(json[name])){json[name]=[];}
|
||||||
json[name].push({});ref=json[name][json[name].length-1];}}
|
json[name].push({});ref=json[name][json[name].length-1];}}
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
window.ls.container.set('form', function () {
|
window.ls.container.set('form', function () {
|
||||||
|
|
||||||
function cast(value, to) {
|
function cast(value, to) {
|
||||||
|
if (value && Array.isArray(value) && to !== 'array') {
|
||||||
|
value = value.map(element => cast(element, to));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
switch (to) {
|
switch (to) {
|
||||||
case 'int':
|
case 'int':
|
||||||
case 'integer':
|
case 'integer':
|
||||||
|
@ -42,6 +46,12 @@
|
||||||
let ref = json;
|
let ref = json;
|
||||||
|
|
||||||
if (name && 'FORM' !== element.tagName) {
|
if (name && 'FORM' !== element.tagName) {
|
||||||
|
if (name.startsWith('[')) { // Check for array names
|
||||||
|
let splitName = name.split('.');
|
||||||
|
if (splitName.length > 1 && splitName[0].endsWith(']')) {
|
||||||
|
name = splitName[splitName.length-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
if ('FIELDSET' === element.tagName) { // Fieldset Array / Object
|
if ('FIELDSET' === element.tagName) { // Fieldset Array / Object
|
||||||
if (castTo === 'object') {
|
if (castTo === 'object') {
|
||||||
|
|
||||||
|
@ -118,4 +128,4 @@
|
||||||
}
|
}
|
||||||
}, true, false);
|
}, true, false);
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
56
src/Appwrite/Network/Validator/Email.php
Normal file
56
src/Appwrite/Network/Validator/Email.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use Utopia\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email
|
||||||
|
*
|
||||||
|
* Validate that an variable is a valid email address
|
||||||
|
*
|
||||||
|
* @package Utopia\Validator
|
||||||
|
*/
|
||||||
|
class Email extends Validator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get Description
|
||||||
|
*
|
||||||
|
* Returns validator description
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return 'Value must be a valid email address';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Type
|
||||||
|
*
|
||||||
|
* Returns validator type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is valid
|
||||||
|
*
|
||||||
|
* Validation will pass when $value is valid email address.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid($value)
|
||||||
|
{
|
||||||
|
if (!\filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
72
src/Appwrite/Network/Validator/Host.php
Normal file
72
src/Appwrite/Network/Validator/Host.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use Utopia\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host
|
||||||
|
*
|
||||||
|
* Validate that a host is allowed from given whitelisted hosts list
|
||||||
|
*
|
||||||
|
* @package Utopia\Validator
|
||||||
|
*/
|
||||||
|
class Host extends Validator
|
||||||
|
{
|
||||||
|
protected $whitelist = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $whitelist
|
||||||
|
*/
|
||||||
|
public function __construct(array $whitelist)
|
||||||
|
{
|
||||||
|
$this->whitelist = $whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Description
|
||||||
|
*
|
||||||
|
* Returns validator description
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return 'URL host must be one of: ' . \implode(', ', $this->whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Type
|
||||||
|
*
|
||||||
|
* Returns validator type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is valid
|
||||||
|
*
|
||||||
|
* Validation will pass when $value starts with one of the given hosts
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid($value)
|
||||||
|
{
|
||||||
|
$urlValidator = new URL();
|
||||||
|
|
||||||
|
if (!$urlValidator->isValid($value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\in_array(\parse_url($value, PHP_URL_HOST), $this->whitelist)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
102
src/Appwrite/Network/Validator/IP.php
Normal file
102
src/Appwrite/Network/Validator/IP.php
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Utopia\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP
|
||||||
|
*
|
||||||
|
* Validate that an variable is a valid IP address
|
||||||
|
*
|
||||||
|
* @package Utopia\Validator
|
||||||
|
*/
|
||||||
|
class IP extends Validator
|
||||||
|
{
|
||||||
|
const ALL = 'all';
|
||||||
|
const V4 = 'ipv4';
|
||||||
|
const V6 = 'ipv6';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $type = self::ALL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* Set a the type of IP check.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*/
|
||||||
|
public function __construct(string $type = self::ALL)
|
||||||
|
{
|
||||||
|
if (!in_array($type, [self::ALL, self::V4, self::V6])) {
|
||||||
|
throw new Exception('Unsupported IP type');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Description
|
||||||
|
*
|
||||||
|
* Returns validator description
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return 'Value must be a valid IP address';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Type
|
||||||
|
*
|
||||||
|
* Returns validator type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is valid
|
||||||
|
*
|
||||||
|
* Validation will pass when $value is valid IP address.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid($value)
|
||||||
|
{
|
||||||
|
switch ($this->type) {
|
||||||
|
case self::ALL:
|
||||||
|
if (\filter_var($value, FILTER_VALIDATE_IP)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::V4:
|
||||||
|
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case self::V6:
|
||||||
|
if (\filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
56
src/Appwrite/Network/Validator/URL.php
Normal file
56
src/Appwrite/Network/Validator/URL.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use Utopia\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
*
|
||||||
|
* Validate that an variable is a valid URL
|
||||||
|
*
|
||||||
|
* @package Utopia\Validator
|
||||||
|
*/
|
||||||
|
class URL extends Validator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get Description
|
||||||
|
*
|
||||||
|
* Returns validator description
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return 'Value must be a valid URL';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Type
|
||||||
|
*
|
||||||
|
* Returns validator type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is valid
|
||||||
|
*
|
||||||
|
* Validation will pass when $value is valid URL.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isValid($value)
|
||||||
|
{
|
||||||
|
if (\filter_var($value, FILTER_VALIDATE_URL) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,7 +83,9 @@ class OpenAPI3 extends Format
|
||||||
$output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => ''];
|
$output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
|
$usedModels = [];
|
||||||
|
|
||||||
|
foreach ($this->routes as $route) { /** @var \Utopia\Route $route */
|
||||||
$url = \str_replace('/v1', '', $route->getURL());
|
$url = \str_replace('/v1', '', $route->getURL());
|
||||||
$scope = $route->getLabel('scope', '');
|
$scope = $route->getLabel('scope', '');
|
||||||
$hide = $route->getLabel('sdk.hide', false);
|
$hide = $route->getLabel('sdk.hide', false);
|
||||||
|
@ -146,6 +148,7 @@ class OpenAPI3 extends Format
|
||||||
// ],
|
// ],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
$usedModels[] = $model->getType();
|
||||||
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
||||||
'description' => $model->getName(),
|
'description' => $model->getName(),
|
||||||
'content' => [
|
'content' => [
|
||||||
|
@ -236,7 +239,7 @@ class OpenAPI3 extends Format
|
||||||
$node['schema']['format'] = 'format';
|
$node['schema']['format'] = 'format';
|
||||||
$node['schema']['x-example'] = 'password';
|
$node['schema']['x-example'] = 'password';
|
||||||
break;
|
break;
|
||||||
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
|
case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */
|
||||||
$node['schema']['type'] = 'integer';
|
$node['schema']['type'] = 'integer';
|
||||||
$node['schema']['format'] = 'int32';
|
$node['schema']['format'] = 'int32';
|
||||||
$node['schema']['x-example'] = $validator->getMin();
|
$node['schema']['x-example'] = $validator->getMin();
|
||||||
|
@ -253,7 +256,7 @@ class OpenAPI3 extends Format
|
||||||
$node['schema']['format'] = 'url';
|
$node['schema']['format'] = 'url';
|
||||||
$node['schema']['x-example'] = 'https://example.com';
|
$node['schema']['x-example'] = 'https://example.com';
|
||||||
break;
|
break;
|
||||||
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
|
case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */
|
||||||
$node['schema']['type'] = 'string';
|
$node['schema']['type'] = 'string';
|
||||||
$node['schema']['x-example'] = $validator->getList()[0];
|
$node['schema']['x-example'] = $validator->getList()[0];
|
||||||
break;
|
break;
|
||||||
|
@ -307,8 +310,18 @@ class OpenAPI3 extends Format
|
||||||
|
|
||||||
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->models as $model) {
|
foreach ($this->models as $model) {
|
||||||
|
foreach ($model->getRules() as $rule) {
|
||||||
|
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
||||||
|
$usedModels[] = $rule['type'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($this->models as $model) {
|
||||||
|
if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$required = $model->getRequired();
|
$required = $model->getRequired();
|
||||||
$rules = $model->getRules();
|
$rules = $model->getRules();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Appwrite\Specification\Format;
|
||||||
|
|
||||||
use Appwrite\Specification\Format;
|
use Appwrite\Specification\Format;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
|
use Appwrite\Utopia\Response\Model;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
class Swagger2 extends Format
|
class Swagger2 extends Format
|
||||||
|
@ -81,7 +82,9 @@ class Swagger2 extends Format
|
||||||
$output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => ''];
|
$output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => ''];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
|
$usedModels = [];
|
||||||
|
|
||||||
|
foreach ($this->routes as $route) { /** @var \Utopia\Route $route */
|
||||||
$url = \str_replace('/v1', '', $route->getURL());
|
$url = \str_replace('/v1', '', $route->getURL());
|
||||||
$scope = $route->getLabel('scope', '');
|
$scope = $route->getLabel('scope', '');
|
||||||
$hide = $route->getLabel('sdk.hide', false);
|
$hide = $route->getLabel('sdk.hide', false);
|
||||||
|
@ -148,6 +151,7 @@ class Swagger2 extends Format
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
|
$usedModels[] = $model->getType();
|
||||||
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
||||||
'description' => $model->getName(),
|
'description' => $model->getName(),
|
||||||
'schema' => [
|
'schema' => [
|
||||||
|
@ -232,7 +236,7 @@ class Swagger2 extends Format
|
||||||
$node['format'] = 'format';
|
$node['format'] = 'format';
|
||||||
$node['x-example'] = 'password';
|
$node['x-example'] = 'password';
|
||||||
break;
|
break;
|
||||||
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
|
case 'Utopia\Validator\Range': /** @var \Utopia\Validator\Range $validator */
|
||||||
$node['type'] = 'integer';
|
$node['type'] = 'integer';
|
||||||
$node['format'] = 'int32';
|
$node['format'] = 'int32';
|
||||||
$node['x-example'] = $validator->getMin();
|
$node['x-example'] = $validator->getMin();
|
||||||
|
@ -249,7 +253,7 @@ class Swagger2 extends Format
|
||||||
$node['format'] = 'url';
|
$node['format'] = 'url';
|
||||||
$node['x-example'] = 'https://example.com';
|
$node['x-example'] = 'https://example.com';
|
||||||
break;
|
break;
|
||||||
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
|
case 'Utopia\Validator\WhiteList': /** @var \Utopia\Validator\WhiteList $validator */
|
||||||
$node['type'] = 'string';
|
$node['type'] = 'string';
|
||||||
$node['x-example'] = $validator->getList()[0];
|
$node['x-example'] = $validator->getList()[0];
|
||||||
break;
|
break;
|
||||||
|
@ -308,8 +312,18 @@ class Swagger2 extends Format
|
||||||
|
|
||||||
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->models as $model) {
|
foreach ($this->models as $model) {
|
||||||
|
foreach ($model->getRules() as $rule) {
|
||||||
|
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
|
||||||
|
$usedModels[] = $rule['type'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($this->models as $model) {
|
||||||
|
if (!in_array($model->getType(), $usedModels) && $model->getType() !== 'error') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$required = $model->getRequired();
|
$required = $model->getRequired();
|
||||||
$rules = $model->getRules();
|
$rules = $model->getRules();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use Appwrite\Utopia\Response\Model\Collection;
|
||||||
use Appwrite\Utopia\Response\Model\Continent;
|
use Appwrite\Utopia\Response\Model\Continent;
|
||||||
use Appwrite\Utopia\Response\Model\Country;
|
use Appwrite\Utopia\Response\Model\Country;
|
||||||
use Appwrite\Utopia\Response\Model\Currency;
|
use Appwrite\Utopia\Response\Model\Currency;
|
||||||
|
use Appwrite\Utopia\Response\Model\Document as ModelDocument;
|
||||||
use Appwrite\Utopia\Response\Model\Domain;
|
use Appwrite\Utopia\Response\Model\Domain;
|
||||||
use Appwrite\Utopia\Response\Model\Error;
|
use Appwrite\Utopia\Response\Model\Error;
|
||||||
use Appwrite\Utopia\Response\Model\ErrorDev;
|
use Appwrite\Utopia\Response\Model\ErrorDev;
|
||||||
|
@ -61,6 +62,7 @@ class Response extends SwooleResponse
|
||||||
const MODEL_COLLECTION = 'collection';
|
const MODEL_COLLECTION = 'collection';
|
||||||
const MODEL_COLLECTION_LIST = 'collectionList';
|
const MODEL_COLLECTION_LIST = 'collectionList';
|
||||||
const MODEL_RULE = 'rule';
|
const MODEL_RULE = 'rule';
|
||||||
|
const MODEL_DOCUMENT = 'document';
|
||||||
const MODEL_DOCUMENT_LIST = 'documentList';
|
const MODEL_DOCUMENT_LIST = 'documentList';
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
|
@ -145,7 +147,7 @@ class Response extends SwooleResponse
|
||||||
->setModel(new ErrorDev())
|
->setModel(new ErrorDev())
|
||||||
// Lists
|
// Lists
|
||||||
->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION))
|
->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION))
|
||||||
->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_ANY))
|
->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT))
|
||||||
->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER))
|
->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER))
|
||||||
->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION))
|
->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION))
|
||||||
->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG, false))
|
->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG, false))
|
||||||
|
@ -169,6 +171,7 @@ class Response extends SwooleResponse
|
||||||
// Entities
|
// Entities
|
||||||
->setModel(new Permissions())
|
->setModel(new Permissions())
|
||||||
->setModel(new Collection())
|
->setModel(new Collection())
|
||||||
|
->setModel(new ModelDocument())
|
||||||
->setModel(new Rule())
|
->setModel(new Rule())
|
||||||
->setModel(new Log())
|
->setModel(new Log())
|
||||||
->setModel(new User())
|
->setModel(new User())
|
||||||
|
|
|
@ -108,6 +108,7 @@ class V06 extends Filter {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Response::MODEL_ANY :
|
case Response::MODEL_ANY :
|
||||||
|
case Response::MODEL_DOCUMENT :
|
||||||
$parsedResponse = $content;
|
$parsedResponse = $content;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
52
src/Appwrite/Utopia/Response/Model/Document.php
Normal file
52
src/Appwrite/Utopia/Response/Model/Document.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Appwrite\Utopia\Response\Model;
|
||||||
|
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
|
|
||||||
|
class Document extends Any
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get Name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return 'Document';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Collection
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return Response::MODEL_DOCUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->addRule('$id', [
|
||||||
|
'type' => self::TYPE_STRING,
|
||||||
|
'description' => 'Document ID.',
|
||||||
|
'default' => '',
|
||||||
|
'example' => '5e5ea5c16897e',
|
||||||
|
])
|
||||||
|
->addRule('$collection', [
|
||||||
|
'type' => self::TYPE_STRING,
|
||||||
|
'description' => 'Collection ID.',
|
||||||
|
'default' => '',
|
||||||
|
'example' => '5e5ea5c15117e',
|
||||||
|
])
|
||||||
|
->addRule('$permissions', [
|
||||||
|
'type' => Response::MODEL_PERMISSIONS,
|
||||||
|
'description' => 'Document permissions.',
|
||||||
|
'default' => new \stdClass,
|
||||||
|
'example' => new \stdClass,
|
||||||
|
'array' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -485,6 +485,14 @@ class FunctionsCustomServerTest extends Scope
|
||||||
'command' => 'python main.py',
|
'command' => 'python main.py',
|
||||||
'timeout' => 15,
|
'timeout' => 15,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'language' => 'Python',
|
||||||
|
'version' => '3.9',
|
||||||
|
'name' => 'python-3.9',
|
||||||
|
'code' => $functions.'/python.tar.gz',
|
||||||
|
'command' => 'python main.py',
|
||||||
|
'timeout' => 15,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'language' => 'Node.js',
|
'language' => 'Node.js',
|
||||||
'version' => '14.5',
|
'version' => '14.5',
|
||||||
|
@ -533,6 +541,14 @@ class FunctionsCustomServerTest extends Scope
|
||||||
'command' => 'deno run --allow-env index.ts',
|
'command' => 'deno run --allow-env index.ts',
|
||||||
'timeout' => 15,
|
'timeout' => 15,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'language' => 'Deno',
|
||||||
|
'version' => '1.8',
|
||||||
|
'name' => 'deno-1.8',
|
||||||
|
'code' => $functions.'/deno.tar.gz',
|
||||||
|
'command' => 'deno run --allow-env index.ts',
|
||||||
|
'timeout' => 15,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'language' => 'Dart',
|
'language' => 'Dart',
|
||||||
'version' => '2.10',
|
'version' => '2.10',
|
||||||
|
@ -541,6 +557,14 @@ class FunctionsCustomServerTest extends Scope
|
||||||
'command' => 'dart main.dart',
|
'command' => 'dart main.dart',
|
||||||
'timeout' => 15,
|
'timeout' => 15,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'language' => 'Dart',
|
||||||
|
'version' => '2.12',
|
||||||
|
'name' => 'dart-2.12',
|
||||||
|
'code' => $functions.'/dart.tar.gz',
|
||||||
|
'command' => 'dart main.dart',
|
||||||
|
'timeout' => 15,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'language' => '.NET',
|
'language' => '.NET',
|
||||||
'version' => '3.1',
|
'version' => '3.1',
|
||||||
|
|
|
@ -62,7 +62,7 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mariadb
|
||||||
- redis
|
- redis
|
||||||
- clamav
|
# - clamav
|
||||||
- influxdb
|
- influxdb
|
||||||
environment:
|
environment:
|
||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
|
@ -81,6 +81,7 @@ services:
|
||||||
- _APP_USAGE_STATS
|
- _APP_USAGE_STATS
|
||||||
- _APP_INFLUXDB_HOST
|
- _APP_INFLUXDB_HOST
|
||||||
- _APP_INFLUXDB_PORT
|
- _APP_INFLUXDB_PORT
|
||||||
|
- _APP_STORAGE_ANTIVIRUS=disabled
|
||||||
- _APP_STORAGE_LIMIT
|
- _APP_STORAGE_LIMIT
|
||||||
- _APP_FUNCTIONS_TIMEOUT
|
- _APP_FUNCTIONS_TIMEOUT
|
||||||
- _APP_FUNCTIONS_CONTAINERS
|
- _APP_FUNCTIONS_CONTAINERS
|
||||||
|
@ -326,14 +327,14 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-redis:/data:rw
|
- appwrite-redis:/data:rw
|
||||||
|
|
||||||
clamav:
|
# clamav:
|
||||||
image: appwrite/clamav:1.2.0
|
# image: appwrite/clamav:1.2.0
|
||||||
container_name: appwrite-clamav
|
# container_name: appwrite-clamav
|
||||||
restart: unless-stopped
|
# restart: unless-stopped
|
||||||
networks:
|
# networks:
|
||||||
- appwrite
|
# - appwrite
|
||||||
volumes:
|
# volumes:
|
||||||
- appwrite-uploads:/storage/uploads
|
# - appwrite-uploads:/storage/uploads
|
||||||
|
|
||||||
influxdb:
|
influxdb:
|
||||||
image: influxdb:1.6
|
image: influxdb:1.6
|
||||||
|
|
|
@ -36,7 +36,7 @@ class ComposeTest extends TestCase
|
||||||
|
|
||||||
public function testServices()
|
public function testServices()
|
||||||
{
|
{
|
||||||
$this->assertCount(17, $this->object->getServices());
|
$this->assertCount(16, $this->object->getServices());
|
||||||
$this->assertEquals('appwrite-telegraf', $this->object->getService('telegraf')->getContainerName());
|
$this->assertEquals('appwrite-telegraf', $this->object->getService('telegraf')->getContainerName());
|
||||||
$this->assertEquals('appwrite', $this->object->getService('appwrite')->getContainerName());
|
$this->assertEquals('appwrite', $this->object->getService('appwrite')->getContainerName());
|
||||||
$this->assertEquals('', $this->object->getService('appwrite')->getImageVersion());
|
$this->assertEquals('', $this->object->getService('appwrite')->getImageVersion());
|
||||||
|
|
71
tests/unit/Network/Validators/EmailTest.php
Executable file
71
tests/unit/Network/Validators/EmailTest.php
Executable file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Utopia PHP Framework
|
||||||
|
*
|
||||||
|
* @package Framework
|
||||||
|
* @subpackage Tests
|
||||||
|
*
|
||||||
|
* @link https://github.com/utopia-php/framework
|
||||||
|
* @author Appwrite Team <team@appwrite.io>
|
||||||
|
* @version 1.0 RC4
|
||||||
|
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class EmailTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Email
|
||||||
|
*/
|
||||||
|
protected $email = null;
|
||||||
|
|
||||||
|
public function setUp():void
|
||||||
|
{
|
||||||
|
$this->email = new Email();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown():void
|
||||||
|
{
|
||||||
|
$this->email = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid()
|
||||||
|
{
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('firstname.lastname@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@subdomain.domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('firstname+lastname@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@[123.123.123.123]'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('"email"@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('1234567890@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@domain-one.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('_______@domain.com'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@domain.name'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('email@domain.co.jp'));
|
||||||
|
$this->assertEquals(true, $this->email->isValid('firstname-lastname@domain.com'));
|
||||||
|
$this->assertEquals(false, $this->email->isValid(false));
|
||||||
|
$this->assertEquals(false, $this->email->isValid(['string', 'string']));
|
||||||
|
$this->assertEquals(false, $this->email->isValid(1));
|
||||||
|
$this->assertEquals(false, $this->email->isValid(1.2));
|
||||||
|
$this->assertEquals(false, $this->email->isValid('plainaddress')); // Missing @ sign and domain
|
||||||
|
$this->assertEquals(false, $this->email->isValid('@domain.com')); // Missing username
|
||||||
|
$this->assertEquals(false, $this->email->isValid('#@%^%#$@#$@#.com')); // Garbage
|
||||||
|
$this->assertEquals(false, $this->email->isValid('Joe Smith <email@domain.com>')); // Encoded html within email is invalid
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email.domain.com')); // Missing @
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@domain@domain.com')); // Two @ sign
|
||||||
|
$this->assertEquals(false, $this->email->isValid('.email@domain.com')); // Leading dot in address is not allowed
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email.@domain.com')); // Trailing dot in address is not allowed
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email..email@domain.com')); // Multiple dots
|
||||||
|
$this->assertEquals(false, $this->email->isValid('あいうえお@domain.com')); // Unicode char as address
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@domain.com (Joe Smith)')); // Text followed email is not allowed
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@domain')); // Missing top level domain (.com/.net/.org/etc)
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@-domain.com')); // Leading dash in front of domain is invalid
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@111.222.333.44444')); // Invalid IP format
|
||||||
|
$this->assertEquals(false, $this->email->isValid('email@domain..com')); // Multiple dot in the domain portion is invalid
|
||||||
|
$this->assertEquals($this->email->getType(), 'string');
|
||||||
|
}
|
||||||
|
}
|
45
tests/unit/Network/Validators/HostTest.php
Executable file
45
tests/unit/Network/Validators/HostTest.php
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Utopia PHP Framework
|
||||||
|
*
|
||||||
|
* @package Framework
|
||||||
|
* @subpackage Tests
|
||||||
|
*
|
||||||
|
* @link https://github.com/utopia-php/framework
|
||||||
|
* @author Appwrite Team <team@appwrite.io>
|
||||||
|
* @version 1.0 RC4
|
||||||
|
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class HostTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Host
|
||||||
|
*/
|
||||||
|
protected $host = null;
|
||||||
|
|
||||||
|
public function setUp():void
|
||||||
|
{
|
||||||
|
$this->host = new Host(['appwrite.io', 'subdomain.appwrite.test', 'localhost']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown():void
|
||||||
|
{
|
||||||
|
$this->host = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid()
|
||||||
|
{
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals($this->host->isValid('https://appwrite.io/link'), true);
|
||||||
|
$this->assertEquals($this->host->isValid('https://localhost'), true);
|
||||||
|
$this->assertEquals($this->host->isValid('localhost'), false);
|
||||||
|
$this->assertEquals($this->host->isValid('http://subdomain.appwrite.test/path'), true);
|
||||||
|
$this->assertEquals($this->host->isValid('http://test.subdomain.appwrite.test/path'), false);
|
||||||
|
$this->assertEquals($this->host->getType(), 'string');
|
||||||
|
}
|
||||||
|
}
|
81
tests/unit/Network/Validators/IPTest.php
Executable file
81
tests/unit/Network/Validators/IPTest.php
Executable file
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Utopia PHP Framework
|
||||||
|
*
|
||||||
|
* @package Framework
|
||||||
|
* @subpackage Tests
|
||||||
|
*
|
||||||
|
* @link https://github.com/utopia-php/framework
|
||||||
|
* @author Appwrite Team <team@appwrite.io>
|
||||||
|
* @version 1.0 RC4
|
||||||
|
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class IPTest extends TestCase
|
||||||
|
{
|
||||||
|
public function tearDown():void
|
||||||
|
{
|
||||||
|
$this->validator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValidIP()
|
||||||
|
{
|
||||||
|
$validator = new IP();
|
||||||
|
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||||
|
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||||
|
$this->assertEquals($validator->isValid(23.5), false);
|
||||||
|
$this->assertEquals($validator->isValid('23.5'), false);
|
||||||
|
$this->assertEquals($validator->isValid(null), false);
|
||||||
|
$this->assertEquals($validator->isValid(true), false);
|
||||||
|
$this->assertEquals($validator->isValid(false), false);
|
||||||
|
$this->assertEquals($validator->getType(), 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValidIPALL()
|
||||||
|
{
|
||||||
|
$validator = new IP(IP::ALL);
|
||||||
|
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||||
|
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||||
|
$this->assertEquals($validator->isValid(23.5), false);
|
||||||
|
$this->assertEquals($validator->isValid('23.5'), false);
|
||||||
|
$this->assertEquals($validator->isValid(null), false);
|
||||||
|
$this->assertEquals($validator->isValid(true), false);
|
||||||
|
$this->assertEquals($validator->isValid(false), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValidIPV4()
|
||||||
|
{
|
||||||
|
$validator = new IP(IP::V4);
|
||||||
|
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), false);
|
||||||
|
$this->assertEquals($validator->isValid('109.67.204.101'), true);
|
||||||
|
$this->assertEquals($validator->isValid(23.5), false);
|
||||||
|
$this->assertEquals($validator->isValid('23.5'), false);
|
||||||
|
$this->assertEquals($validator->isValid(null), false);
|
||||||
|
$this->assertEquals($validator->isValid(true), false);
|
||||||
|
$this->assertEquals($validator->isValid(false), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValidIPV6()
|
||||||
|
{
|
||||||
|
$validator = new IP(IP::V6);
|
||||||
|
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals($validator->isValid('2001:0db8:85a3:08d3:1319:8a2e:0370:7334'), true);
|
||||||
|
$this->assertEquals($validator->isValid('109.67.204.101'), false);
|
||||||
|
$this->assertEquals($validator->isValid(23.5), false);
|
||||||
|
$this->assertEquals($validator->isValid('23.5'), false);
|
||||||
|
$this->assertEquals($validator->isValid(null), false);
|
||||||
|
$this->assertEquals($validator->isValid(true), false);
|
||||||
|
$this->assertEquals($validator->isValid(false), false);
|
||||||
|
}
|
||||||
|
}
|
48
tests/unit/Network/Validators/URLTest.php
Executable file
48
tests/unit/Network/Validators/URLTest.php
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Utopia PHP Framework
|
||||||
|
*
|
||||||
|
* @package Framework
|
||||||
|
* @subpackage Tests
|
||||||
|
*
|
||||||
|
* @link https://github.com/utopia-php/framework
|
||||||
|
* @author Appwrite Team <team@appwrite.io>
|
||||||
|
* @version 1.0 RC4
|
||||||
|
* @license The MIT License (MIT) <http://www.opensource.org/licenses/mit-license.php>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Appwrite\Network\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class URLTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Domain
|
||||||
|
*/
|
||||||
|
protected $url = null;
|
||||||
|
|
||||||
|
public function setUp():void
|
||||||
|
{
|
||||||
|
$this->url = new URL();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown():void
|
||||||
|
{
|
||||||
|
$this->url = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid()
|
||||||
|
{
|
||||||
|
// Assertions
|
||||||
|
$this->assertEquals(true, $this->url->isValid('http://example.com'));
|
||||||
|
$this->assertEquals(true, $this->url->isValid('https://example.com'));
|
||||||
|
$this->assertEquals(true, $this->url->isValid('htts://example.com')); // does not validate protocol
|
||||||
|
$this->assertEquals(false, $this->url->isValid('example.com')); // though, requires some kind of protocol
|
||||||
|
$this->assertEquals(false, $this->url->isValid('http:/example.com'));
|
||||||
|
$this->assertEquals(true, $this->url->isValid('http://exa-mple.com'));
|
||||||
|
$this->assertEquals(false, $this->url->isValid('htt@s://example.com'));
|
||||||
|
$this->assertEquals(true, $this->url->isValid('http://www.example.com/foo%2\u00c2\u00a9zbar'));
|
||||||
|
$this->assertEquals(true, $this->url->isValid('http://www.example.com/?q=%3Casdf%3E'));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue