1
0
Fork 0
mirror of synced 2024-05-21 05:02:37 +12:00

Merge branch 'master' of github.com:appwrite/appwrite into database-ui

This commit is contained in:
Eldad Fux 2020-03-27 01:56:57 +02:00
commit f35258b9c5
141 changed files with 2438 additions and 3000 deletions

View file

@ -1,4 +1,24 @@
# Version 0.5.0 (PRE-RELEASE) - PLANNED
# Version 0.5.3 (PRE-RELEASE)
## Bug Fixes
* Fixed bug where multiple unique attribute were allowed
* Blocked forms from being submitted unlimited times
# Version 0.5.2 (PRE-RELEASE)
## Bug Fixes
* Fixed missing attributes in user account
# Version 0.5.1 (PRE-RELEASE)
## Bug Fixes
* Delayed SSL init when server startup for traefik to be ready for HTTP challenge
* Enabled easy access to the upgrade tool from the terminal
# Version 0.5.0 (PRE-RELEASE)
## Features

View file

@ -1,4 +1,4 @@
FROM ubuntu:18.04 AS builder
FROM ubuntu:19.10 AS builder
LABEL maintainer="team@appwrite.io"
@ -131,8 +131,14 @@ RUN mkdir -p /storage/uploads && \
# Supervisord Conf
COPY ./docker/supervisord.conf /etc/supervisord.conf
COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod 775 /entrypoint.sh
# Start
COPY ./docker/bin/start /start
RUN chmod 775 /start
# Upgrade
COPY ./docker/bin/upgrade /upgrade
RUN chmod 775 /upgrade
# Letsencrypt Permissions
RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
@ -141,4 +147,4 @@ EXPOSE 80
WORKDIR /usr/share/nginx/html
CMD ["/bin/bash", "/entrypoint.sh"]
CMD ["/bin/bash", "/start"]

View file

