1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

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

This commit is contained in:
Eldad Fux 2020-04-15 16:45:24 +03:00
commit 0c205fcf55
62 changed files with 985 additions and 515 deletions

View file

@ -1,4 +1,4 @@
FROM ubuntu:19.10 AS builder
FROM ubuntu:18.04 AS builder
LABEL maintainer="team@appwrite.io"
@ -7,7 +7,7 @@ ARG TESTING=false
ENV TZ=Asia/Tel_Aviv \
DEBIAN_FRONTEND=noninteractive \
PHP_VERSION=7.4 \
PHP_REDIS_VERSION=3.1.2
PHP_REDIS_VERSION=5.2.1
RUN \
apt-get update && \
@ -72,7 +72,7 @@ ENV TZ=Asia/Tel_Aviv \
#ENV _APP_SMTP_USERNAME ''
#ENV _APP_SMTP_PASSWORD ''
COPY --from=builder /phpredis-3.1.2/modules/redis.so /usr/lib/php/20190902/
COPY --from=builder /phpredis-5.2.1/modules/redis.so /usr/lib/php/20190902/
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View file

@ -55,6 +55,10 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
$route = $utopia->match($request);
if(!empty($route->getLabel('sdk.platform', [])) && empty($project->getId())) {
throw new Exception('Missing or unknown project ID', 400);
}
$referrer = $request->getServer('HTTP_REFERER', '');
$origin = parse_url($request->getServer('HTTP_ORIGIN', $referrer), PHP_URL_HOST);
$protocol = parse_url($request->getServer('HTTP_ORIGIN', $referrer), PHP_URL_SCHEME);
@ -66,8 +70,9 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
$selfDomain = new Domain(Config::getParam('domain'));
$endDomain = new Domain($origin);
Config::setParam('domainVerification', ($selfDomain->getRegisterable() === $endDomain->getRegisterable()));
Config::setParam('domainVerification',
($selfDomain->getRegisterable() === $endDomain->getRegisterable()));
/*
* Security Headers
*

View file

@ -130,7 +130,7 @@ return [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '0.0.7',
'version' => '0.0.8',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'enabled' => true,
'beta' => true,

View file

@ -24,11 +24,15 @@ use Appwrite\Database\Validator\UID;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Template\Template;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\URL\URL as URLParser;
use DeviceDetector\DeviceDetector;
use GeoIp2\Database\Reader;
include_once __DIR__ . '/../shared/api.php';
$oauthDefaultSuccess = Config::getParam('protocol').'://'.Config::getParam('domain').'/auth/oauth2/success';
$oauthDefaultFailure = Config::getParam('protocol').'://'.Config::getParam('domain').'/auth/oauth2/failure';
$oauth2Keys = [];
$utopia->init(function() use (&$oauth2Keys) {
@ -243,12 +247,12 @@ $utopia->get('/v1/account/sessions/oauth2/:provider')
->label('sdk.description', '/docs/references/account/create-session-oauth2.md')
->label('sdk.response.code', 301)
->label('sdk.response.type', 'text/html')
->label('sdk.location', true)
->label('sdk.methodType', 'webAuth')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->param('provider', '', function () { return new WhiteList(array_keys(Config::getParam('providers'))); }, 'OAuth2 Provider. Currently, supported providers are: ' . implode(', ', array_keys(array_filter(Config::getParam('providers'), function($node) {return (!$node['mock']);}))).'.')
->param('success', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt.')
->param('failure', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt.')
->param('success', $oauthDefaultSuccess, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt.', true)
->param('failure', $oauthDefaultFailure, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt.', true)
->action(
function ($provider, $success, $failure) use ($response, $request, $project) {
$protocol = Config::getParam('protocol');
@ -264,7 +268,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider')
}
if (empty($appId) || empty($appSecret)) {
throw new Exception('Provider is undefined, configure provider app ID and app secret key to continue', 412);
throw new Exception('This provider is disabled. Please configure the provider app ID and app secret key from your '.APP_NAME.' console to continue.', 412);
}
$classname = 'Appwrite\\Auth\\OAuth2\\'.ucfirst($provider);
@ -275,7 +279,10 @@ $utopia->get('/v1/account/sessions/oauth2/:provider')
$oauth2 = new $classname($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure]);
$response->redirect($oauth2->getLoginURL());
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->redirect($oauth2->getLoginURL());
}
);
@ -292,8 +299,12 @@ $utopia->get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
function ($projectId, $provider, $code, $state) use ($response) {
$domain = Config::getParam('domain');
$protocol = Config::getParam('protocol');
$response->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
}
);
@ -309,7 +320,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
->param('state', '', function () { return new Text(2048); }, 'OAuth2 state params.', true)
->action(
function ($provider, $code, $state) use ($response, $request, $user, $projectDB, $project, $audit) {
function ($provider, $code, $state) use ($response, $request, $user, $projectDB, $project, $audit, $oauthDefaultSuccess) {
$protocol = Config::getParam('protocol');
$callback = $protocol.'://'.$request->getServer('HTTP_HOST').'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId();
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
@ -469,7 +480,19 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
;
}
if($state['success'] === $oauthDefaultSuccess) { // Add keys for non-web platforms
$state['success'] = URLParser::parse($state['success']);
$query = URLParser::parseQuery($state['success']['query']);
$query['domain'] = COOKIE_DOMAIN;
$query['key'] = Auth::$cookieName;
$query['secret'] = Auth::encodeSession($user->getId(), $secret);
$state['success']['query'] = URLParser::unparseQuery($query);
$state['success'] = URLParser::unparse($state['success']);
}
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', COOKIE_DOMAIN, ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', COOKIE_DOMAIN, ('https' == $protocol), true, COOKIE_SAMESITE)
->redirect($state['success'])
@ -486,7 +509,7 @@ $utopia->get('/v1/account')
->label('sdk.description', '/docs/references/account/get.md')
->label('sdk.response', ['200' => 'user'])
->action(
function () use ($response, &$user, $oauth2Keys) {
function () use ($response, &$user, $oauth2Keys) {
$response->json(array_merge($user->getArrayCopy(array_merge(
[
'$id',

View file

@ -10,6 +10,7 @@ use Utopia\Validator\URL;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Appwrite\Resize\Resize;
use Appwrite\URL\URL as URLParse;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
@ -265,7 +266,7 @@ $utopia->get('/v1/avatars/favicon')
$href = $link->getAttribute('href');
$rel = $link->getAttribute('rel');
$sizes = $link->getAttribute('sizes');
$absolute = unparse_url(array_merge(parse_url($url), parse_url($href)));
$absolute = URLParse::unparse(array_merge(parse_url($url), parse_url($href)));
switch (strtolower($rel)) {
case 'icon':
@ -381,41 +382,4 @@ $utopia->get('/v1/avatars/qr')
->send('', $writer->writeString($text))
;
}
);
function unparse_url($parsed_url, $ommit = array())
{
if (isset($parsed_url['path']) && mb_substr($parsed_url['path'], 0, 1) !== '/') {
$parsed_url['path'] = '/'.$parsed_url['path'];
}
$p = array();
$p['scheme'] = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://' : '';
$p['host'] = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$p['port'] = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
$p['user'] = isset($parsed_url['user']) ? $parsed_url['user'] : '';
$p['pass'] = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
$p['pass'] = ($p['user'] || $p['pass']) ? $p['pass'].'@' : '';
$p['path'] = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$p['query'] = isset($parsed_url['query']) ? '?'.$parsed_url['query'] : '';
$p['fragment'] = isset($parsed_url['fragment']) ? '#'.$parsed_url['fragment'] : '';
if ($ommit) {
foreach ($ommit as $key) {
if (isset($p[ $key ])) {
$p[ $key ] = '';
}
}
}
return $p['scheme'].$p['user'].$p['pass'].$p['host'].$p['port'].$p['path'].$p['query'].$p['fragment'];
}
);

View file

@ -51,7 +51,7 @@ $utopia->get('/v1/health/cache')
);
$utopia->get('/v1/health/time')
->desc('Check Webhooks Health')
->desc('Check Time Health')
->label('scope', 'health.read')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.namespace', 'health')
@ -98,7 +98,7 @@ $utopia->get('/v1/health/time')
);
$utopia->get('/v1/health/webhooks')
->desc('Check Time Health')
->desc('Check Webhooks Health')
->label('scope', 'health.read')
->label('sdk.platform', [APP_PLATFORM_SERVER])
->label('sdk.namespace', 'health')

View file

@ -134,7 +134,7 @@ $utopia->get('/v1/locale/countries/phones')
);
$utopia->get('/v1/locale/continents')
->desc('List Countries')
->desc('List Continents')
->label('scope', 'locale.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
->label('sdk.namespace', 'locale')

View file

@ -142,6 +142,7 @@ $utopia->post('/v1/storage/files')
->label('sdk.method', 'createFile')
->label('sdk.description', '/docs/references/storage/create-file.md')
->label('sdk.consumes', 'multipart/form-data')
->label('sdk.methodType', 'upload')
->param('file', [], function () { return new File(); }, 'Binary File.', false)
->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.')
@ -183,7 +184,6 @@ $utopia->post('/v1/storage/files')
/*
* Models
*/
$list = [];
$device = Storage::getDevice('local');
if (!$upload->isValid($file['tmp_name'])) {
@ -328,7 +328,7 @@ $utopia->get('/v1/storage/files/:fileId/preview')
->label('sdk.method', 'getFilePreview')
->label('sdk.description', '/docs/references/storage/get-file-preview.md')
->label('sdk.response.type', 'image/*')
->label('sdk.location', true)
->label('sdk.methodType', 'location')
->param('fileId', '', function () { return new UID(); }, 'File unique ID')
->param('width', 0, function () { return new Range(0, 4000); }, 'Resize preview image width, Pass an integer between 0 to 4000.', true)
->param('height', 0, function () { return new Range(0, 4000); }, 'Resize preview image height, Pass an integer between 0 to 4000.', true)
@ -452,7 +452,7 @@ $utopia->get('/v1/storage/files/:fileId/download')
->label('sdk.method', 'getFileDownload')
->label('sdk.description', '/docs/references/storage/get-file-download.md')
->label('sdk.response.type', '*')
->label('sdk.location', true)
->label('sdk.methodType', 'location')
->param('fileId', '', function () { return new UID(); }, 'File unique ID.')
->action(
function ($fileId) use ($response, $request, $projectDB) {
@ -505,7 +505,7 @@ $utopia->get('/v1/storage/files/:fileId/view')
->label('sdk.method', 'getFileView')
->label('sdk.description', '/docs/references/storage/get-file-view.md')
->label('sdk.response.type', '*')
->label('sdk.location', true)
->label('sdk.methodType', 'location')
->param('fileId', '', function () { return new UID(); }, 'File unique ID.')
->param('as', '', function () { return new WhiteList(['pdf', /*'html',*/ 'text']); }, 'Choose a file format to convert your file to. Currently you can only convert word and pdf files to pdf or txt. This option is currently experimental only, use at your own risk.', true)
->action(

View file

@ -222,6 +222,32 @@ $utopia->get('/v1/mock/tests/general/redirected')
}
);
$utopia->get('/v1/mock/tests/general/set-cookie')
->desc('Mock a cookie request for SDK tests')
->label('scope', 'public')
->label('sdk.namespace', 'general')
->label('sdk.method', 'setCookie')
->label('sdk.description', 'Mock a set cookie request for SDK tests')
->action(
function () use ($response) {
$response->addCookie('cookieName', 'cookieValue', time() + 31536000, '/', 'localhost', true, true);
}
);
$utopia->get('/v1/mock/tests/general/get-cookie')
->desc('Mock a cookie request for SDK tests')
->label('scope', 'public')
->label('sdk.namespace', 'general')
->label('sdk.method', 'getCookie')
->label('sdk.description', 'Mock a get cookie request for SDK tests')
->action(
function () use ($request) {
if($request->getCookie('cookieName', '') !== 'cookieValue') {
throw new Exception('Missing cookie value', 400);
}
}
);
$utopia->get('/v1/mock/tests/general/empty')
->desc('Mock a post request for SDK tests')
->label('scope', 'public')

View file

@ -108,6 +108,37 @@ $utopia->get('/auth/recovery/reset')
->setParam('body', $page);
});
$utopia->get('/auth/oauth2/success')
->desc('Registration page')
->label('permission', 'public')
->label('scope', 'home')
->action(function () use ($layout) {
$page = new View(__DIR__.'/../../views/home/auth/oauth2.phtml');
$layout
->setParam('title', APP_NAME)
->setParam('body', $page)
->setParam('header', [])
->setParam('footer', [])
;
});
$utopia->get('/auth/oauth2/failure')
->desc('Registration page')
->label('permission', 'public')
->label('scope', 'home')
->action(function () use ($layout) {
$page = new View(__DIR__.'/../../views/home/auth/oauth2.phtml');
$layout
->setParam('title', APP_NAME)
->setParam('body', $page)
->setParam('header', [])
->setParam('footer', [])
;
});
$utopia->get('/error/:code')
->desc('Error page')
->label('permission', 'public')

View file

@ -0,0 +1 @@
# Change Log

View file

@ -31,6 +31,21 @@ To install with a CDN (content delivery network) add the following scripts to th
<script src="https://cdn.jsdelivr.net/npm/appwrite@1.0.0"></script>
```
## Getting Started
Initialise the Appwrite SDK in your code, and setup your API credentials:
```js
// Init your JS SDK
var appwrite = new Appwrite();
appwrite
.setEndpoint('http://localhost/v1') // Set only when using self-hosted solution
.setProject('455x34dfkj') // Your Appwrite Project UID
;
```
## Contribution

View file

@ -0,0 +1,86 @@
{
"configVersion": 2,
"packages": [
{
"name": "charcode",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "collection",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "cookie_jar",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/cookie_jar-1.0.1",
"packageUri": "lib/",
"languageVersion": "1.20"
},
{
"name": "dio",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/dio-3.0.9",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "dio_cookie_manager",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/dio_cookie_manager-1.0.0",
"packageUri": "lib/",
"languageVersion": "2.4"
},
{
"name": "http_parser",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4",
"packageUri": "lib/",
"languageVersion": "2.3"
},
{
"name": "meta",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8",
"packageUri": "lib/",
"languageVersion": "1.12"
},
{
"name": "path",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/path-1.6.4",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "source_span",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/source_span-1.7.0",
"packageUri": "lib/",
"languageVersion": "2.6"
},
{
"name": "string_scanner",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "term_glyph",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0",
"packageUri": "lib/",
"languageVersion": "1.8"
},
{
"name": "typed_data",
"rootUri": "file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.6",
"packageUri": "lib/",
"languageVersion": "2.0"
},
{
"name": "appwrite",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "2.6"
}
],
"generated": "2020-04-10T18:56:11.631386Z",
"generator": "pub",
"generatorVersion": "2.7.2"
}

View file

@ -0,0 +1,14 @@
# Generated by pub on 2020-04-10 21:56:11.618646.
charcode:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.3/lib/
collection:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/collection-1.14.12/lib/
cookie_jar:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/cookie_jar-1.0.1/lib/
dio:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/dio-3.0.9/lib/
dio_cookie_manager:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/dio_cookie_manager-1.0.0/lib/
http_parser:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4/lib/
meta:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/meta-1.1.8/lib/
path:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/path-1.6.4/lib/
source_span:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/source_span-1.7.0/lib/
string_scanner:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.0.5/lib/
term_glyph:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.1.0/lib/
typed_data:file:///Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.6/lib/
appwrite:lib/

View file

@ -0,0 +1,4 @@
## 0.0.8
- Fixed compilation error in Client class
- Shorter description for package

View file

@ -3,7 +3,7 @@
![License](https://img.shields.io/github/license/appwrite/sdk-for-dart.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.**
**This SDK is compatible with Appwrite server version 0.5.3. For older versions, please check previous releases.**
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)
@ -13,17 +13,17 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for
## Installation
Add this to your package's pubspec.yaml file:
Add this to your package's `pubspec.yaml` file:
```yml
dependencies:
appwrite: ^0.0.7
appwrite: ^0.0.8
```
You can install packages from the command line:
```bash
pub get
pub get appwrite
```
## Contribution

View file

@ -1,8 +1,9 @@
export 'package:appwrite/services/account.dart';
export 'package:appwrite/services/avatars.dart';
export 'package:appwrite/services/database.dart';
export 'package:appwrite/services/locale.dart';
export 'package:appwrite/services/storage.dart';
export 'package:appwrite/services/teams.dart';
export 'package:appwrite/client.dart';
export 'services/account.dart';
export 'services/avatars.dart';
export 'services/database.dart';
export 'services/locale.dart';
export 'services/storage.dart';
export 'services/teams.dart';
export 'client.dart';
export 'enums.dart';
export 'package:dio/dio.dart' show Response;

View file

@ -1,3 +1,6 @@
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
@ -8,95 +11,74 @@ class Client {
String endPoint;
Map<String, String> headers;
bool selfSigned;
Dio http;
Client() {
this.endPoint = 'https://appwrite.io/v1';
final Dio http;
Client({this.endPoint: 'https://appwrite.io/v1', this.selfSigned: false, Dio http}) : this.http = http ?? Dio() {
this.headers = {
'content-type': 'application/json',
'x-sdk-version': 'appwrite:dart:0.0.7',
'x-sdk-version': 'appwrite:dart:0.0.8',
};
this.selfSigned = false;
this.http = Dio();
assert(endPoint.startsWith(RegExp("http://|https://")), "endPoint $endPoint must start with 'http'");
this.http.options.baseUrl = this.endPoint;
this.http.options.validateStatus = (status) => status != 404;
this.http.interceptors.add(CookieManager(CookieJar()));
}
/// Your project ID
Client setProject(value) {
this.addHeader('X-Appwrite-Project', value);
addHeader('X-Appwrite-Project', value);
return this;
}
/// Your secret API key
Client setKey(value) {
this.addHeader('X-Appwrite-Key', value);
addHeader('X-Appwrite-Key', value);
return this;
}
Client setLocale(value) {
this.addHeader('X-Appwrite-Locale', value);
addHeader('X-Appwrite-Locale', value);
return this;
}
Client setMode(value) {
this.addHeader('X-Appwrite-Mode', value);
addHeader('X-Appwrite-Mode', value);
return this;
}
Client setSelfSigned({bool status = true}) {
this.selfSigned = status;
selfSigned = status;
return this;
}
Client setEndpoint(String endPoint)
{
Client setEndpoint(String endPoint) {
this.endPoint = endPoint;
this.http.options.baseUrl = this.endPoint;
return this;
}
Client addHeader(String key, String value) {
this.headers[key.toLowerCase()] = value.toLowerCase();
headers[key] = value;
return this;
}
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}}) {
if(this.selfSigned) {
if(this.selfSigned) {
// Allow self signed requests
(http.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
return client;
};
}
String reqPath = path;
bool isGet = method == HttpMethod.get;
// Origin is hardcoded for testing
Options options = Options(
headers: {...this.headers, ...headers, "Origin": "http://localhost"},
method: method.name(),
);
if (isGet) {
path += "?";
params.forEach((k, v) {
path += "${k}=${v}&";
});
if (method == HttpMethod.get) {
return http.get(path, queryParameters: params, options: options);
} else {
return http.request(path, data: params, options: options);
}
if (!isGet)
return http.request(reqPath, data: params, options: options);
else
return http.request(reqPath, options: options);
}
}

View file

@ -2,7 +2,17 @@ enum HttpMethod {
get, post, put, delete, patch
}
extension HttpMethodString on HttpMethod{
extension HttpMethodString on HttpMethod {
String name(){
return this.toString().split('.').last.toUpperCase();
}
}
enum OrderType {
asc, desc
}
extension OrderTypeString on OrderType {
String name(){
return this.toString().split('.').last.toUpperCase();
}

View file

@ -1,9 +1,7 @@
import 'package:appwrite/client.dart';
import 'client.dart';
class Service {
Client client;
final Client client;
Service(Client client) {
this.client = client;
}
const Service(this.client);
}

View file

@ -1,24 +1,23 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Account extends Service {
Account(Client client): super(client);
Account(Client client): super(client);
/// Get currently logged in user data as JSON object.
Future<Response> get() async {
String path = '/account';
Future<Response> get() {
final String path = '/account';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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
@ -26,95 +25,95 @@ 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({@required String email, @required String password, String name = null}) async {
String path = '/account';
Future<Response> create({@required String email, @required String password, String name = null}) {
final String path = '/account';
Map<String, dynamic> params = {
'email': email,
'password': password,
'name': name,
};
final Map<String, dynamic> params = {
'email': email,
'password': password,
'name': name,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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
/// to avoid deleted accounts being overtaken by new users with the same email
/// address. Any user-related resources like documents or storage files should
/// be deleted separately.
Future<Response> delete() async {
String path = '/account';
Future<Response> delete() {
final String path = '/account';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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({@required String email, @required String password}) async {
String path = '/account/email';
Future<Response> updateEmail({@required String email, @required String password}) {
final String path = '/account/email';
Map<String, dynamic> params = {
'email': email,
'password': password,
};
final Map<String, dynamic> params = {
'email': email,
'password': password,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return 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.
Future<Response> getLogs() async {
String path = '/account/logs';
Future<Response> getLogs() {
final String path = '/account/logs';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
/// Update currently logged in user account name.
Future<Response> updateName({@required String name}) async {
String path = '/account/name';
Future<Response> updateName({@required String name}) {
final String path = '/account/name';
Map<String, dynamic> params = {
'name': name,
};
final Map<String, dynamic> params = {
'name': name,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return 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({@required String password, @required String oldPassword}) async {
String path = '/account/password';
Future<Response> updatePassword({@required String password, @required String oldPassword}) {
final String path = '/account/password';
Map<String, dynamic> params = {
'password': password,
'old-password': oldPassword,
};
final Map<String, dynamic> params = {
'password': password,
'old-password': oldPassword,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return this.client.call(HttpMethod.patch, path: path, params: params);
}
/// Get currently logged in user preferences as a key-value object.
Future<Response> getPrefs() async {
String path = '/account/prefs';
Future<Response> getPrefs() {
final String path = '/account/prefs';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required dynamic prefs}) async {
String path = '/account/prefs';
Future<Response> updatePrefs({@required dynamic prefs}) {
final String path = '/account/prefs';
Map<String, dynamic> params = {
'prefs': prefs,
};
final Map<String, dynamic> params = {
'prefs': prefs,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return 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
@ -122,15 +121,15 @@ 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({@required String email, @required String url}) async {
String path = '/account/recovery';
Future<Response> createRecovery({@required String email, @required String url}) {
final String path = '/account/recovery';
Map<String, dynamic> params = {
'email': email,
'url': url,
};
final Map<String, dynamic> params = {
'email': email,
'url': url,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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
@ -141,74 +140,74 @@ 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({@required String userId, @required String secret, @required String passwordA, @required String passwordB}) async {
String path = '/account/recovery';
Future<Response> updateRecovery({@required String userId, @required String secret, @required String passwordA, @required String passwordB}) {
final String path = '/account/recovery';
Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
'password-a': passwordA,
'password-b': passwordB,
};
final Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
'password-a': passwordA,
'password-b': passwordB,
};
return await this.client.call(HttpMethod.put, path: path, params: params);
return this.client.call(HttpMethod.put, path: path, params: params);
}
/// Get currently logged in user list of active sessions across different
/// devices.
Future<Response> getSessions() async {
String path = '/account/sessions';
Future<Response> getSessions() {
final String path = '/account/sessions';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String email, @required String password}) async {
String path = '/account/sessions';
Future<Response> createSession({@required String email, @required String password}) {
final String path = '/account/sessions';
Map<String, dynamic> params = {
'email': email,
'password': password,
};
final Map<String, dynamic> params = {
'email': email,
'password': password,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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.
Future<Response> deleteSessions() async {
String path = '/account/sessions';
Future<Response> deleteSessions() {
final String path = '/account/sessions';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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({@required String provider, @required String success, @required String failure}) async {
String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider);
Future<Response> createOAuth2Session({@required String provider, @required String success, @required String failure}) {
final String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider);
Map<String, dynamic> params = {
'success': success,
'failure': failure,
};
final Map<String, dynamic> params = {
'success': success,
'failure': failure,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String sessionId}) async {
String path = '/account/sessions/{sessionId}'.replaceAll(RegExp('{sessionId}'), sessionId);
Future<Response> deleteSession({@required String sessionId}) {
final String path = '/account/sessions/{sessionId}'.replaceAll(RegExp('{sessionId}'), sessionId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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**
@ -223,27 +222,27 @@ 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({@required String url}) async {
String path = '/account/verification';
Future<Response> createVerification({@required String url}) {
final String path = '/account/verification';
Map<String, dynamic> params = {
'url': url,
};
final Map<String, dynamic> params = {
'url': url,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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({@required String userId, @required String secret}) async {
String path = '/account/verification';
Future<Response> updateVerification({@required String userId, @required String secret}) {
final String path = '/account/verification';
Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
};
final Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
};
return await this.client.call(HttpMethod.put, path: path, params: params);
return this.client.call(HttpMethod.put, path: path, params: params);
}
}

View file

@ -1,98 +1,97 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Avatars extends Service {
Avatars(Client client): super(client);
Avatars(Client client): super(client);
/// You can use this endpoint to show different browser icons to your users.
/// 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({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code);
Future<Response> getBrowser({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
final Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code);
Future<Response> getCreditCard({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
final Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String url}) async {
String path = '/avatars/favicon';
Future<Response> getFavicon({@required String url}) {
final String path = '/avatars/favicon';
Map<String, dynamic> params = {
'url': url,
};
final Map<String, dynamic> params = {
'url': url,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String code, int width = 100, int height = 100, int quality = 100}) async {
String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code);
Future<Response> getFlag({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code);
Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
final Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String url, int width = 400, int height = 400}) async {
String path = '/avatars/image';
Future<Response> getImage({@required String url, int width = 400, int height = 400}) {
final String path = '/avatars/image';
Map<String, dynamic> params = {
'url': url,
'width': width,
'height': height,
};
final Map<String, dynamic> params = {
'url': url,
'width': width,
'height': height,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String text, int size = 400, int margin = 1, int download = null}) async {
String path = '/avatars/qr';
Future<Response> getQR({@required String text, int size = 400, int margin = 1, int download = null}) {
final String path = '/avatars/qr';
Map<String, dynamic> params = {
'text': text,
'size': size,
'margin': margin,
'download': download,
};
final Map<String, dynamic> params = {
'text': text,
'size': size,
'margin': margin,
'download': download,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,82 +1,81 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Database extends Service {
Database(Client client): super(client);
Database(Client client): super(client);
/// Get a list of all the user documents. You can use the query params to
/// 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({@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);
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}) {
final String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
Map<String, dynamic> params = {
'filters': filters,
'offset': offset,
'limit': limit,
'order-field': orderField,
'order-type': orderType,
'order-cast': orderCast,
'search': search,
'first': first,
'last': last,
};
final Map<String, dynamic> params = {
'filters': filters,
'offset': offset,
'limit': limit,
'order-field': orderField,
'order-type': orderType,
'order-cast': orderCast,
'search': search,
'first': first,
'last': last,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
/// Create a new Document.
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);
Future<Response> createDocument({@required String collectionId, @required dynamic data, @required List read, @required List write, String parentDocument = null, String parentProperty = null, String parentPropertyType = 'assign'}) {
final String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
Map<String, dynamic> params = {
'data': data,
'read': read,
'write': write,
'parentDocument': parentDocument,
'parentProperty': parentProperty,
'parentPropertyType': parentPropertyType,
};
final Map<String, dynamic> params = {
'data': data,
'read': read,
'write': write,
'parentDocument': parentDocument,
'parentProperty': parentProperty,
'parentPropertyType': parentPropertyType,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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({@required String collectionId, @required String documentId}) async {
String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Future<Response> getDocument({@required String collectionId, @required String documentId}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
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);
Future<Response> updateDocument({@required String collectionId, @required String documentId, @required dynamic data, @required List read, @required List write}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
'data': data,
'read': read,
'write': write,
};
final Map<String, dynamic> params = {
'data': data,
'read': read,
'write': write,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return 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({@required String collectionId, @required String documentId}) async {
String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Future<Response> deleteDocument({@required String collectionId, @required String documentId}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return this.client.call(HttpMethod.delete, path: path, params: params);
}
}

View file

@ -1,15 +1,14 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Locale extends Service {
Locale(Client client): super(client);
Locale(Client client): super(client);
/// Get the current user location based on IP. Returns an object with user
/// country code, country name, continent name, continent code, ip address and
@ -17,63 +16,63 @@ class Locale extends Service {
/// supported language.
///
/// ([IP Geolocation by DB-IP](https://db-ip.com))
Future<Response> get() async {
String path = '/locale';
Future<Response> get() {
final String path = '/locale';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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.
Future<Response> getContinents() async {
String path = '/locale/continents';
Future<Response> getContinents() {
final String path = '/locale/continents';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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.
Future<Response> getCountries() async {
String path = '/locale/countries';
Future<Response> getCountries() {
final String path = '/locale/countries';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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.
Future<Response> getCountriesEU() async {
String path = '/locale/countries/eu';
Future<Response> getCountriesEU() {
final String path = '/locale/countries/eu';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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.
Future<Response> getCountriesPhones() async {
String path = '/locale/countries/phones';
Future<Response> getCountriesPhones() {
final String path = '/locale/countries/phones';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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
/// get the data in a supported language.
Future<Response> getCurrencies() async {
String path = '/locale/currencies';
Future<Response> getCurrencies() {
final String path = '/locale/currencies';
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,114 +1,113 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Storage extends Service {
Storage(Client client): super(client);
Storage(Client client): super(client);
/// 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({String search = null, int limit = 25, int offset = null, String orderType = 'ASC'}) async {
String path = '/storage/files';
Future<Response> listFiles({String search = null, int limit = 25, int offset = null, OrderType orderType = OrderType.asc}) {
final String path = '/storage/files';
Map<String, dynamic> params = {
'search': search,
'limit': limit,
'offset': offset,
'orderType': orderType,
};
final Map<String, dynamic> params = {
'search': search,
'limit': limit,
'offset': offset,
'orderType': orderType.name(),
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required File file, @required List read, @required List write}) async {
String path = '/storage/files';
Future<Response> createFile({@required file, @required List read, @required List write}) {
final String path = '/storage/files';
Map<String, dynamic> params = {
'file': file,
'read': read,
'write': write,
};
final Map<String, dynamic> params = {
'file': file,
'read': read,
'write': write,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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({@required String fileId}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Future<Response> getFile({@required String fileId}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String fileId, @required List read, @required List write}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Future<Response> updateFile({@required String fileId, @required List read, @required List write}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
'read': read,
'write': write,
};
final Map<String, dynamic> params = {
'read': read,
'write': write,
};
return await this.client.call(HttpMethod.put, path: path, params: params);
return 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({@required String fileId}) async {
String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Future<Response> deleteFile({@required String fileId}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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({@required String fileId}) async {
String path = '/storage/files/{fileId}/download'.replaceAll(RegExp('{fileId}'), fileId);
Future<Response> getFileDownload({@required String fileId}) {
final String path = '/storage/files/{fileId}/download'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@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);
Future<Response> getFilePreview({@required String fileId, int width = null, int height = null, int quality = 100, String background = null, String output = null}) {
final String path = '/storage/files/{fileId}/preview'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
'background': background,
'output': output,
};
final Map<String, dynamic> params = {
'width': width,
'height': height,
'quality': quality,
'background': background,
'output': output,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String fileId, String as = null}) async {
String path = '/storage/files/{fileId}/view'.replaceAll(RegExp('{fileId}'), fileId);
Future<Response> getFileView({@required String fileId, String as = null}) {
final String path = '/storage/files/{fileId}/view'.replaceAll(RegExp('{fileId}'), fileId);
Map<String, dynamic> params = {
'as': as,
};
final Map<String, dynamic> params = {
'as': as,
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return this.client.call(HttpMethod.get, path: path, params: params);
}
}

View file

@ -1,85 +1,84 @@
import 'dart:html';
import "package:appwrite/service.dart";
import "package:appwrite/client.dart";
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Teams extends Service {
Teams(Client client): super(client);
Teams(Client client): super(client);
/// 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({String search = null, int limit = 25, int offset = null, String orderType = 'ASC'}) async {
String path = '/teams';
Future<Response> list({String search = null, int limit = 25, int offset = null, OrderType orderType = OrderType.asc}) {
final String path = '/teams';
Map<String, dynamic> params = {
'search': search,
'limit': limit,
'offset': offset,
'orderType': orderType,
};
final Map<String, dynamic> params = {
'search': search,
'limit': limit,
'offset': offset,
'orderType': orderType.name(),
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String name, List roles = const ["owner"]}) async {
String path = '/teams';
Future<Response> create({@required String name, List roles = const ["owner"]}) {
final String path = '/teams';
Map<String, dynamic> params = {
'name': name,
'roles': roles,
};
final Map<String, dynamic> params = {
'name': name,
'roles': roles,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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({@required String teamId}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Future<Response> get({@required String teamId}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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({@required String teamId, @required String name}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Future<Response> update({@required String teamId, @required String name}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
'name': name,
};
final Map<String, dynamic> params = {
'name': name,
};
return await this.client.call(HttpMethod.put, path: path, params: params);
return 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({@required String teamId}) async {
String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Future<Response> delete({@required String teamId}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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({@required String teamId}) async {
String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
Future<Response> getMemberships({@required String teamId}) {
final String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.get, path: path, params: params);
return 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
@ -94,40 +93,40 @@ 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({@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);
Future<Response> createMembership({@required String teamId, @required String email, @required List roles, @required String url, String name = null}) {
final String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
Map<String, dynamic> params = {
'email': email,
'name': name,
'roles': roles,
'url': url,
};
final Map<String, dynamic> params = {
'email': email,
'name': name,
'roles': roles,
'url': url,
};
return await this.client.call(HttpMethod.post, path: path, params: params);
return 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({@required String teamId, @required String inviteId}) async {
String path = '/teams/{teamId}/memberships/{inviteId}'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
Future<Response> deleteMembership({@required String teamId, @required String inviteId}) {
final String path = '/teams/{teamId}/memberships/{inviteId}'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
Map<String, dynamic> params = {
};
final Map<String, dynamic> params = {
};
return await this.client.call(HttpMethod.delete, path: path, params: params);
return 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({@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);
Future<Response> updateMembershipStatus({@required String teamId, @required String inviteId, @required String userId, @required String secret}) {
final String path = '/teams/{teamId}/memberships/{inviteId}/status'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
};
final Map<String, dynamic> params = {
'userId': userId,
'secret': secret,
};
return await this.client.call(HttpMethod.patch, path: path, params: params);
return this.client.call(HttpMethod.patch, path: path, params: params);
}
}

View file

@ -0,0 +1,89 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.12"
cookie_jar:
dependency: "direct main"
description:
name: cookie_jar
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.9"
dio_cookie_manager:
dependency: "direct main"
description:
name: dio_cookie_manager
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
meta:
dependency: "direct main"
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
sdks:
dart: ">=2.6.0 <3.0.0"

View file

@ -1,11 +1,11 @@
name: appwrite
version: 0.0.7
version: 0.0.8
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@appwrite.io>
homepage: https://github.com/appwrite/sdk-for-dart
environment:
sdk: '>=2.6.0 <3.0.0'
dependencies:
meta: ^1.1.8
dio: ^3.0.0
cookie_jar: ^1.0.0
dio_cookie_manager: ^1.0.0
dio_cookie_manager: ^1.0.0

View file

@ -0,0 +1 @@
# Change Log

View file

@ -3,7 +3,7 @@
![License](https://img.shields.io/github/license/appwrite/sdk-for-go.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.**
**This SDK is compatible with Appwrite server version 0.5.3. For older versions, please check previous releases.**
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)

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -3,7 +3,7 @@
![License](https://img.shields.io/github/license/appwrite/sdk-for-python.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.**
**This SDK is compatible with Appwrite server version 0.5.3. For older versions, please check previous releases.**
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)

View file

@ -0,0 +1 @@
# Change Log

View file

@ -3,7 +3,7 @@
![License](https://img.shields.io/github/license/appwrite/sdk-for-ruby.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.**
**This SDK is compatible with Appwrite server version 0.5.3. For older versions, please check previous releases.**
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)

View file

@ -0,0 +1 @@
# Change Log

View file

@ -31,6 +31,21 @@ To install with a CDN (content delivery network) add the following scripts to th
<script src="https://cdn.jsdelivr.net/npm/appwrite@1.0.29"></script>
```
## Getting Started
Initialise the Appwrite SDK in your code, and setup your API credentials:
```js
// Init your JS SDK
var appwrite = new Appwrite();
appwrite
.setEndpoint('http://localhost/v1') // Set only when using self-hosted solution
.setProject('455x34dfkj') // Your Appwrite Project UID
;
```
## Contribution