@ -8,7 +8,7 @@
</p>
[![Discord](https://img.shields.io/discord/564160730845151244)](https://discord.gg/GSeTUeA)
[![Discord](https://badgen.net/badge/discord/chat/green)](https://discord.gg/GSeTUeA)
[![Docker Pulls](https://badgen.net/docker/pulls/appwrite/appwrite)](https://travis-ci.org/appwrite/appwrite)
[![Travis CI](https://badgen.net/travis/appwrite/appwrite?label=build)](https://travis-ci.org/appwrite/appwrite)
[![Twitter Account](https://badgen.net/twitter/follow/appwrite_io?label=twitter)](https://twitter.com/appwrite_io)
@ -46,13 +46,13 @@ Appwrite backend server is designed to run in a container environment. Running y
The easiest way to start running your Appwrite server is by running our docker-compose file. Before running the installation command make sure you have [Docker](https://www.docker.com/products/docker-desktop) installed on your machine:
```bash
mkdir appwrite-ce && \
cd appwrite-ce && \
curl -o docker-compose.yml https://appwrite.io/docker-compose.yml?version=0.4.0&port=80 && \
docker-compose up -d --remove-orphans
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/install/appwrite:rw \
-e version=0.5.3 \
appwrite/install
```
Once the Docker installation completes, go to http://localhost to access the Appwrite console from your browser. Please note that on non-linux native hosts, the server might take a few minutes to start after installation completes.

View file

@ -3,21 +3,18 @@
// Init
require_once __DIR__.'/init.php';
global $env, $utopia, $request, $response, $register, $consoleDB, $project, $domain, $version, $service, $protocol;
global $env, $utopia, $request, $response, $register, $consoleDB, $project, $domain, $version, $service, $protocol, $domainVerification;
use Utopia\App;
use Utopia\Request;
use Utopia\Response;
use Utopia\Validator\Range;
use Utopia\View;
use Utopia\Exception;
use Auth\Auth;
use Database\Database;
use Database\Document;
use Database\Validator\Authorization;
use Event\Event;
use Utopia\Domains\Domain;
use Utopia\Validator\WhiteList;
use Appwrite\Auth\Auth;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Event\Event;
/*
* Configuration files
@ -404,494 +401,11 @@ $utopia->get('/.well-known/acme-challenge')
}
);
$utopia->get('/v1/info') // This is only visible to the gods
->label('scope', 'god')
->label('docs', false)
->action(
function () use ($response, $user, $project, $version, $env) {
$response->json([
'name' => 'API',
'version' => $version,
'environment' => $env,
'time' => date('Y-m-d H:i:s', time()),
'user' => [
'id' => $user->getId(),
'name' => $user->getAttribute('name', ''),
],
'project' => [
'id' => $project->getId(),
'name' => $project->getAttribute('name', ''),
],
]);
}
);
$utopia->get('/v1/xss')
->desc('Log XSS errors reported by browsers using X-XSS-Protection header')
->label('scope', 'public')
->label('docs', false)
->action(
function () {
throw new Exception('XSS detected and reported by a browser client', 500);
}
);
$utopia->get('/v1/proxy')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($response, $console, $clients) {
$view = new View(__DIR__.'/views/proxy.phtml');
$view
->setParam('routes', '')
->setParam('clients', array_merge($clients, $console->getAttribute('clients', [])))
;
$response
->setContentType(Response::CONTENT_TYPE_HTML)
->removeHeader('X-Frame-Options')
->send($view->render());
}
);
$utopia->get('/v1/open-api-2.json')
->label('scope', 'public')
->label('docs', false)
->param('platform', 'client', function () {return new WhiteList([APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER, APP_PLATFORM_CONSOLE]);}, 'Choose target platform.', true)
->param('extensions', 0, function () {return new Range(0, 1);}, 'Show extra data.', true)
->param('tests', 0, function () {return new Range(0, 1);}, 'Include only test services.', true)
->action(
function ($platform, $extensions, $tests) use ($response, $request, $utopia, $domain, $services, $protocol) {
function fromCamelCase($input)
{
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
$ret = $matches[0];
foreach ($ret as &$match) {
$match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
}
return implode('_', $ret);
}
function fromCamelCaseToDash($input)
{
return str_replace([' ', '_'], '-', strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $input)));
}
foreach ($services as $service) { /* @noinspection PhpIncludeInspection */
if($tests && !$service['tests']) {
continue;
}
if (!$tests && !$service['sdk']) {
continue;
}
/** @noinspection PhpIncludeInspection */
include_once $service['controller'];
}
$security = [
APP_PLATFORM_CLIENT => ['Project' => []],
APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
];
$platforms = [
'client' => APP_PLATFORM_CLIENT,
'server' => APP_PLATFORM_SERVER,
'all' => APP_PLATFORM_CONSOLE,
];
/*
* Specifications (v3.0.0):
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
*/
$output = [
'swagger' => '2.0',
'info' => [
'version' => APP_VERSION_STABLE,
'title' => APP_NAME,
'description' => 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)',
'termsOfService' => 'https://appwrite.io/policy/terms',
'contact' => [
'name' => 'Appwrite Team',
'url' => 'https://appwrite.io/support',
'email' => APP_EMAIL_TEAM,
],
'license' => [
'name' => 'BSD-3-Clause',
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
],
],
'host' => parse_url($request->getServer('_APP_HOME', $domain), PHP_URL_HOST),
'basePath' => '/v1',
'schemes' => ['https'],
'consumes' => ['application/json', 'multipart/form-data'],
'produces' => ['application/json'],
'securityDefinitions' => [
'Project' => [
'type' => 'apiKey',
'name' => 'X-Appwrite-Project',
'description' => 'Your project ID',
'in' => 'header',
],
'Key' => [
'type' => 'apiKey',
'name' => 'X-Appwrite-Key',
'description' => 'Your secret API key',
'in' => 'header',
],
'Locale' => [
'type' => 'apiKey',
'name' => 'X-Appwrite-Locale',
'description' => '',
'in' => 'header',
],
'Mode' => [
'type' => 'apiKey',
'name' => 'X-Appwrite-Mode',
'description' => '',
'in' => 'header',
],
],
'paths' => [],
'definitions' => [
// 'Pet' => [
// 'required' => ['id', 'name'],
// 'properties' => [
// 'id' => [
// 'type' => 'integer',
// 'format' => 'int64',
// ],
// 'name' => [
// 'type' => 'string',
// ],
// 'tag' => [
// 'type' => 'string',
// ],
// ],
// ],
// 'Pets' => array(
// 'type' => 'array',
// 'items' => array(
// '$ref' => '#/definitions/Pet',
// ),
// ),
'Error' => array(
'required' => array(
0 => 'code',
1 => 'message',
),
'properties' => array(
'code' => array(
'type' => 'integer',
'format' => 'int32',
),
'message' => array(
'type' => 'string',
),
),
),
],
'externalDocs' => [
'description' => 'Full API docs, specs and tutorials',
'url' => $protocol.'://'.$domain.'/docs',
],
];
if ($extensions) {
$output['securityDefinitions']['Project']['extensions'] = ['demo' => '5df5acd0d48c2'];
$output['securityDefinitions']['Key']['extensions'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
$output['securityDefinitions']['Locale']['extensions'] = ['demo' => 'en'];
$output['securityDefinitions']['Mode']['extensions'] = ['demo' => ''];
}
foreach ($utopia->getRoutes() as $key => $method) {
foreach ($method as $route) { /* @var $route \Utopia\Route */
if (!$route->getLabel('docs', true)) {
continue;
}
if (empty($route->getLabel('sdk.namespace', null))) {
continue;
}
if($platform !== APP_PLATFORM_CONSOLE && !in_array($platforms[$platform], $route->getLabel('sdk.platform', []))) {
continue;
}
$url = str_replace('/v1', '', $route->getURL());
$scope = $route->getLabel('scope', '');
$hide = $route->getLabel('sdk.hide', false);
$consumes = ['application/json'];
if ($hide) {
continue;
}
$desc = (!empty($route->getLabel('sdk.description', ''))) ? realpath(__DIR__ . '/..' . $route->getLabel('sdk.description', '')) : null;
$temp = [
'summary' => $route->getDesc(),
'operationId' => $route->getLabel('sdk.method', uniqid()),
'consumes' => [],
'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? file_get_contents($desc) : '',
// 'responses' => [
// 200 => [
// 'description' => 'An paged array of pets',
// 'schema' => [
// '$ref' => '#/definitions/Pet',
// ],
// ],
// ],
];
if ($extensions) {
$platformList = $route->getLabel('sdk.platform', []);
if(in_array(APP_PLATFORM_CLIENT, $platformList)) {
$platformList = array_merge($platformList, [
APP_PLATFORM_WEB,
APP_PLATFORM_IOS,
APP_PLATFORM_ANDROID,
APP_PLATFORM_FLUTTER,
]);
}
$temp['extensions'] = [
'weight' => $route->getOrder(),
'cookies' => $route->getLabel('sdk.cookies', false),
'location' => $route->getLabel('sdk.location', false),
'demo' => 'docs/examples/'.fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.fromCamelCaseToDash($temp['operationId']).'.md',
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''),
'rate-limit' => $route->getLabel('abuse-limit', 0),
'rate-time' => $route->getLabel('abuse-time', 3600),
'scope' => $route->getLabel('scope', ''),
'platforms' => $platformList,
];
}
if ((!empty($scope))) { // && 'public' != $scope
$temp['security'][] = $route->getLabel('sdk.security', $security[$platform]);
}
$requestBody = [
'content' => [
'application/x-www-form-urlencoded' => [
'schema' => [
'type' => 'object',
'properties' => [],
],
'required' => [],
],
],
];
foreach ($route->getParams() as $name => $param) {
$validator = (is_callable($param['validator'])) ? $param['validator']() : $param['validator']; /* @var $validator \Utopia\Validator */
$node = [
'name' => $name,
'description' => $param['description'],
'required' => !$param['optional'],
];
switch ((!empty($validator)) ? get_class($validator) : '') {
case 'Utopia\Validator\Text':
$node['type'] = 'string';
$node['x-example'] = '['.strtoupper(fromCamelCase($node['name'])).']';
break;
case 'Database\Validator\UID':
$node['type'] = 'string';
$node['x-example'] = '['.strtoupper(fromCamelCase($node['name'])).']';
break;
case 'Utopia\Validator\Email':
$node['type'] = 'string';
$node['format'] = 'email';
$node['x-example'] = 'email@example.com';
break;
case 'Utopia\Validator\URL':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['type'] = 'object';
$node['type'] = 'object';
$node['x-example'] = '{}';
//$node['format'] = 'json';
break;
case 'Storage\Validators\File':
$consumes = ['multipart/form-data'];
$node['type'] = 'file';
break;
case 'Utopia\Validator\ArrayList':
$node['type'] = 'array';
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
break;
case 'Auth\Validator\Password':
$node['type'] = 'string';
$node['format'] = 'format';
$node['x-example'] = 'password';
break;
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
$node['type'] = 'integer';
$node['format'] = 'int32';
$node['x-example'] = $validator->getMin();
break;
case 'Utopia\Validator\Numeric':
$node['type'] = 'integer';
$node['format'] = 'int32';
break;
case 'Utopia\Validator\Length':
$node['type'] = 'string';
break;
case 'Utopia\Validator\Host':
$node['type'] = 'string';
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
$node['type'] = 'string';
$node['x-example'] = $validator->getList()[0];
break;
default:
$node['type'] = 'string';
break;
}
if ($param['optional'] && !is_null($param['default'])) { // Param has default value
$node['default'] = $param['default'];
}
if (false !== strpos($url, ':'.$name)) { // Param is in URL path
$node['in'] = 'path';
$temp['parameters'][] = $node;
} elseif ($key == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
} else { // Param is in payload
$node['in'] = 'formData';
$temp['parameters'][] = $node;
$requestBody['content']['application/x-www-form-urlencoded']['schema']['properties'][] = $node;
if (!$param['optional']) {
$requestBody['content']['application/x-www-form-urlencoded']['required'][] = $name;
}
}
$url = str_replace(':'.$name, '{'.$name.'}', $url);
}
$temp['consumes'] = $consumes;
$output['paths'][$url][strtolower($route->getMethod())] = $temp;
}
}
/*foreach ($consoleDB->getMocks() as $mock) {
var_dump($mock['name']);
}*/
ksort($output['paths']);
$response
->json($output);
}
);
$utopia->get('/v1/debug')
->label('scope', 'public')
->label('docs', false)
->action(
function () use ($response, $request, $utopia, $domain, $services) {
$output = [
'scopes' => [],
'webhooks' => [],
'methods' => [],
'routes' => [],
'docs' => [],
];
foreach ($services as $service) { /* @noinspection PhpIncludeInspection */
/** @noinspection PhpIncludeInspection */
if($service['tests']) {
continue;
}
include_once $service['controller'];
}
$i = 0;
foreach ($utopia->getRoutes() as $key => $method) {
foreach ($method as $route) { /* @var $route \Utopia\Route */
if (!$route->getLabel('docs', true)) {
continue;
}
if (empty($route->getLabel('sdk.namespace', null))) {
continue;
}
if ($route->getLabel('scope', false)) {
$output['scopes'][$route->getLabel('scope', false)] = $route->getMethod().' '.$route->getURL();
}
if ($route->getLabel('sdk.description', false)) {
if(!realpath(__DIR__.'/../'.$route->getLabel('sdk.description', false))) {
throw new Exception('Docs file ('.$route->getLabel('sdk.description', false).') is missing', 500);
}
if(array_key_exists($route->getLabel('sdk.description', false), $output['docs'])) {
throw new Exception('Docs file ('.$route->getLabel('sdk.description', false).') is already in use by another route', 500);
}
$output['docs'][$route->getLabel('sdk.description', false)] = $route->getMethod().' '.$route->getURL();
}
if ($route->getLabel('webhook', false)) {
if(array_key_exists($route->getLabel('webhook', false), $output['webhooks'])) {
//throw new Exception('Webhook ('.$route->getLabel('webhook', false).') is already in use by another route', 500);
}
$output['webhooks'][$route->getLabel('webhook', false)] = $route->getMethod().' '.$route->getURL();
}
if ($route->getLabel('sdk.namespace', false)) {
$method = $route->getLabel('sdk.namespace', false).'->'.$route->getLabel('sdk.method', false).'()';
if(array_key_exists($method, $output['methods'])) {
throw new Exception('Method ('.$method.') is already in use by another route', 500);
}
$output['methods'][$method] = $route->getMethod().' '.$route->getURL();
}
$output['routes'][$route->getURL().' ('.$route->getMethod().')'] = [];
$i++;
}
}
ksort($output['scopes']);
ksort($output['webhooks']);
ksort($output['methods']);
ksort($output['routes']);
ksort($output['docs']);
$response
->json($output);
}
);
$name = APP_NAME;
@ -903,4 +417,4 @@ if (array_key_exists($service, $services)) { /** @noinspection PhpIncludeInspect
include_once $services['/']['controller'];
}
$utopia->run($request, $response);
$utopia->run($request, $response);

0
app/cache/.gitkeep vendored
View file

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
global $providers, $request;
use Database\Database;
use Appwrite\Database\Database;
$collections = [
'console' => [

View file

@ -21,7 +21,7 @@ return [
[
'key' => 'javascript',
'name' => 'JavaScript',
'version' => '1.0.28',
'version' => '1.0.29',
'url' => 'https://github.com/appwrite/sdk-for-js',
'enabled' => true,
'beta' => false,
@ -130,7 +130,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '0.0.6',
'version' => '0.0.7',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'enabled' => true,
'beta' => true,
@ -177,7 +177,7 @@ return [
[
'key' => 'nodejs',
'name' => 'Node.js',
'version' => '1.0.31',
'version' => '1.0.32',
'url' => 'https://github.com/appwrite/sdk-for-node',
'enabled' => true,
'beta' => false,
@ -191,7 +191,7 @@ return [
[
'key' => 'php',
'name' => 'PHP',
'version' => '1.0.16',
'version' => '1.0.17',
'url' => 'https://github.com/appwrite/sdk-for-php',
'enabled' => true,
'beta' => false,
@ -205,7 +205,7 @@ return [
[
'key' => 'python',
'name' => 'Python',
'version' => '0.0.3',
'version' => '0.0.4',
'url' => 'https://github.com/appwrite/sdk-for-python',
'enabled' => true,
'beta' => true,
@ -219,7 +219,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '1.0.8',
'version' => '1.0.9',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'enabled' => true,
'beta' => true,
@ -233,7 +233,7 @@ return [
[
'key' => 'go',
'name' => 'Go',
'version' => '0.0.5',
'version' => '0.0.6',
'url' => 'https://github.com/appwrite/sdk-for-go',
'enabled' => true,
'beta' => true,

View file

@ -14,16 +14,17 @@ use Utopia\Validator\URL;
use Utopia\Audit\Audit;
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
use Utopia\Locale\Locale;
use Auth\Auth;
use Auth\Validator\Password;
use Database\Database;
use Database\Document;
use Database\Validator\UID;
use Database\Validator\Authorization;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\Password;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Exception\Duplicate;
use Appwrite\Database\Validator\UID;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Template\Template;
use Appwrite\OpenSSL\OpenSSL;
use DeviceDetector\DeviceDetector;
use GeoIp2\Database\Reader;
use Template\Template;
use OpenSSL\OpenSSL;
include_once __DIR__ . '/../shared/api.php';
@ -88,21 +89,25 @@ $utopia->post('/v1/account')
Authorization::disable();
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::enable();
@ -259,7 +264,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider')
throw new Exception('Provider is undefined, configure provider app ID and app secret key to continue', 412);
}
$classname = 'Auth\\OAuth2\\'.ucfirst($provider);
$classname = 'Appwrite\\Auth\\OAuth2\\'.ucfirst($provider);
if (!class_exists($classname)) {
throw new Exception('Provider is not supported', 501);
@ -314,7 +319,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
$appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, hex2bin($appSecret['iv']), hex2bin($appSecret['tag']));
}
$classname = 'Auth\\OAuth2\\'.ucfirst($provider);
$classname = 'Appwrite\\Auth\\OAuth2\\'.ucfirst($provider);
if (!class_exists($classname)) {
throw new Exception('Provider is not supported', 501);
@ -391,18 +396,22 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
if (!$user || empty($user->getId())) { // Last option -> create user alone, generate random password
Authorization::disable();
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => ['read' => ['*'], 'write' => ['user:{self}']],
'email' => $email,
'emailVerification' => true,
'status' => Auth::USER_STATUS_ACTIVATED, // Email should already be authenticated by OAuth2 provider
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => ['read' => ['*'], 'write' => ['user:{self}']],
'email' => $email,
'emailVerification' => true,
'status' => Auth::USER_STATUS_ACTIVATED, // Email should already be authenticated by OAuth2 provider
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::enable();
@ -476,6 +485,7 @@ $utopia->get('/v1/account')
[
'$id',
'email',
'emailVerification',
'registration',
'name',
],

View file

@ -9,7 +9,7 @@ use Utopia\Validator\Range;
use Utopia\Validator\URL;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Resize\Resize;
use Appwrite\Resize\Resize;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;

View file

@ -9,15 +9,15 @@ use Utopia\Validator\Range;
use Utopia\Validator\WhiteList;
use Utopia\Validator\Text;
use Utopia\Validator\ArrayList;
use Database\Database;
use Database\Document;
use Database\Validator\UID;
use Database\Validator\Key;
use Database\Validator\Structure;
use Database\Validator\Collection;
use Database\Validator\Authorization;
use Database\Exception\Authorization as AuthorizationException;
use Database\Exception\Structure as StructureException;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\UID;
use Appwrite\Database\Validator\Key;
use Appwrite\Database\Validator\Structure;
use Appwrite\Database\Validator\Collection;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Exception\Authorization as AuthorizationException;
use Appwrite\Database\Exception\Structure as StructureException;
include_once __DIR__ . '/../shared/api.php';
@ -282,7 +282,7 @@ $utopia->post('/v1/database/collections/:collectionId/documents')
->label('sdk.method', 'createDocument')
->label('sdk.description', '/docs/references/database/create-document.md')
->param('collectionId', null, function () { return new UID(); }, 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/database?platform=server#createCollection).')
->param('data', [], function () { return new \Utopia\Validator\Mock(); }, 'Document data as JSON string.')
->param('data', [], function () { return new \Utopia\Validator\Mock(); }, 'Document data as JSON object.')
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('parentDocument', '', function () { return new UID(); }, 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
@ -502,7 +502,7 @@ $utopia->patch('/v1/database/collections/:collectionId/documents/:documentId')
->label('sdk.description', '/docs/references/database/update-document.md')
->param('collectionId', null, function () { return new UID(); }, 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/database?platform=server#createCollection).')
->param('documentId', null, function () { return new UID(); }, 'Document unique ID.')
->param('data', [], function () { return new \Utopia\Validator\Mock(); }, 'Document data as JSON string.')
->param('data', [], function () { return new \Utopia\Validator\Mock(); }, 'Document data as JSON object.')
->param('read', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', [], function () { return new ArrayList(new Text(64)); }, 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->action(

View file

@ -3,8 +3,8 @@
global $utopia, $request, $response, $register, $project;
use Utopia\Exception;
use Storage\Devices\Local;
use Storage\Storage;
use Appwrite\Storage\Devices\Local;
use Appwrite\Storage\Storage;
use Appwrite\ClamAV\Network;
$utopia->get('/v1/health')

View file

@ -2,7 +2,6 @@
global $utopia, $request, $response, $register, $user, $consoleDB, $projectDB, $providers;
use Auth\Auth;
use Utopia\Exception;
use Utopia\Response;
use Utopia\Validator\ArrayList;
@ -12,13 +11,14 @@ use Utopia\Validator\WhiteList;
use Utopia\Validator\Range;
use Utopia\Validator\URL;
use Utopia\Domains\Domain;
use Task\Validator\Cron;
use Database\Database;
use Database\Document;
use Database\Validator\UID;
use OpenSSL\OpenSSL;
use Appwrite\Auth\Auth;
use Appwrite\Task\Validator\Cron;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\UID;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Network\Validators\CNAME;
use Cron\CronExpression;
use Network\Validators\CNAME;
include_once __DIR__ . '/../shared/api.php';
@ -1383,24 +1383,4 @@ $utopia->delete('/v1/projects/:projectId/domains/:domainId')
$response->noContent();
}
);
$utopia->get('/v1/projects/x/certs')
->desc('List Domains')
->label('scope', 'public')
->action(
function () use ($response, $consoleDB) {
\Database\Validator\Authorization::disable();
$results = $consoleDB->getCollection([
'limit' => 2000,
'offset' => 0,
'filters' => [
'$collection='.Database::SYSTEM_COLLECTION_USERS,
],
]);
\Database\Validator\Authorization::reset();
$response->json($results);
}
);

View file

@ -12,16 +12,16 @@ use Utopia\Validator\HexColor;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Appwrite\ClamAV\Network;
use Database\Database;
use Database\Validator\UID;
use Storage\Storage;
use Storage\Devices\Local;
use Storage\Validators\File;
use Storage\Validators\FileSize;
use Storage\Validators\Upload;
use Storage\Compression\Algorithms\GZIP;
use Resize\Resize;
use OpenSSL\OpenSSL;
use Appwrite\Database\Database;
use Appwrite\Database\Validator\UID;
use Appwrite\Storage\Storage;
use Appwrite\Storage\Devices\Local;
use Appwrite\Storage\Validators\File;
use Appwrite\Storage\Validators\FileSize;
use Appwrite\Storage\Validators\Upload;
use Appwrite\Storage\Compression\Algorithms\GZIP;
use Appwrite\Resize\Resize;
use Appwrite\OpenSSL\OpenSSL;
include_once __DIR__ . '/../shared/api.php';

View file

@ -11,12 +11,13 @@ use Utopia\Validator\Range;
use Utopia\Validator\ArrayList;
use Utopia\Validator\WhiteList;
use Utopia\Locale\Locale;
use Database\Database;
use Database\Document;
use Database\Validator\UID;
use Database\Validator\Authorization;
use Template\Template;
use Auth\Auth;
use Appwrite\Auth\Auth;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\UID;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Exception\Duplicate;
use Appwrite\Template\Template;
include_once __DIR__ . '/../shared/api.php';
@ -243,22 +244,26 @@ $utopia->post('/v1/teams/:teamId/memberships')
Authorization::disable();
$invitee = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['user:{self}', '*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
'tokens' => [],
]);
try {
$invitee = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['user:{self}', '*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
'tokens' => [],
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::reset();

View file

@ -2,8 +2,6 @@
global $utopia, $response, $projectDB, $providers;
use Auth\Auth;
use Auth\Validator\Password;
use Utopia\Exception;
use Utopia\Response;
use Utopia\Validator\Assoc;
@ -14,8 +12,11 @@ use Utopia\Validator\Range;
use Utopia\Audit\Audit;
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
use Utopia\Locale\Locale;
use Database\Database;
use Database\Validator\UID;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\Password;
use Appwrite\Database\Database;
use Appwrite\Database\Exception\Duplicate;
use Appwrite\Database\Validator\UID;
use DeviceDetector\DeviceDetector;
use GeoIp2\Database\Reader;
@ -46,21 +47,25 @@ $utopia->post('/v1/users')
throw new Exception('User already registered', 409);
}
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'emailVerification' => false,
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
$oauth2Keys = [];

View file

@ -5,9 +5,9 @@ global $utopia, $request, $response;
use Utopia\Validator\Numeric;
use Utopia\Validator\Text;
use Utopia\Validator\ArrayList;
use Storage\Validators\File;
use Utopia\Response;
use Utopia\Validator\Host;
use Appwrite\Storage\Validators\File;
$result = [];

View file

@ -6,9 +6,9 @@ global $utopia, $response, $request, $layout, $version, $providers, $projectDB;
use Utopia\View;
use Utopia\Domains\Domain;
use Database\Database;
use Database\Validator\UID;
use Storage\Storage;
use Appwrite\Database\Database;
use Appwrite\Database\Validator\UID;
use Appwrite\Storage\Storage;
$utopia->init(function () use ($layout, $utopia) {
$layout

View file

@ -5,7 +5,7 @@ USE `appwrite`;
CREATE TABLE IF NOT EXISTS `template.abuse.abuse` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`_key` varchar(255) NOT NULL,
`_time` varchar(45) NOT NULL,
`_time` int(11) NOT NULL,
`_count` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `unique1` (`_key`,`_time`),
@ -15,7 +15,6 @@ CREATE TABLE IF NOT EXISTS `template.abuse.abuse` (
CREATE TABLE IF NOT EXISTS `template.audit.audit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userId` varchar(45) NOT NULL,
`userType` int(11) NOT NULL,
`event` varchar(45) NOT NULL,
`resource` varchar(45) DEFAULT NULL,
`userAgent` text NOT NULL,
@ -25,7 +24,7 @@ CREATE TABLE IF NOT EXISTS `template.audit.audit` (
`data` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `index_1` (`userId`,`userType`),
KEY `index_1` (`userId`),
KEY `index_2` (`event`),
KEY `index_3` (`resource`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@ -74,10 +73,18 @@ CREATE TABLE IF NOT EXISTS `template.database.relationships` (
KEY `relationships_end_nodes_id_idx` (`end`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `template.database.unique` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index1` (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/* Default App */
CREATE TABLE IF NOT EXISTS `app_console.database.documents` LIKE `template.database.documents`;
CREATE TABLE IF NOT EXISTS `app_console.database.properties` LIKE `template.database.properties`;
CREATE TABLE IF NOT EXISTS `app_console.database.relationships` LIKE `template.database.relationships`;
CREATE TABLE IF NOT EXISTS `app_console.database.unique` LIKE `template.database.unique`;
CREATE TABLE IF NOT EXISTS `app_console.audit.audit` LIKE `template.audit.audit`;
CREATE TABLE IF NOT EXISTS `app_console.abuse.abuse` LIKE `template.abuse.abuse`;

View file

@ -1,6 +1,12 @@
<?php
// Init
/**
* Init
*
* Inializes both Appwrite API entry point, queue workers, and CLI tasks.
* Set configuration, framework resources, app constants
*
*/
if (file_exists(__DIR__.'/../vendor/autoload.php')) {
require_once __DIR__.'/../vendor/autoload.php';
}
@ -8,14 +14,14 @@ if (file_exists(__DIR__.'/../vendor/autoload.php')) {
use Utopia\App;
use Utopia\Request;
use Utopia\Response;
use Auth\Auth;
use Database\Database;
use Database\Document;
use Database\Validator\Authorization;
use Database\Adapter\MySQL as MySQLAdapter;
use Database\Adapter\Redis as RedisAdapter;
use Utopia\Locale\Locale;
use Utopia\Registry\Registry;
use Appwrite\Auth\Auth;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Adapter\MySQL as MySQLAdapter;
use Appwrite\Database\Adapter\Redis as RedisAdapter;
use PHPMailer\PHPMailer\PHPMailer;
const APP_NAME = 'Appwrite';
@ -26,7 +32,7 @@ const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 15;
const APP_CACHE_BUSTER = 69;
const APP_VERSION_STABLE = '0.5.0';
const APP_VERSION_STABLE = '0.5.3';
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_CERTIFICATES = '/storage/certificates';

View file

@ -1,7 +1,7 @@
# Appwrite SDK for JavaScript
![License](https://img.shields.io/github/license/appwrite/sdk-for-console.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
@ -33,6 +33,10 @@ To install with a CDN (content delivery network) add the following scripts to th
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -1,7 +1,7 @@
# Appwrite SDK for Dart
![License](https://img.shields.io/github/license/appwrite/sdk-for-dart.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
**This SDK is compatible with Appwrite server version . For older versions, please check previous releases.**
@ -17,7 +17,7 @@ Add this to your package's pubspec.yaml file:
```yml
dependencies:
appwrite: ^0.0.6
appwrite: ^0.0.7
```
You can install packages from the command line:
@ -26,6 +26,10 @@ You can install packages from the command line:
pub get
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -2,6 +2,8 @@ import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'enums.dart';
class Client {
String endPoint;
Map<String, String> headers;
@ -12,7 +14,7 @@ class Client {
this.endPoint = 'https://appwrite.io/v1';
this.headers = {
'content-type': 'application/json',
'x-sdk-version': 'appwrite:dart:0.0.6',
'x-sdk-version': 'appwrite:dart:0.0.7',
};
this.selfSigned = false;
@ -71,18 +73,18 @@ class Client {
return this;
}
Future<Response> call(String method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}}) {
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}}) {
if(this.selfSigned) {
// Allow self signed requests
}
String reqPath = path;
bool isGet = method.toUpperCase() == "GET";
bool isGet = method == HttpMethod.get;
// Origin is hardcoded for testing
Options options = Options(
headers: {...this.headers, ...headers, "Origin": "http://localhost"},
method: method.toUpperCase(),
method: method.name(),
);
if (isGet) {

View file

@ -0,0 +1,9 @@
enum HttpMethod {
get, post, put, delete, patch
}
extension HttpMethodString on HttpMethod{
String name(){
return this.toString().split('.').last.toUpperCase();
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Account extends Service {
@ -13,7 +18,7 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Use this endpoint to allow a new user to register a new account in your
/// project. After the user registration completes successfully, you can use
@ -21,7 +26,7 @@ class Account extends Service {
/// verifying the user email address. To allow your new user to login to his
/// new account, you need to create a new [account
/// session](/docs/account#createSession).
Future<Response> create({email, password, name = null}) async {
Future<Response> create({@required String email, @required String password, String name = null}) async {
String path = '/account';
Map<String, dynamic> params = {
@ -30,7 +35,7 @@ class Account extends Service {
'name': name,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Delete a currently logged in user account. Behind the scene, the user
/// record is not deleted but permanently blocked from any access. This is done
@ -43,13 +48,13 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Update currently logged in user account email address. After changing user
/// address, user confirmation status is being reset and a new confirmation
/// mail is sent. For security measures, user password is required to complete
/// this request.
Future<Response> updateEmail({email, password}) async {
Future<Response> updateEmail({@required String email, @required String password}) async {
String path = '/account/email';
Map<String, dynamic> params = {
@ -57,7 +62,7 @@ class Account extends Service {
'password': password,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Get currently logged in user list of latest security activity logs. Each
/// log returns user IP address, location and date and time of log.
@ -67,21 +72,21 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Update currently logged in user account name.
Future<Response> updateName({name}) async {
Future<Response> updateName({@required String name}) async {
String path = '/account/name';
Map<String, dynamic> params = {
'name': name,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Update currently logged in user password. For validation, user is required
/// to pass the password twice.
Future<Response> updatePassword({password, oldPassword}) async {
Future<Response> updatePassword({@required String password, @required String oldPassword}) async {
String path = '/account/password';
Map<String, dynamic> params = {
@ -89,7 +94,7 @@ class Account extends Service {
'old-password': oldPassword,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Get currently logged in user preferences as a key-value object.
Future<Response> getPrefs() async {
@ -98,18 +103,18 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Update currently logged in user account preferences. You can pass only the
/// specific settings you wish to update.
Future<Response> updatePrefs({prefs}) async {
Future<Response> updatePrefs({@required dynamic prefs}) async {
String path = '/account/prefs';
Map<String, dynamic> params = {
'prefs': prefs,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Sends the user an email with a temporary secret key for password reset.
/// When the user clicks the confirmation link he is redirected back to your
@ -117,7 +122,7 @@ class Account extends Service {
/// attached to the URL query string. Use the query string params to submit a
/// request to the [PUT /account/recovery](/docs/account#updateRecovery)
/// endpoint to complete the process.
Future<Response> createRecovery({email, url}) async {
Future<Response> createRecovery({@required String email, @required String url}) async {
String path = '/account/recovery';
Map<String, dynamic> params = {
@ -125,7 +130,7 @@ class Account extends Service {
'url': url,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Use this endpoint to complete the user account password reset. Both the
/// **userId** and **secret** arguments will be passed as query parameters to
@ -136,7 +141,7 @@ class Account extends Service {
/// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URLs are the ones from domains you have set when
/// adding your platforms in the console interface.
Future<Response> updateRecovery({userId, secret, passwordA, passwordB}) async {
Future<Response> updateRecovery({@required String userId, @required String secret, @required String passwordA, @required String passwordB}) async {
String path = '/account/recovery';
Map<String, dynamic> params = {
@ -146,7 +151,7 @@ class Account extends Service {
'password-b': passwordB,
};
return await this.client.call('put', path: path, params: params);
return await this.client.call(HttpMethod.put, path: path, params: params);
}
/// Get currently logged in user list of active sessions across different
/// devices.
@ -156,11 +161,11 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Allow the user to login into his account by providing a valid email and
/// password combination. This route will create a new session for the user.
Future<Response> createSession({email, password}) async {
Future<Response> createSession({@required String email, @required String password}) async {
String path = '/account/sessions';
Map<String, dynamic> params = {
@ -168,7 +173,7 @@ class Account extends Service {
'password': password,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Delete all sessions from the user account and remove any sessions cookies
/// from the end client.
@ -178,13 +183,13 @@ class Account extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Allow the user to login to his account using the OAuth2 provider of his
/// choice. Each OAuth2 provider should be enabled from the Appwrite console
/// first. Use the success and failure arguments to provide a redirect URL's
/// back to your app when login is completed.
Future<Response> createOAuth2Session({provider, success, failure}) async {
Future<Response> createOAuth2Session({@required String provider, @required String success, @required String failure}) async {
String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider);
Map<String, dynamic> params = {
@ -192,18 +197,18 @@ class Account extends Service {
'failure': failure,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Use this endpoint to log out the currently logged in user from all his
/// account sessions across all his different devices. When using the option id
/// argument, only the session unique ID provider will be deleted.
Future<Response> deleteSession({sessionId}) async {
Future<Response> deleteSession({@required String sessionId}) async {
String path = '/account/sessions/{sessionId}'.replaceAll(RegExp('{sessionId}'), sessionId);
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Use this endpoint to send a verification message to your user email address
/// to confirm they are the valid owners of that address. Both the **userId**
@ -218,20 +223,20 @@ class Account extends Service {
/// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URLs are the ones from domains you have set when
/// adding your platforms in the console interface.
Future<Response> createVerification({url}) async {
Future<Response> createVerification({@required String url}) async {
String path = '/account/verification';
Map<String, dynamic> params = {
'url': url,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Use this endpoint to complete the user email verification process. Use both
/// the **userId** and **secret** parameters that were attached to your app URL
/// to verify the user email ownership. If confirmed this route will return a
/// 200 status code.
Future<Response> updateVerification({userId, secret}) async {
Future<Response> updateVerification({@required String userId, @required String secret}) async {
String path = '/account/verification';
Map<String, dynamic> params = {
@ -239,6 +244,6 @@ class Account extends Service {
'secret': secret,
};
return await this.client.call('put', path: path, params: params);
return await this.client.call(HttpMethod.put, path: path, params: params);
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Avatars extends Service {
@ -10,7 +15,7 @@ class Avatars extends Service {
/// The code argument receives the browser code as it appears in your user
/// /account/sessions endpoint. Use width, height and quality arguments to
/// change the output settings.
Future<Response> getBrowser({code, width = 100, height = 100, quality = 100}) async {
Future<Response> getBrowser({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
@ -19,13 +24,13 @@ class Avatars extends Service {
'quality': quality,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Need to display your users with your billing method or their payment
/// methods? The credit card endpoint will return you the icon of the credit
/// card provider you need. Use width, height and quality arguments to change
/// the output settings.
Future<Response> getCreditCard({code, width = 100, height = 100, quality = 100}) async {
Future<Response> getCreditCard({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
@ -34,23 +39,23 @@ class Avatars extends Service {
'quality': quality,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Use this endpoint to fetch the favorite icon (AKA favicon) of a any remote
/// website URL.
Future<Response> getFavicon({url}) async {
Future<Response> getFavicon({@required String url}) async {
String path = '/avatars/favicon';
Map<String, dynamic> params = {
'url': url,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// You can use this endpoint to show different country flags icons to your
/// users. The code argument receives the 2 letter country code. Use width,
/// height and quality arguments to change the output settings.
Future<Response> getFlag({code, width = 100, height = 100, quality = 100}) async {
Future<Response> getFlag({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
@ -59,13 +64,13 @@ class Avatars extends Service {
'quality': quality,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Use this endpoint to fetch a remote image URL and crop it to any image size
/// you want. This endpoint is very useful if you need to crop and display
/// remote images in your app or in case you want to make sure a 3rd party
/// image is properly served using a TLS protocol.
Future<Response> getImage({url, width = 400, height = 400}) async {
Future<Response> getImage({@required String url, int width = 400, int height = 400}) async {
String path = '/avatars/image';
Map<String, dynamic> params = {
@ -74,11 +79,11 @@ class Avatars extends Service {
'height': height,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Converts a given plain text to a QR code image. You can use the query
/// parameters to change the size and style of the resulting image.
Future<Response> getQR({text, size = 400, margin = 1, download = null}) async {
Future<Response> getQR({@required String text, int size = 400, int margin = 1, int download = null}) async {
String path = '/avatars/qr';
Map<String, dynamic> params = {
@ -88,6 +93,6 @@ class Avatars extends Service {
'download': download,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Database extends Service {
@ -10,7 +15,7 @@ class Database extends Service {
/// filter your results. On admin mode, this endpoint will return a list of all
/// of the project documents. [Learn more about different API
/// modes](/docs/admin).
Future<Response> listDocuments({collectionId, filters = const [], offset = null, limit = 50, orderField = '\$id', orderType = 'ASC', orderCast = 'string', search = null, first = null, last = null}) async {
Future<Response> listDocuments({@required String collectionId, List filters = const [], int offset = null, int limit = 50, String orderField = '\$id', String orderType = 'ASC', String orderCast = 'string', String search = null, int first = null, int last = null}) async {
String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
Map<String, dynamic> params = {
@ -25,10 +30,10 @@ class Database extends Service {
'last': last,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Create a new Document.
Future<Response> createDocument({collectionId, data, read, write, parentDocument = null, parentProperty = null, parentPropertyType = 'assign'}) async {
Future<Response> createDocument({@required String collectionId, @required dynamic data, @required List read, @required List write, String parentDocument = null, String parentProperty = null, String parentPropertyType = 'assign'}) async {
String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
Map<String, dynamic> params = {
@ -40,19 +45,19 @@ class Database extends Service {
'parentPropertyType': parentPropertyType,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Get document by its unique ID. This endpoint response returns a JSON object
/// with the document data.
Future<Response> getDocument({collectionId, documentId}) async {
Future<Response> getDocument({@required String collectionId, @required String documentId}) async {
String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
Future<Response> updateDocument({collectionId, documentId, data, read, write}) async {
Future<Response> updateDocument({@required String collectionId, @required String documentId, @required dynamic data, @required List read, @required List write}) async {
String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
@ -61,17 +66,17 @@ class Database extends Service {
'write': write,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Delete document by its unique ID. This endpoint deletes only the parent
/// documents, his attributes and relations to other documents. Child documents
/// **will not** be deleted.
Future<Response> deleteDocument({collectionId, documentId}) async {
Future<Response> deleteDocument({@required String collectionId, @required String documentId}) async {
String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Locale extends Service {
@ -18,7 +23,7 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// List of all continents. You can use the locale header to get the data in a
/// supported language.
@ -28,7 +33,7 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// List of all countries. You can use the locale header to get the data in a
/// supported language.
@ -38,7 +43,7 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// List of all countries that are currently members of the EU. You can use the
/// locale header to get the data in a supported language.
@ -48,7 +53,7 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// List of all countries phone codes. You can use the locale header to get the
/// data in a supported language.
@ -58,7 +63,7 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// List of all currencies, including currency symol, name, plural, and decimal
/// digits for all major and minor currencies. You can use the locale header to
@ -69,6 +74,6 @@ class Locale extends Service {
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Storage extends Service {
@ -9,7 +14,7 @@ class Storage extends Service {
/// Get a list of all the user files. You can use the query params to filter
/// your results. On admin mode, this endpoint will return a list of all of the
/// project files. [Learn more about different API modes](/docs/admin).
Future<Response> listFiles({search = null, limit = 25, offset = null, orderType = 'ASC'}) async {
Future<Response> listFiles({String search = null, int limit = 25, int offset = null, String orderType = 'ASC'}) async {
String path = '/storage/files';
Map<String, dynamic> params = {
@ -19,12 +24,12 @@ class Storage extends Service {
'orderType': orderType,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Create a new file. The user who creates the file will automatically be
/// assigned to read and write access unless he has passed custom values for
/// read and write arguments.
Future<Response> createFile({file, read, write}) async {
Future<Response> createFile({@required File file, @required List read, @required List write}) async {
String path = '/storage/files';
Map<String, dynamic> params = {
@ -33,21 +38,21 @@ class Storage extends Service {
'write': write,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Get file by its unique ID. This endpoint response returns a JSON object
/// with the file metadata.
Future<Response> getFile({fileId}) async {
Future<Response> getFile({@required String fileId}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Update file by its unique ID. Only users with write permissions have access
/// to update this resource.
Future<Response> updateFile({fileId, read, write}) async {
Future<Response> updateFile({@required String fileId, @required List read, @required List write}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
@ -55,34 +60,34 @@ class Storage extends Service {
'write': write,
};
return await this.client.call('put', path: path, params: params);
return await this.client.call(HttpMethod.put, path: path, params: params);
}
/// Delete a file by its unique ID. Only users with write permissions have
/// access to delete this resource.
Future<Response> deleteFile({fileId}) async {
Future<Response> deleteFile({@required String fileId}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Get file content by its unique ID. The endpoint response return with a
/// 'Content-Disposition: attachment' header that tells the browser to start
/// downloading the file to user downloads directory.
Future<Response> getFileDownload({fileId}) async {
Future<Response> getFileDownload({@required String fileId}) async {
String path = '/storage/files/{fileId}/download'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Get a file preview image. Currently, this method supports preview for image
/// files (jpg, png, and gif), other supported formats, like pdf, docs, slides,
/// and spreadsheets, will return the file icon image. You can also pass query
/// string arguments for cutting and resizing your preview image.
Future<Response> getFilePreview({fileId, width = null, height = null, quality = 100, background = null, output = null}) async {
Future<Response> getFilePreview({@required String fileId, int width = null, int height = null, int quality = 100, String background = null, String output = null}) async {
String path = '/storage/files/{fileId}/preview'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
@ -93,17 +98,17 @@ class Storage extends Service {
'output': output,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Get file content by its unique ID. This endpoint is similar to the download
/// method but returns with no 'Content-Disposition: attachment' header.
Future<Response> getFileView({fileId, as = null}) async {
Future<Response> getFileView({@required String fileId, String as = null}) async {
String path = '/storage/files/{fileId}/view'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
'as': as,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,6 +1,11 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import '../enums.dart';
class Teams extends Service {
@ -9,7 +14,7 @@ class Teams extends Service {
/// Get a list of all the current user teams. You can use the query params to
/// filter your results. On admin mode, this endpoint will return a list of all
/// of the project teams. [Learn more about different API modes](/docs/admin).
Future<Response> list({search = null, limit = 25, offset = null, orderType = 'ASC'}) async {
Future<Response> list({String search = null, int limit = 25, int offset = null, String orderType = 'ASC'}) async {
String path = '/teams';
Map<String, dynamic> params = {
@ -19,13 +24,13 @@ class Teams extends Service {
'orderType': orderType,
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Create a new team. The user who creates the team will automatically be
/// assigned as the owner of the team. The team owner can invite new members,
/// who will be able add new owners and update or delete the team from your
/// project.
Future<Response> create({name, roles = const ["owner"]}) async {
Future<Response> create({@required String name, List roles = const ["owner"]}) async {
String path = '/teams';
Map<String, dynamic> params = {
@ -33,48 +38,48 @@ class Teams extends Service {
'roles': roles,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// Get team by its unique ID. All team members have read access for this
/// resource.
Future<Response> get({teamId}) async {
Future<Response> get({@required String teamId}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Update team by its unique ID. Only team owners have write access for this
/// resource.
Future<Response> update({teamId, name}) async {
Future<Response> update({@required String teamId, @required String name}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
'name': name,
};
return await this.client.call('put', path: path, params: params);
return await this.client.call(HttpMethod.put, path: path, params: params);
}
/// Delete team by its unique ID. Only team owners have write access for this
/// resource.
Future<Response> delete({teamId}) async {
Future<Response> delete({@required String teamId}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Get team members by the team unique ID. All team members have read access
/// for this list of resources.
Future<Response> getMemberships({teamId}) async {
Future<Response> getMemberships({@required String teamId}) async {
String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
return await this.client.call('get', path: path, params: params);
return await this.client.call(HttpMethod.get, path: path, params: params);
}
/// Use this endpoint to invite a new member to join your team. An email with a
/// link to join the team will be sent to the new member email address if the
@ -89,7 +94,7 @@ class Teams extends Service {
/// Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URL's are the once from domains you have set when
/// added your platforms in the console interface.
Future<Response> createMembership({teamId, email, roles, url, name = null}) async {
Future<Response> createMembership({@required String teamId, @required String email, @required List roles, @required String url, String name = null}) async {
String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
@ -99,23 +104,23 @@ class Teams extends Service {
'url': url,
};
return await this.client.call('post', path: path, params: params);
return await this.client.call(HttpMethod.post, path: path, params: params);
}
/// This endpoint allows a user to leave a team or for a team owner to delete
/// the membership of any other team member. You can also use this endpoint to
/// delete a user membership even if he didn't accept it.
Future<Response> deleteMembership({teamId, inviteId}) async {
Future<Response> deleteMembership({@required String teamId, @required String inviteId}) async {
String path = '/teams/{teamId}/memberships/{inviteId}'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
Map<String, dynamic> params = {
};
return await this.client.call('delete', path: path, params: params);
return await this.client.call(HttpMethod.delete, path: path, params: params);
}
/// Use this endpoint to allow a user to accept an invitation to join a team
/// after he is being redirected back to your app from the invitation email he
/// was sent.
Future<Response> updateMembershipStatus({teamId, inviteId, userId, secret}) async {
Future<Response> updateMembershipStatus({@required String teamId, @required String inviteId, @required String userId, @required String secret}) async {
String path = '/teams/{teamId}/memberships/{inviteId}/status'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
Map<String, dynamic> params = {
@ -123,6 +128,6 @@ class Teams extends Service {
'secret': secret,
};
return await this.client.call('patch', path: path, params: params);
return await this.client.call(HttpMethod.patch, path: path, params: params);
}
}

View file

@ -1,10 +1,10 @@
name: appwrite
version: 0.0.6
version: 0.0.7
description: Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
author: Appwrite Team <team@localhost.test>
author: Appwrite Team <team@appwrite.io>
homepage: https://github.com/appwrite/sdk-for-dart
environment:
sdk: '>=2.2.2 <3.0.0'
sdk: '>=2.6.0 <3.0.0'
dependencies:
dio: ^3.0.0
cookie_jar: ^1.0.0

View file

@ -1,7 +1,7 @@
# Appwrite SDK for Go
![License](https://img.shields.io/github/license/appwrite/sdk-for-go.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
**This SDK is compatible with Appwrite server version . For older versions, please check previous releases.**
@ -19,6 +19,10 @@ To install using `go get`:
go get github.com/appwrite/sdk-for-go
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -1,7 +1,7 @@
# Appwrite SDK for NodeJS
![License](https://img.shields.io/github/license/appwrite/sdk-for-node.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
@ -17,6 +17,10 @@ To install via [NPM](https://www.npmjs.com/):
npm install node-appwrite --save
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -7,7 +7,7 @@ class Client {
this.endpoint = 'https://appwrite.io/v1';
this.headers = {
'content-type': '',
'x-sdk-version': 'appwrite:nodejs:1.0.31',
'x-sdk-version': 'appwrite:nodejs:1.0.32',
};
this.selfSigned = false;
}

View file

@ -2,7 +2,7 @@
"name": "node-appwrite",
"homepage": "https://appwrite.io/support",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)",
"version": "1.0.31",
"version": "1.0.32",
"license": "BSD-3-Clause",
"main": "index.js",
"repository": {

View file

@ -1,7 +1,7 @@
# Appwrite SDK for PHP
![License](https://img.shields.io/github/license/appwrite/sdk-for-php.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
@ -17,6 +17,10 @@ To install via [Composer](http://getcomposer.org/):
composer require appwrite/appwrite
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -5,7 +5,7 @@
"license": "BSD-3-Clause",
"support": {
"url": "https://appwrite.io/support",
"email": "team@localhost.test"
"email": "team@appwrite.io"
},
"autoload": {
"psr-4": {

View file

@ -116,7 +116,7 @@ POST https://appwrite.io/v1/database/collections/{collectionId}/documents
| Field Name | Type | Description | Default |
| --- | --- | --- | --- |
| collectionId | string | **Required** Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/database?platform=server#createCollection). | |
| data | object | Document data as JSON string. | |
| data | object | Document data as JSON object. | |
| read | array | An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions. | |
| write | array | An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions. | |
| parentDocument | string | Parent document unique ID. Use when you want your new document to be a child of a parent document. | |
@ -150,7 +150,7 @@ PATCH https://appwrite.io/v1/database/collections/{collectionId}/documents/{docu
| --- | --- | --- | --- |
| collectionId | string | **Required** Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/database?platform=server#createCollection). | |
| documentId | string | **Required** Document unique ID. | |
| data | object | Document data as JSON string. | |
| data | object | Document data as JSON object. | |
| read | array | An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions. | |
| write | array | An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions. | |

View file

@ -37,7 +37,7 @@ class Client
*/
protected $headers = [
'content-type' => '',
'x-sdk-version' => 'appwrite:php:1.0.16',
'x-sdk-version' => 'appwrite:php:1.0.17',
];
/**

View file

@ -1,7 +1,7 @@
# Appwrite SDK for Python
![License](https://img.shields.io/github/license/appwrite/sdk-for-python.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
**This SDK is compatible with Appwrite server version . For older versions, please check previous releases.**
@ -19,6 +19,10 @@ To install via [PyPI](https://pypi.org/):
pip install appwrite
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -7,7 +7,7 @@ class Client:
self._endpoint = 'https://appwrite.io/v1'
self._global_headers = {
'content-type': '',
'x-sdk-version': 'appwrite:python:0.0.3',
'x-sdk-version': 'appwrite:python:0.0.4',
}
def set_self_signed(self, status=True):

View file

@ -3,15 +3,15 @@ import setuptools
setuptools.setup(
name = 'appwrite',
packages = ['appwrite', 'appwrite/services'],
version = '0.0.3',
version = '0.0.4',
license='BSD-3-Clause',
description = 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)',
author = 'Appwrite Team',
author_email = 'team@localhost.test',
author_email = 'team@appwrite.io',
maintainer = 'Appwrite Team',
maintainer_email = 'team@localhost.test',
maintainer_email = 'team@appwrite.io',
url = 'https://appwrite.io/support',
download_url='https://github.com/appwrite/sdk-for-python/archive/0.0.3.tar.gz',
download_url='https://github.com/appwrite/sdk-for-python/archive/0.0.4.tar.gz',
# keywords = ['SOME', 'MEANINGFULL', 'KEYWORDS'],
install_requires=[
'requests',

View file

@ -1,7 +1,7 @@
# Appwrite SDK for Ruby
![License](https://img.shields.io/github/license/appwrite/sdk-for-ruby.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
**This SDK is compatible with Appwrite server version . For older versions, please check previous releases.**
@ -19,6 +19,10 @@ To install via [Gem](https://rubygems.org/):
gem install appwrite --save
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -1,11 +1,11 @@
Gem::Specification.new do |s|
s.name = 'appwrite'
s.version = '1.0.8'
s.version = '1.0.9'
s.summary = "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)"
s.author = 'Appwrite Team'
s.homepage = 'https://appwrite.io/support'
s.email = 'team@localhost.test'
s.email = 'team@appwrite.io'
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
end

View file

@ -20,7 +20,7 @@ module Appwrite
@headers = {
'content-type' => '',
'user-agent' => RUBY_PLATFORM + ':ruby-' + RUBY_VERSION,
'x-sdk-version' => 'appwrite:ruby:1.0.8'
'x-sdk-version' => 'appwrite:ruby:1.0.9'
}
@endpoint = 'https://appwrite.io/v1';
end

View file

@ -1,7 +1,7 @@
# Appwrite SDK for JavaScript
![License](https://img.shields.io/github/license/appwrite/sdk-for-js.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.0-blue.svg?v=1)
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
@ -28,11 +28,15 @@ import * as Appwrite from "appwrite";
To install with a CDN (content delivery network) add the following scripts to the bottom of your <body> tag, but before you use any Appwrite services:
```html
<script src="https://cdn.jsdelivr.net/npm/appwrite@1.0.28"></script>
<script src="https://cdn.jsdelivr.net/npm/appwrite@1.0.29"></script>
```
## Contribution
This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request.
## License
Please see the [BSD-3-Clause license](https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE) file for more information.

View file

@ -2,7 +2,7 @@
"name": "appwrite",
"homepage": "https://appwrite.io/support",
"description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)",
"version": "1.0.28",
"version": "1.0.29",
"license": "BSD-3-Clause",
"main": "src/sdk.js",
"repository": {

View file

@ -139,7 +139,7 @@
globalParams.push({key: key, value: value});
};
addGlobalHeader('x-sdk-version', 'appwrite:javascript:1.0.28');
addGlobalHeader('x-sdk-version', 'appwrite:javascript:1.0.29');
addGlobalHeader('content-type', '');
/**

View file

@ -1,5 +1,5 @@
(function(window){'use strict';window.Appwrite=function(){let config={endpoint:'https://appwrite.io/v1',project:'',key:'',locale:'',mode:'',};let setEndpoint=function(endpoint){config.endpoint=endpoint;return this};let setProject=function(value){http.addGlobalHeader('X-Appwrite-Project',value);config.project=value;return this};let setKey=function(value){http.addGlobalHeader('X-Appwrite-Key',value);config.key=value;return this};let setLocale=function(value){http.addGlobalHeader('X-Appwrite-Locale',value);config.locale=value;return this};let setMode=function(value){http.addGlobalHeader('X-Appwrite-Mode',value);config.mode=value;return this};let http=function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&amp;|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href};let buildQuery=function(params){let str=[];for(let p in params){if(Array.isArray(params[p])){for(let index=0;index<params[p].length;index++){let param=params[p][index];str.push(encodeURIComponent(p+'[]')+"="+encodeURIComponent(param))}}else{str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]))}}
return str.join("&")};let addGlobalHeader=function(key,value){globalHeaders[key]={key:key.toLowerCase(),value:value.toLowerCase()}};let addGlobalParam=function(key,value){globalParams.push({key:key,value:value})};addGlobalHeader('x-sdk-version','appwrite:javascript:1.0.28');addGlobalHeader('content-type','');let call=function(method,path,headers={},params={},progress=null){let i;path=config.endpoint+path;if(-1===['GET','POST','PUT','DELETE','TRACE','HEAD','OPTIONS','CONNECT','PATCH'].indexOf(method)){throw new Error('var method must contain a valid HTTP method name')}
return str.join("&")};let addGlobalHeader=function(key,value){globalHeaders[key]={key:key.toLowerCase(),value:value.toLowerCase()}};let addGlobalParam=function(key,value){globalParams.push({key:key,value:value})};addGlobalHeader('x-sdk-version','appwrite:javascript:1.0.29');addGlobalHeader('content-type','');let call=function(method,path,headers={},params={},progress=null){let i;path=config.endpoint+path;if(-1===['GET','POST','PUT','DELETE','TRACE','HEAD','OPTIONS','CONNECT','PATCH'].indexOf(method)){throw new Error('var method must contain a valid HTTP method name')}
if(typeof path!=='string'){throw new Error('var path must be of type string')}
if(typeof headers!=='object'){throw new Error('var headers must be of type object')}
for(i=0;i<globalParams.length;i++){path=addParam(path,globalParams[i].key,globalParams[i].value)}

View file

@ -18,7 +18,7 @@ $cli
Console::log('Issue a TLS certificate for master domain ('.$domain.')');
Resque::enqueue('v1-certificates', 'CertificatesV1', [
ResqueScheduler::enqueueAt(time() + 30, 'v1-certificates', 'CertificatesV1', [
'document' => [],
'domain' => $domain,
'validateTarget' => false,

View file

@ -40,6 +40,7 @@ $cli
$platforms = include __DIR__ . '/../config/platforms.php';
$message = Console::confirm('Please enter your commit message:');
$production = (Console::confirm('Type "Appwrite" to deploy for production') == 'Appwrite');
foreach($platforms as $key => $platform) {
foreach($platform['languages'] as $language) {
@ -50,7 +51,8 @@ $cli
Console::info('Fetching API Spec for '.$language['name'].' for '.$platform['name']);
$spec = getSSLPage('http://localhost/v1/open-api-2.json?extensions=1&platform='.$language['family']);
//$spec = getSSLPage('http://localhost/v1/open-api-2.json?extensions=1&platform='.$language['family']);
$spec = getSSLPage('https://appwrite.io/v1/open-api-2.json?extensions=1&platform='.$language['family']);
$result = realpath(__DIR__.'/..').'/sdks/'.$key.'-'.$language['key'];
$target = realpath(__DIR__.'/..').'/sdks/git/'.$language['key'].'/';
@ -156,7 +158,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
continue;
}
$gitUrl = 'git@github.com:aw-tests/'.$language['gitRepoName'].'.git';
if(!$production) {
$gitUrl = 'git@github.com:aw-tests/'.$language['gitRepoName'].'.git';
}
exec('rm -rf '.$target.' && \
mkdir -p '.$target.' && \

View file

@ -3,13 +3,13 @@
require_once __DIR__.'/../init.php';
global $register, $projectDB, $console, $providers;
global $register, $projectDB, $console, $providers, $request;
use Database\Database;
use Database\Document;
use Database\Validator\Authorization;
use Utopia\CLI\CLI;
use Utopia\CLI\Console;
use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
$cli = new CLI();
$db = $register->get('db');
@ -18,7 +18,7 @@ $callbacks = [
'0.4.0' => function() {
Console::log('I got nothing to do.');
},
'0.5.0' => function($project) use ($db, $projectDB) {
'0.5.0' => function($project) use ($db, $projectDB, $requset) {
Console::info('Upgrading project: '.$project->getId());
@ -64,11 +64,22 @@ $callbacks = [
$offset = $offset + $limit;
}
$schema = (isset($_SERVER['_APP_DB_SCHEMA'])) ? $_SERVER['_APP_DB_SCHEMA'] : '';
try {
$statement = $db->prepare("
ALTER TABLE `appwrite`.`app_{$project->getId()}.audit.audit` DROP COLUMN IF EXISTS `userType`;
ALTER TABLE `appwrite`.`app_{$project->getId()}.audit.audit` DROP INDEX IF EXISTS `index_1`;
ALTER TABLE `appwrite`.`app_{$project->getId()}.audit.audit` ADD INDEX IF NOT EXISTS `index_1` (`userId` ASC);
CREATE TABLE IF NOT EXISTS `template.database.unique` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index1` (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `{$schema}`.`app_{$project->getId()}.database.unique` LIKE `template.database.unique`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` DROP COLUMN IF EXISTS `userType`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` DROP INDEX IF EXISTS `index_1`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` ADD INDEX IF NOT EXISTS `index_1` (`userId` ASC);
");
$statement->closeCursor();
@ -141,6 +152,8 @@ function fixDocument(Document $document) {
->removeAttribute('$uid')
;
Console::log('Switched from $uid to $id: '.$document->getCollection().'/'.$document->getId());
foreach($document as &$attr) {
if($attr instanceof Document) {
$attr = fixDocument($attr);

View file

@ -74,7 +74,7 @@
data-event="submit"
data-success="trigger,alert"
data-success-param-alert-text="Email address updated successfully"
data-success-param-trigger-events="account-update"
data-success-param-trigger-events="account-update,modal-close"
data-failure="alert"
data-failure-param-alert-text="Failed updating email address"
data-failure-param-alert-classname="error">

View file

@ -124,7 +124,7 @@ $providers = $this->getParam('providers', []);
<span class="tag">Unverified</span>
</span>
<span data-ls-if="{{user.status}} === <?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>">
<span data-ls-if="{{user.status}} === <?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>">
<span class="tag red">Blocked</span>
</span>
</td>

View file

@ -20,7 +20,7 @@
<li data-state="/console/users/view?id={{router.params.id}}&project={{router.params.project}}">
<h2>General</h2>
<div data-ls-if="{{user.status}} === <?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none" class="box padding-small danger margin-bottom-xxl text-align-center">
<div data-ls-if="{{user.status}} === <?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none" class="box padding-small danger margin-bottom-xxl text-align-center">
This user account is blocked.
</div>
@ -85,7 +85,7 @@
<input id="uid" type="text" autocomplete="off" placeholder="" data-ls-bind="{{user.$id}}" disabled data-forms-copy>
</div>
<div data-ls-if="{{user.status}} !== <?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none">
<div data-ls-if="{{user.status}} !== <?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none">
<form name="users.updateStatus" class="margin-bottom"
data-analytics-event="submit"
data-analytics-category="console"
@ -100,11 +100,11 @@
data-failure-param-alert-text="Failed to Block User"
data-failure-param-alert-classname="error">
<button name="status" type="submit" class="danger fill" value="<?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>">Block Account</button>
<button name="status" type="submit" class="danger fill" value="<?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>">Block Account</button>
</form>
</div>
<div data-ls-if="{{user.status}} === <?php echo \Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none">
<div data-ls-if="{{user.status}} === <?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none">
<form name="users.updateStatus" class="margin-bottom"
data-analytics-event="submit"
data-analytics-category="console"
@ -119,7 +119,7 @@
data-failure-param-alert-text="Failed to Activate User"
data-failure-param-alert-classname="error">
<button name="status" type="submit" class="fill" value="<?php echo \Auth\Auth::USER_STATUS_ACTIVATED; ?>">Activate Account</button>
<button name="status" type="submit" class="fill" value="<?php echo \Appwrite\Auth\Auth::USER_STATUS_ACTIVATED; ?>">Activate Account</button>
</form>
</div>
</div>

View file

@ -23,7 +23,7 @@
data-service="account.createSession"
data-scope="console"
data-event="submit"
data-success="trigger,redirect"
data-success="trigger,hide,redirect"
data-success-param-trigger-events="account.createSession"
data-success-param-redirect-url="/console"
data-failure="alert"

View file

@ -14,7 +14,7 @@
data-service="account.create"
data-scope="console"
data-event="submit"
data-success="trigger"
data-success="trigger,hide"
data-success-param-trigger-events="account.create"
data-success-param-redirect-url="/console"
data-failure="alert"

View file

@ -1,11 +1,10 @@
<?php
use Database\Database;
use Database\Document;
use Database\Validator\Authorization;
use Network\Validators\CNAME;
use Utopia\App;
use Utopia\Domains\Domain;
use Appwrite\Database\Database;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Network\Validators\CNAME;
require_once __DIR__.'/../init.php';

View file

@ -2,8 +2,8 @@
require_once __DIR__.'/../init.php';
use Database\Database;
use Database\Validator\Authorization;
use Appwrite\Database\Database;
use Appwrite\Database\Validator\Authorization;
use Cron\CronExpression;
cli_set_process_title('Tasks V1 Worker');

View file

@ -6,8 +6,8 @@ cli_set_process_title('Webhooks V1 Worker');
echo APP_NAME.' webhooks worker v1 has started';
use Database\Database;
use Database\Validator\Authorization;
use Appwrite\Database\Database;
use Appwrite\Database\Validator\Authorization;
class WebhooksV1
{

View file

@ -11,16 +11,7 @@
],
"autoload": {
"psr-4": {
"Audit\\": "src/Audit",
"Auth\\": "src/Auth",
"Database\\": "src/Database",
"Event\\": "src/Event",
"Network\\": "src/Network",
"OpenSSL\\": "src/OpenSSL",
"Resize\\": "src/Resize",
"Storage\\": "src/Storage",
"Task\\": "src/Task",
"Template\\": "src/Template"
"Appwrite\\": "src/Appwrite"
}
},
"autoload-dev": {
@ -39,16 +30,16 @@
"ext-zlib": "*",
"ext-sockets": "*",
"appwrite/php-clamav": "master",
"appwrite/php-clamav": "1.0.*",
"utopia-php/framework": "master",
"utopia-php/abuse": "master",
"utopia-php/audit": "master",
"utopia-php/cache": "master",
"utopia-php/cli": "master",
"utopia-php/locale": "master",
"utopia-php/registry": "master",
"utopia-php/domains": "master",
"utopia-php/framework": "0.2.*",
"utopia-php/abuse": "0.2.*",
"utopia-php/audit": "0.2.*",
"utopia-php/cache": "0.2.*",
"utopia-php/cli": "0.4.*",
"utopia-php/locale": "0.2.*",
"utopia-php/registry": "0.2.*",
"utopia-php/domains": "0.2.*",
"chrisboulton/php-resque": "*",
"chrisboulton/php-resque-scheduler": "*",

159
composer.lock generated
View file

@ -4,11 +4,11 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2974879777e4362ff4e8138a0e12f926",
"content-hash": "54701e5067d9b94ae765f3f0e560b531",
"packages": [
{
"name": "appwrite/php-clamav",
"version": "dev-master",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/appwrite/php-clamav.git",
@ -1111,12 +1111,21 @@
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
<<<<<<< HEAD
"reference": "e1cb6eca27ccfd46567a2837eeba62bc5fecdee2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/e1cb6eca27ccfd46567a2837eeba62bc5fecdee2",
"reference": "e1cb6eca27ccfd46567a2837eeba62bc5fecdee2",
=======
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
>>>>>>> 677b609f371682824639847680f17f5261fd11de
"shasum": ""
},
"require": {
@ -1150,7 +1159,11 @@
"psr",
"psr-3"
],
<<<<<<< HEAD
"time": "2020-02-28T08:38:25+00:00"
=======
"time": "2020-03-23T09:12:05+00:00"
>>>>>>> 677b609f371682824639847680f17f5261fd11de
},
{
"name": "ralouphie/getallheaders",
@ -1194,7 +1207,7 @@
},
{
"name": "utopia-php/abuse",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
@ -1241,7 +1254,7 @@
},
{
"name": "utopia-php/audit",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
@ -1288,7 +1301,7 @@
},
{
"name": "utopia-php/cache",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/cache.git",
@ -1335,21 +1348,21 @@
},
{
"name": "utopia-php/cli",
"version": "dev-master",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/cli.git",
"reference": "0d232917ec9afefdcb5d0fa486c6005e928e561a"
"reference": "a3e893c49546fa7d8254a63ec6f919653d292af8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/cli/zipball/0d232917ec9afefdcb5d0fa486c6005e928e561a",
"reference": "0d232917ec9afefdcb5d0fa486c6005e928e561a",
"url": "https://api.github.com/repos/utopia-php/cli/zipball/a3e893c49546fa7d8254a63ec6f919653d292af8",
"reference": "a3e893c49546fa7d8254a63ec6f919653d292af8",
"shasum": ""
},
"require": {
"php": ">=7.1",
"utopia-php/framework": "master"
"utopia-php/framework": "0.2.*"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
@ -1379,11 +1392,11 @@
"upf",
"utopia"
],
"time": "2019-12-31T20:42:16+00:00"
"time": "2020-03-25T04:46:43+00:00"
},
{
"name": "utopia-php/domains",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/domains.git",
@ -1433,7 +1446,7 @@
},
{
"name": "utopia-php/framework",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/framework.git",
@ -1477,7 +1490,7 @@
},
{
"name": "utopia-php/locale",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/locale.git",
@ -1523,7 +1536,7 @@
},
{
"name": "utopia-php/registry",
"version": "dev-master",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/registry.git",
@ -1779,12 +1792,12 @@
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "b2c28789e80a97badd14145fda39b545d83ca3ef"
"reference": "a491d65139e2411c75704e871dd02bdddf5a4bdc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef",
"reference": "b2c28789e80a97badd14145fda39b545d83ca3ef",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a491d65139e2411c75704e871dd02bdddf5a4bdc",
"reference": "a491d65139e2411c75704e871dd02bdddf5a4bdc",
"shasum": ""
},
"require": {
@ -1819,7 +1832,7 @@
"object",
"object graph"
],
"time": "2020-01-17T21:11:47+00:00"
"time": "2020-03-12T21:49:07+00:00"
},
{
"name": "phar-io/manifest",
@ -2206,20 +2219,20 @@
},
{
"name": "phpunit/php-file-iterator",
"version": "dev-master",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "bc6c7c703f4ac9284b7c767f1d1ddfb114a3c0b4"
"reference": "050bedf145a257b1ff02746c31894800e5122946"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/bc6c7c703f4ac9284b7c767f1d1ddfb114a3c0b4",
"reference": "bc6c7c703f4ac9284b7c767f1d1ddfb114a3c0b4",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
"reference": "050bedf145a257b1ff02746c31894800e5122946",
"shasum": ""
},
"require": {
"php": "^7.3"
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.1"
@ -2252,7 +2265,7 @@
"filesystem",
"iterator"
],
"time": "2019-12-27T07:39:30+00:00"
"time": "2018-09-13T20:33:42+00:00"
},
{
"name": "phpunit/php-text-template",
@ -2297,20 +2310,20 @@
},
{
"name": "phpunit/php-timer",
"version": "dev-master",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "0f76cad901d778be0e908160d850b5469b9dff89"
"reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/0f76cad901d778be0e908160d850b5469b9dff89",
"reference": "0f76cad901d778be0e908160d850b5469b9dff89",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
"reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
"shasum": ""
},
"require": {
"php": "^7.3"
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
@ -2342,25 +2355,25 @@
"keywords": [
"timer"
],
"time": "2020-01-17T12:26:29+00:00"
"time": "2019-06-07T04:22:29+00:00"
},
{
"name": "phpunit/php-token-stream",
"version": "dev-master",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "80d6b894fd17bbeb2c6432209afbda84c34e129d"
"reference": "995192df77f63a59e47f025390d2d1fdf8f425ff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/80d6b894fd17bbeb2c6432209afbda84c34e129d",
"reference": "80d6b894fd17bbeb2c6432209afbda84c34e129d",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff",
"reference": "995192df77f63a59e47f025390d2d1fdf8f425ff",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": "^7.3"
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
@ -2391,20 +2404,20 @@
"keywords": [
"tokenizer"
],
"time": "2020-01-17T12:30:57+00:00"
"time": "2019-09-17T06:23:10+00:00"
},
{
"name": "phpunit/phpunit",
"version": "7.5.x-dev",
"version": "7.5.20",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "fc43f121f3c4ad93630bac6f9c86c23fb917b095"
"reference": "9467db479d1b0487c99733bb1e7944d32deded2c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc43f121f3c4ad93630bac6f9c86c23fb917b095",
"reference": "fc43f121f3c4ad93630bac6f9c86c23fb917b095",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c",
"reference": "9467db479d1b0487c99733bb1e7944d32deded2c",
"shasum": ""
},
"require": {
@ -2475,24 +2488,24 @@
"testing",
"xunit"
],
"time": "2020-01-23T15:43:47+00:00"
"time": "2020-01-08T08:45:45+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "dev-master",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "f48317adc82e5b3f6d2b369af78e2a721d027f5d"
"reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/f48317adc82e5b3f6d2b369af78e2a721d027f5d",
"reference": "f48317adc82e5b3f6d2b369af78e2a721d027f5d",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
"reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
"shasum": ""
},
"require": {
"php": "^7.3"
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.0"
@ -2520,7 +2533,7 @@
],
"description": "Looks up which function or method a line of code belongs to",
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"time": "2020-01-17T12:04:18+00:00"
"time": "2017-03-04T06:30:41+00:00"
},
{
"name": "sebastian/comparator",
@ -2644,20 +2657,20 @@
},
{
"name": "sebastian/environment",
"version": "dev-master",
"version": "4.2.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "635345ff4f2262c07379fdbb4ead0ca14efa941b"
"reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/635345ff4f2262c07379fdbb4ead0ca14efa941b",
"reference": "635345ff4f2262c07379fdbb4ead0ca14efa941b",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
"reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368",
"shasum": ""
},
"require": {
"php": "^7.3"
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.5"
@ -2693,7 +2706,7 @@
"environment",
"hhvm"
],
"time": "2020-01-17T12:13:49+00:00"
"time": "2019-11-20T08:46:58+00:00"
},
{
"name": "sebastian/exporter",
@ -2960,20 +2973,20 @@
},
{
"name": "sebastian/resource-operations",
"version": "dev-master",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "89893975fe3fcc2e60214471761af5e91cc7a933"
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/89893975fe3fcc2e60214471761af5e91cc7a933",
"reference": "89893975fe3fcc2e60214471761af5e91cc7a933",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"shasum": ""
},
"require": {
"php": "^7.3"
"php": "^7.1"
},
"type": "library",
"extra": {
@ -2998,7 +3011,7 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"time": "2019-10-23T09:09:44+00:00"
"time": "2018-10-04T04:07:39+00:00"
},
{
"name": "sebastian/version",
@ -3107,12 +3120,21 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
<<<<<<< HEAD
"reference": "766ee47e656529b352da69c0ff29da928a9629e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/766ee47e656529b352da69c0ff29da928a9629e7",
"reference": "766ee47e656529b352da69c0ff29da928a9629e7",
=======
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
>>>>>>> 677b609f371682824639847680f17f5261fd11de
"shasum": ""
},
"require": {
@ -3158,7 +3180,11 @@
"portable",
"shim"
],
<<<<<<< HEAD
"time": "2020-02-27T09:26:54+00:00"
=======
"time": "2020-03-09T19:04:49+00:00"
>>>>>>> 677b609f371682824639847680f17f5261fd11de
},
{
"name": "theseer/tokenizer",
@ -3206,12 +3232,21 @@
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
<<<<<<< HEAD
"reference": "0da153eb3b843d1117e52c882df6f40aefb954ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/0da153eb3b843d1117e52c882df6f40aefb954ab",
"reference": "0da153eb3b843d1117e52c882df6f40aefb954ab",
=======
"reference": "27af7d9cd1b77fcb13b4ed452c291d9defad088b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/27af7d9cd1b77fcb13b4ed452c291d9defad088b",
"reference": "27af7d9cd1b77fcb13b4ed452c291d9defad088b",
>>>>>>> 677b609f371682824639847680f17f5261fd11de
"shasum": ""
},
"require": {
@ -3263,7 +3298,11 @@
"keywords": [
"templating"
],
<<<<<<< HEAD
"time": "2020-02-23T08:42:25+00:00"
=======
"time": "2020-03-24T12:35:30+00:00"
>>>>>>> 677b609f371682824639847680f17f5261fd11de
},
{
"name": "webmozart/assert",

View file

@ -22,7 +22,7 @@ services:
- appwrite-config:/storage/config:ro
- appwrite-certificates:/storage/certificates:ro
depends_on:
- appwrite
- appwrite
networks:
- gateway
- appwrite
@ -84,7 +84,7 @@ services:
- _APP_SMTP_PORT=25
mariadb:
image: appwrite/mariadb:1.0.2 # fix issues when upgrading using: mysql_upgrade -u root -p
image: appwrite/mariadb:1.0.3 # fix issues when upgrading using: mysql_upgrade -u root -p
restart: unless-stopped
networks:
- appwrite

6
docker/bin/upgrade Executable file
View file

@ -0,0 +1,6 @@
#!/bin/bash
export PHP_VERSION=$PHP_VERSION
# Init server settings
php /usr/share/nginx/html/app/tasks/upgrade.php run

3645
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,11 +5,11 @@
"repository": "public",
"devDependencies": {
"gulp": "^4.0.0",
"gulp-clean-css": "^4.0.0",
"gulp-concat": "2.5.2",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-jsmin": "^0.1.5",
"gulp-less": "^4.0.1",
"jest": "^24.9.0",
"jest": "^25.1.0",
"ls-service-form2json": "^1.0.0"
}
}

View file

@ -2595,8 +2595,8 @@ if("/console"===router.getCurrent().path){document.body.classList.add("index");}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}}).add({selector:"data-ls-ui-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");child.width=500;child.height=175;let stats=container.get("usage");if(!stats||!stats["requests"]||!stats["requests"]["data"]){return;}
let config={type:"line",data:{labels:[],datasets:[{label:"Requests",backgroundColor:"rgba(230, 248, 253, 0.3)",borderColor:"#29b5d9",borderWidth:2,data:[0,0,0,0,0,0,0],fill:true}]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};for(let i=0;i<stats["requests"]["data"].length;i++){config.data.datasets[0].data[i]=stats["requests"]["data"][i].value;config.data.labels[i]=date.format("d F Y",stats["requests"]["data"][i].date);}
let chart=container.get("chart");if(chart){}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let debug=!!element.dataset["debug"];let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];if(debug)
console.log("%c[service init]: "+action+" ("+service+")","color:red");let callbacks={reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let fade=(element.dataset["fade"]||false);let scope=element.dataset["scope"]||"sdk";let debug=!!element.dataset["debug"];let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];if(debug)
console.log("%c[service init]: "+action+" ("+service+")","color:red");let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){window.location=url||"/";};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
@ -2612,21 +2612,26 @@ let args=getParams(target);if(debug)console.log("%c[form data]: ","color:green",
console.log("[param resolved]: ("+service+") "+value+"=",result);return result;}));};let exec=function(event){element.$lsSkip=true;element.classList.add("load-service-start");if(debug)
console.log("%c[executed]: "+scope+"."+action,"color:yellow",event,element,document.body.contains(element));if(!document.body.contains(element)){element=undefined;return false;}
if(event){event.preventDefault();}
<<<<<<< HEAD
if(confirm){if(window.confirm(confirm)!==true){element.classList.add("load-service-end");return false;}}
=======
if(running){console.log('blocked');return false;}
running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm)!==true){return false;}}
>>>>>>> 677b609f371682824639847680f17f5261fd11de
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
let method=container.path(scope+"."+action);if(!method){throw new Error('Method "'+scope+"."+action+'" not found');}
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);if(debug)
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);if(debug)
console.log('%cservice ready: "'+service.replace(".","-")+'"',"color:green");if(debug)
console.log("%cservice:","color:blue",container.get(service.replace(".","-")));for(let i=0;i<success.length;i++){container.resolve(resolve(callbacks[success[i]],"successParam"+
success[i].charAt(0).toUpperCase()+
success[i].slice(1),{}));}
container.set("serviceData",null,true,true);container.set("serviceForm",null,true,true);element.$lsSkip=false;view.render(element);},function(exception){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
failure[i].charAt(0).toUpperCase()+
failure[i].slice(1),{}));}
element.$lsSkip=false;view.render(element);});};let events=event.trim().split(",");for(let y=0;y<events.length;y++){if(""===events[y]){continue;}

View file

@ -311,8 +311,8 @@ if("/console"===router.getCurrent().path){document.body.classList.add("index");}
window.getSelection().removeAllRanges();});element.parentNode.parentNode.appendChild(copy);}}).add({selector:"data-ls-ui-chart",controller:function(element,container,date,document){let child=document.createElement("canvas");child.width=500;child.height=175;let stats=container.get("usage");if(!stats||!stats["requests"]||!stats["requests"]["data"]){return;}
let config={type:"line",data:{labels:[],datasets:[{label:"Requests",backgroundColor:"rgba(230, 248, 253, 0.3)",borderColor:"#29b5d9",borderWidth:2,data:[0,0,0,0,0,0,0],fill:true}]},options:{responsive:true,title:{display:false,text:"Stats"},legend:{display:false},tooltips:{mode:"index",intersect:false,caretPadding:0},hover:{mode:"nearest",intersect:true},scales:{xAxes:[{display:false}],yAxes:[{display:false}]}}};for(let i=0;i<stats["requests"]["data"].length;i++){config.data.datasets[0].data[i]=stats["requests"]["data"][i].value;config.data.labels[i]=date.format("d F Y",stats["requests"]["data"][i].date);}
let chart=container.get("chart");if(chart){}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let scope=element.dataset["scope"]||"sdk";let debug=!!element.dataset["debug"];let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];if(debug)
console.log("%c[service init]: "+action+" ("+service+")","color:red");let callbacks={reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
element.innerHTML="";element.appendChild(child);container.set("chart",new Chart(child.getContext("2d"),config),true);element.dataset["canvas"]=true;}});(function(window){"use strict";window.ls.view.add({selector:"data-service",controller:function(element,view,container,form,alerts,expression,window){let action=element.dataset["service"];let service=element.dataset["name"]||action;let event=expression.parse(element.dataset["event"]);let confirm=element.dataset["confirm"]||"";let loading=element.dataset["loading"]||"";let loaderId=null;let fade=(element.dataset["fade"]||false);let scope=element.dataset["scope"]||"sdk";let debug=!!element.dataset["debug"];let success=element.dataset["success"]||"";let failure=element.dataset["failure"]||"";let running=false;success=success&&success!=""?success.split(",").map(element=>element.trim()):[];failure=failure&&failure!=""?failure.split(",").map(element=>element.trim()):[];if(debug)
console.log("%c[service init]: "+action+" ("+service+")","color:red");let callbacks={hide:function(){return function(){return element.style.opacity='0';};},reset:function(){return function(){if("FORM"===element.tagName){return element.reset();}
throw new Error("This callback is only valid for forms");};},alert:function(text,classname){return function(alerts){alerts.add({text:text,class:classname||"success"},3000);};},redirect:function(url){return function(router){window.location=url||"/";};},reload:function(){return function(router){router.reload();};},state:function(keys){let updateQueryString=function(key,value,url){var re=new RegExp("([?&])"+key+"=.*?(&|#|$)(.*)","gi"),hash;if(re.test(url)){if(typeof value!=="undefined"&&value!==null){return url.replace(re,"$1"+key+"="+value+"$2$3");}else{hash=url.split("#");url=hash[0].replace(re,"$1$3").replace(/(&|\?)$/,"");if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}}else{if(typeof value!=="undefined"&&value!==null){var separator=url.indexOf("?")!==-1?"&":"?";hash=url.split("#");url=hash[0]+separator+key+"="+value;if(typeof hash[1]!=="undefined"&&hash[1]!==null){url+="#"+hash[1];}
return url;}else{return url;}}};keys=keys.split(",").map(element=>element.trim());return function(serviceForm,router,window){let url=window.location.href;keys.map(node=>{node=node.split("=");let key=node[0]||"";let name=node[1]||key;let value=getValue(key,"param",serviceForm);url=updateQueryString(name,value?value:null,url);});if(url!==window.location.href){window.history.pushState({},"",url);router.reset();}};},trigger:function(events){return function(document){events=events.trim().split(",");for(let i=0;i<events.length;i++){if(""===events[i]){continue;}
@ -328,21 +328,26 @@ let args=getParams(target);if(debug)console.log("%c[form data]: ","color:green",
console.log("[param resolved]: ("+service+") "+value+"=",result);return result;}));};let exec=function(event){element.$lsSkip=true;element.classList.add("load-service-start");if(debug)
console.log("%c[executed]: "+scope+"."+action,"color:yellow",event,element,document.body.contains(element));if(!document.body.contains(element)){element=undefined;return false;}
if(event){event.preventDefault();}
<<<<<<< HEAD
if(confirm){if(window.confirm(confirm)!==true){element.classList.add("load-service-end");return false;}}
=======
if(running){console.log('blocked');return false;}
running=true;element.style.backgroud='red';if(confirm){if(window.confirm(confirm)!==true){return false;}}
>>>>>>> 677b609f371682824639847680f17f5261fd11de
if(loading){loaderId=alerts.add({text:loading,class:""},0);}
let method=container.path(scope+"."+action);if(!method){throw new Error('Method "'+scope+"."+action+'" not found');}
let formData="FORM"===element.tagName?form.toJson(element):{};let result=resolve(method,"param",formData);if(!result){return;}
if(Promise.resolve(result)!=result){result=new Promise((resolve,reject)=>{resolve(result);});}
result.then(function(data){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);if(debug)
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");container.set(service.replace(".","-"),data,true,true);container.set("serviceData",data,true,true);container.set("serviceForm",formData,true,true);if(debug)
console.log('%cservice ready: "'+service.replace(".","-")+'"',"color:green");if(debug)
console.log("%cservice:","color:blue",container.get(service.replace(".","-")));for(let i=0;i<success.length;i++){container.resolve(resolve(callbacks[success[i]],"successParam"+
success[i].charAt(0).toUpperCase()+
success[i].slice(1),{}));}
container.set("serviceData",null,true,true);container.set("serviceForm",null,true,true);element.$lsSkip=false;view.render(element);},function(exception){if(loaderId!==null){alerts.remove(loaderId);}
if(!element){return;}
element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
running=false;element.style.backgroud='transparent';element.classList.add("load-service-end");for(let i=0;i<failure.length;i++){container.resolve(resolve(callbacks[failure[i]],"failureParam"+
failure[i].charAt(0).toUpperCase()+
failure[i].slice(1),{}));}
element.$lsSkip=false;view.render(element);});};let events=event.trim().split(",");for(let y=0;y<events.length;y++){if(""===events[y]){continue;}

View file

@ -18,10 +18,12 @@
let confirm = element.dataset["confirm"] || ""; // Free text
let loading = element.dataset["loading"] || ""; // Free text
let loaderId = null;
let fade = (element.dataset["fade"] || false);
let scope = element.dataset["scope"] || "sdk"; // Free text
let debug = !!element.dataset["debug"]; // Free text
let success = element.dataset["success"] || "";
let failure = element.dataset["failure"] || "";
let running = false;
success =
success && success != ""
@ -39,6 +41,12 @@
);
let callbacks = {
hide: function() {
return function() {
return element.style.opacity = '0';
};
},
reset: function() {
return function() {
if ("FORM" === element.tagName) {
@ -236,6 +244,7 @@
};
let exec = function(event) {
element.$lsSkip = true;
element.classList.add("load-service-start");
@ -258,6 +267,14 @@
event.preventDefault();
}
if(running) {
console.log('blocked');
return false;
}
running = true;
element.style.backgroud = 'red';
if (confirm) {
if (window.confirm(confirm) !== true) {
element.classList.add("load-service-end");
@ -300,6 +317,8 @@
return;
}
running = false;
element.style.backgroud = 'transparent';
element.classList.add("load-service-end");
container.set(service.replace(".", "-"), data, true, true);
@ -348,6 +367,8 @@
return;
}
running = false;
element.style.backgroud = 'transparent';
element.classList.add("load-service-end");
for (let i = 0; i < failure.length; i++) {

View file

@ -1,8 +1,8 @@
<?php
namespace Auth;
namespace Appwrite\Auth;
use Database\Document;
use Appwrite\Database\Document;
class Auth
{

View file

@ -1,6 +1,6 @@
<?php
namespace Auth;
namespace Appwrite\Auth;
abstract class OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://developer.amazon.com/docs/login-with-amazon/authorization-code-grant.html

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html#OAuthonBitbucketCloud-Createaconsumer

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://dev.bitly.com/v4_documentation.html

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://discordapp.com/developers/docs/topics/oauth2

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://www.dropbox.com/developers/reference/oauth-guide

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class Facebook extends OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class Github extends OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://docs.gitlab.com/ee/api/oauth2.html

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://developers.google.com/oauthplayground/

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class LinkedIn extends OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class Mock extends OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://developer.paypal.com/docs/api/overview/

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://help.salesforce.com/articleView?id=remoteaccess_oauth_endpoints.htm&type=5

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
class Slack extends OAuth2
{

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://dev.twitch.tv/docs/authentication

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://dev.twitch.tv/docs/authentication

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://vk.com/dev/first_guide

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://developer.yahoo.com/oauth2/guide/

View file

@ -1,8 +1,8 @@
<?php
namespace Auth\OAuth2;
namespace Appwrite\Auth\OAuth2;
use Auth\OAuth2;
use Appwrite\Auth\OAuth2;
// Reference Material
// https://tech.yandex.com/passport/doc/dg/reference/request-docpage/

View file

@ -1,6 +1,6 @@
<?php
namespace Auth\Validator;
namespace Appwrite\Auth\Validator;
use Utopia\Validator;

View file

@ -1,6 +1,6 @@
<?php
namespace Database;
namespace Appwrite\Database;
use Exception;
@ -68,7 +68,7 @@ abstract class Adapter
*
* @return array
*/
abstract public function createDocument(array $data);
abstract public function createDocument(array $data, array $unique);
/**
* Update Document.

View file

@ -1,13 +1,14 @@
<?php
namespace Database\Adapter;
namespace Appwrite\Database\Adapter;
use Utopia\Registry\Registry;
use Appwrite\Database\Adapter;
use Appwrite\Database\Exception\Duplicate;
use Appwrite\Database\Validator\Authorization;
use Exception;
use PDO;
use Redis as Client;
use Database\Adapter;
use Database\Validator\Authorization;
class MySQL extends Adapter
{
@ -150,7 +151,7 @@ class MySQL extends Adapter
*
* @return array
*/
public function createDocument(array $data = [])
public function createDocument(array $data = [], array $unique = [])
{
$order = 0;
$data = array_merge(['$id' => null, '$permissions' => []], $data); // Merge data with default params
@ -179,6 +180,21 @@ class MySQL extends Adapter
}
}
/**
* Check Unique Keys
*/
foreach($unique as $key => $value) {
$st = $this->getPDO()->prepare('INSERT INTO `'.$this->getNamespace().'.database.unique`
SET `key` = :key;
');
$st->bindValue(':key', md5($data['$collection'].':'.$key.'='.$value), PDO::PARAM_STR);
if(!$st->execute()) {
throw new Duplicate('Duplicated Property: '.$key.'='.$value);
}
}
// Add or update fields abstraction level
$st1 = $this->getPDO()->prepare('INSERT INTO `'.$this->getNamespace().'.database.documents`
SET uid = :uid, createdAt = :createdAt, updatedAt = :updatedAt, signature = :signature, revision = :revision, permissions = :permissions, status = 0
@ -398,6 +414,7 @@ class MySQL extends Adapter
$documents = 'app_'.$namespace.'.database.documents';
$properties = 'app_'.$namespace.'.database.properties';
$relationships = 'app_'.$namespace.'.database.relationships';
$unique = 'app_'.$namespace.'.database.unique';
$audit = 'app_'.$namespace.'.audit.audit';
$abuse = 'app_'.$namespace.'.abuse.abuse';
@ -405,6 +422,7 @@ class MySQL extends Adapter
$this->getPDO()->prepare('CREATE TABLE `'.$documents.'` LIKE `template.database.documents`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$properties.'` LIKE `template.database.properties`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$relationships.'` LIKE `template.database.relationships`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$unique.'` LIKE `template.database.unique`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$audit.'` LIKE `template.audit.audit`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$abuse.'` LIKE `template.abuse.abuse`;')->execute();
} catch (Exception $e) {
@ -571,23 +589,6 @@ class MySQL extends Adapter
// Search
if (!empty($options['search'])) { // Handle free search
// $where[] = "LEFT JOIN `" . $this->getNamespace() . ".database.properties` b_search ON a.uid IS NOT NULL AND b_search.documentUid = a.uid
// LEFT JOIN
// `" . $this->getNamespace() . ".database.relationships` c_search ON c_search.start = a.uid
// LEFT JOIN
// `" . $this->getNamespace() . ".database.properties` d_search ON d_search.documentUid = c_search.end
// LEFT JOIN
// `" . $this->getNamespace() . ".database.relationships` e_search ON e_search.start = c_search.end
// LEFT JOIN
// `" . $this->getNamespace() . ".database.properties` f_search ON f_search.documentUid = e_search.end
// \n";
// $search = "AND (MATCH (b_search.value) AGAINST ({$this->getPDO()->quote($options['search'], PDO::PARAM_STR)} IN BOOLEAN MODE)
// OR b_search.value LIKE {$this->getPDO()->quote('%%' . $options['search'] . '%%', PDO::PARAM_STR)}
// OR MATCH (d_search.value) AGAINST ({$this->getPDO()->quote($options['search'], PDO::PARAM_STR)} IN BOOLEAN MODE)
// OR d_search.value LIKE {$this->getPDO()->quote('%%' . $options['search'] . '%%', PDO::PARAM_STR)}
// OR MATCH (f_search.value) AGAINST ({$this->getPDO()->quote($options['search'], PDO::PARAM_STR)} IN BOOLEAN MODE)
// OR f_search.value LIKE {$this->getPDO()->quote('%%' . $options['search'] . '%%', PDO::PARAM_STR)})";
$where[] = 'LEFT JOIN `'.$this->getNamespace().".database.properties` b_search ON a.uid IS NOT NULL AND b_search.documentUid = a.uid AND b_search.primitive = 'string'
LEFT JOIN
`".$this->getNamespace().'.database.relationships` c_search ON c_search.start = b_search.documentUid

View file

@ -1,11 +1,11 @@
<?php
namespace Database\Adapter;
namespace Appwrite\Database\Adapter;
use Utopia\Registry\Registry;
use Appwrite\Database\Adapter;
use Exception;
use Redis as Client;
use Database\Adapter;
class Redis extends Adapter
{
@ -105,9 +105,9 @@ class Redis extends Adapter
*
* @throws Exception
*/
public function createDocument(array $data = [])
public function createDocument(array $data = [], array $unique = [])
{
$data = $this->adapter->createDocument($data);
$data = $this->adapter->createDocument($data, $unique);
$this->getRedis()->expire($this->getNamespace().':document-'.$data['$id'], 0);
$this->getRedis()->expire($this->getNamespace().':document-'.$data['$id'], 0);

View file

@ -1,12 +1,12 @@
<?php
namespace Database;
namespace Appwrite\Database;
use Exception;
use Database\Validator\Authorization;
use Database\Validator\Structure;
use Database\Exception\Authorization as AuthorizationException;
use Database\Exception\Structure as StructureException;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Validator\Structure;
use Appwrite\Database\Exception\Authorization as AuthorizationException;
use Appwrite\Database\Exception\Structure as StructureException;
class Database
{
@ -182,7 +182,7 @@ class Database
* @throws AuthorizationException
* @throws StructureException
*/
public function createDocument(array $data)
public function createDocument(array $data, array $unique = [])
{
$document = new Document($data);
@ -198,7 +198,7 @@ class Database
throw new StructureException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
}
return new Document($this->adapter->createDocument($data));
return new Document($this->adapter->createDocument($data, $unique));
}
/**

View file

@ -1,6 +1,6 @@
<?php
namespace Database;
namespace Appwrite\Database;
use ArrayObject;

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