View file

@ -25,7 +25,7 @@ $warning = '**This SDK is compatible with Appwrite server version ' . $version .
$cli
->task('generate')
->action(function () use ($warning) {
->action(function () use ($warning, $version) {
function getSSLPage($url)
{
$ch = curl_init();
@ -58,8 +58,10 @@ $cli
$result = realpath(__DIR__.'/..').'/sdks/'.$key.'-'.$language['key'];
$target = realpath(__DIR__.'/..').'/sdks/git/'.$language['key'].'/';
$readme = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'.md');
$readme = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/README.md');
$readme = ($readme) ? file_get_contents($readme) : '';
$changelog = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/CHANGELOG.md');
$changelog = ($changelog) ? file_get_contents($changelog) : '# Change Log';
$warning = ($language['beta']) ? '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check previous releases.**' : '';
$license = 'BSD-3-Clause';
$licenseContent = 'Copyright (c) 2019 Appwrite (https://appwrite.io) and individual contributors.
@ -119,9 +121,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
break;
case 'dart':
$config = new Dart();
$config
->setPackageName('appwrite')
;
break;
case 'go':
$config = new Go();
@ -151,6 +150,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
->setShareVia('appwrite_io')
->setWarning($warning)
->setReadme($readme)
->setChangelog($changelog)
;
try {

View file

@ -6,7 +6,7 @@ $projectName = $this->getParam('projectName', '');
$projectURL = $this->getParam('projectURL', '');
?>
<section class="zone large margin-top-xl">
<section class="zone large margin-top padding">
<h1 class="margin-bottom">Error <?php echo $code; ?></h1>
<p><?php echo $message; ?></p>

View file

@ -0,0 +1,13 @@
<div class="zone large padding margin-top" id="message" style="display: none">
<h1 class="margin-bottom">Missing Redirect URL</h1>
<p>Your OAuth login flow is missing a redirect URL. Please check the <a href="https://<?php echo APP_DOMAIN; ?>/docs/account?platform=web&language=javascript#createOAuth2Session">OAuth docs</a> and send request for new session with a valid callback URL.</p>
</div>
<script>
setTimeout(function () {
document.getElementById('message').style.display = 'block';
}, 25);
window.location = 'appwrite-callback://'+window.location.search;
</script>
<hr />

12
composer.lock generated
View file

@ -1622,7 +1622,7 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator",
"reference": "97cb12c9c187a42a545060c324b0960c99582893"
"reference": "3b7389388f29c6e0cf53cf2233ee516fb20ad9f7"
},
"require": {
"ext-curl": "*",
@ -1652,7 +1652,7 @@
}
],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"time": "2020-03-27T15:12:28+00:00"
"time": "2020-04-05T20:13:47+00:00"
},
{
"name": "doctrine/instantiator",
@ -3252,12 +3252,12 @@
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "6df2e2c3181e6d0b961fc341fbe8269fefc933c6"
"reference": "e3ff236877694af42d51506dd7476a224fb829fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/6df2e2c3181e6d0b961fc341fbe8269fefc933c6",
"reference": "6df2e2c3181e6d0b961fc341fbe8269fefc933c6",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/e3ff236877694af42d51506dd7476a224fb829fb",
"reference": "e3ff236877694af42d51506dd7476a224fb829fb",
"shasum": ""
},
"require": {
@ -3309,7 +3309,7 @@
"keywords": [
"templating"
],
"time": "2020-03-27T16:41:01+00:00"
"time": "2020-03-31T06:42:10+00:00"
},
{
"name": "webmozart/assert",

View file

@ -0,0 +1,4 @@
## 0.0.8
- Fixed compilation error in Client class
- Shorter description for package

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -0,0 +1 @@
# Change Log

View file

@ -1,5 +1,7 @@
The database service allows you to create structured document collections, query and filter lists of documents, and manage an advanced set of read and write access.
The database service allows you to create structured collections of documents, query and filter lists of documents, and manage an advanced set of read and write access.
All the data in the database service is stored in JSON format. The service also allows you to nest child documents and use advanced filters to search and query the database just like you would with a classic graph database.
All the data in the database service is stored in structured JSON documents. The Appwrite database service also allows you to nest child documents in documents and use advanced filters to both search and query the database just like you would with a classic graph database.
By leveraging the database permission management, you can assign read or write access to the database documents for a specific user, team, user role, or even grant public access to all visitors to your project. You can learn more about [how Appwrite handles permissions and role access control](/docs/permissions).
Each database document structure in your project is defined using the Appwrite [collection rules](/docs/rules). The collections rules help you ensure all your user-submitted data is validated and stored according to the collection structure.
Using Appwrite permissions architecture, you can assign read or write access to each document in your project for either a specific user, team, user role, or even grant it with public access. You can learn more about [how Appwrite handles permissions and access control](/docs/permissions).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,8 @@
.padding {
padding: 30px;
}
.margin-end {
.func-margin-end(20px)!important;
}

View file

@ -173,10 +173,14 @@ class MySQL extends Adapter
$st->execute();
$oldSignature = $st->fetch()['signature'];
$result = $st->fetch();
if ($signature === $oldSignature) {
return $data;
if($result && isset($result['signature'])) {
$oldSignature = $result['signature'];
if ($signature === $oldSignature) {
return $data;
}
}
}

78
src/Appwrite/URL/URL.php Normal file
View file

@ -0,0 +1,78 @@
<?php
namespace Appwrite\URL;
class URL
{
/**
* Parse URL
*
* Take a URL string and split it to array parts
*
* @param $url string
*
* @return array
*/
static public function parse(string $url):array
{
$default = [
'scheme' => '',
'pass' => '',
'user' => '',
'host' => '',
'port' => null,
'path' => '',
'query' => '',
'fragment' => '',
];
return array_merge($default, parse_url($url));
}
/**
* Un-Parse URL
*
* Take URL parts and combine them to a valid string
*
* @param $url array
* @param $ommit array
*
* @return string
*/
static public function unparse(array $url, array $ommit = []):string
{
if (isset($url['path']) && mb_substr($url['path'], 0, 1) !== '/') {
$url['path'] = '/'.$url['path'];
}
$parts = [];
$parts['scheme'] = isset($url['scheme']) ? $url['scheme'].'://' : '';
$parts['host'] = isset($url['host']) ? $url['host'] : '';
$parts['port'] = isset($url['port']) ? ':'.$url['port'] : '';
$parts['user'] = isset($url['user']) ? $url['user'] : '';
$parts['pass'] = isset($url['pass']) ? ':'.$url['pass'] : '';
$parts['pass'] = ($parts['user'] || $parts['pass']) ? $parts['pass'].'@' : '';
$parts['path'] = isset($url['path']) ? $url['path'] : '';
$parts['query'] = isset($url['query']) && !empty($url['query']) ? '?'.$url['query'] : '';
$parts['fragment'] = isset($url['fragment']) ? '#'.$url['fragment'] : '';
if ($ommit) {
foreach ($ommit as $key) {
if (isset($parts[ $key ])) {
$parts[ $key ] = '';
}
}
}
return $parts['scheme'].$parts['user'].$parts['pass'].$parts['host'].$parts['port'].$parts['path'].$parts['query'].$parts['fragment'];
}
}

View file

@ -0,0 +1,90 @@
<?php
namespace Appwrite\Tests;
use Appwrite\URL\URL;
use PHPUnit\Framework\TestCase;
class URLTest extends TestCase
{
public function testParse()
{
$url = URL::parse('https://appwrite.io:8080/path?query=string&param=value');
$this->assertIsArray($url);
$this->assertEquals('https', $url['scheme']);
$this->assertEquals('appwrite.io', $url['host']);
$this->assertEquals('8080', $url['port']);
$this->assertEquals('/path', $url['path']);
$this->assertEquals('query=string&param=value', $url['query']);
$url = URL::parse('https://appwrite.io');
$this->assertIsArray($url);
$this->assertEquals('https', $url['scheme']);
$this->assertEquals('appwrite.io', $url['host']);
$this->assertEquals(null, $url['port']);
$this->assertEquals('', $url['path']);
$this->assertEquals('', $url['query']);
}
public function testUnparse()
{
$url = URL::unparse([
'scheme' => 'https',
'host' => 'appwrite.io',
'port' => 8080,
'path' => '/path',
'query' => 'query=string&param=value',
]);
$this->assertIsString($url);
$this->assertEquals('https://appwrite.io:8080/path?query=string&param=value', $url);
$url = URL::unparse([
'scheme' => 'https',
'host' => 'appwrite.io',
'port' => null,
'path' => '/path',
'query' => 'query=string&param=value',
]);
$this->assertIsString($url);
$this->assertEquals('https://appwrite.io/path?query=string&param=value', $url);
$url = URL::unparse([
'scheme' => 'https',
'host' => 'appwrite.io',
'port' => null,
'path' => '',
'query' => '',
]);
$this->assertIsString($url);
$this->assertEquals('https://appwrite.io/', $url);
$url = URL::unparse([
'scheme' => 'https',
'host' => 'appwrite.io',
'port' => null,
'path' => '',
'fragment' => 'bottom',
]);
$this->assertIsString($url);
$this->assertEquals('https://appwrite.io/#bottom', $url);
$url = URL::unparse([
'scheme' => 'https',
'user' => 'eldad',
'pass' => 'fux',
'host' => 'appwrite.io',
'port' => null,
'path' => '',
'fragment' => 'bottom',
]);
$this->assertIsString($url);
$this->assertEquals('https://eldad:fux@appwrite.io/#bottom', $url);
}
}