diff --git a/app/controllers/database.php b/app/controllers/database.php index 73c829256..34294c913 100644 --- a/app/controllers/database.php +++ b/app/controllers/database.php @@ -19,42 +19,8 @@ use Database\Validator\Authorization; use Database\Exception\Authorization as AuthorizationException; use Database\Exception\Structure as StructureException; -$output = array(); - $isDev = (App::ENV_TYPE_PRODUCTION !== $utopia->getEnv()); -$utopia - ->shutdown( - function () use ($request, $response, $projectDB, $register, &$output) { - /*$lastModified = $projectDB->lastModified(); - $etag = md5(json_encode($output)); - $ifNotModelledSince = strtotime($request->getServer('HTTP_IF_MODIFIED_SINCE', 'now')); - $ifNoneMatch = trim($request->getServer('HTTP_IF_NONE_MATCH', '')); - - // exit if not modified - if ($ifNotModelledSince === $lastModified || $ifNoneMatch == $etag) { - return $response - ->setStatusCode(304) - ->send('', 100); - } - else { - $response - ->addHeader('Cache-Control', 'private, max-age=0') // max-age=' . (60 * 60 * 24 * 30) 1 month - ->addHeader('Last-Modified', gmdate('D, d M Y H:i:s', $lastModified) . ' GMT') - ->addHeader('Etag', $etag) - ; - } - */ - - // Debug Stats - //$cache = $register->get('cache'); /* @var $cache Debug\Redis */ - - //$response - // ->addHeader('X-Debug-Cache-Hit', $cache::getCounter('get') + $cache::getCounter('mget')) - // ->addHeader('X-Debug-Cache-Miss', $cache::getCounter('set')); - } - ); - $utopia->get('/v1/database') ->desc('List Collections') ->label('scope', 'collections.read') @@ -131,9 +97,21 @@ $utopia->post('/v1/database') ->param('name', '', function () {return new Text(256);}, 'Collection name.') ->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of read permissions. [Learn more about permissions and roles](/docs/permissions).', true) ->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of write permissions. [Learn more about permissions and roles](/docs/permissions).', true) - ->param('rules', [], function () use ($projectDB) {return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES]));}, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation', true) + ->param('rules', [], function () use ($projectDB) {return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]]));}, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation', true) ->action( - function ($name, $read, $write, $rules) use ($response, $projectDB, &$output, $webhook, $audit, $isDev) { + function ($name, $read, $write, $rules) use ($response, $projectDB, $webhook, $audit) { + $parsedRules = []; + + foreach($rules as &$rule) { + $parsedRules[] = array_merge([ + '$collection' => Database::SYSTEM_COLLECTION_RULES, + '$permissions' => [ + 'read' => $read, + 'write' => $write, + ] + ], $rule); + } + try { $data = $projectDB->createDocument([ '$collection' => Database::SYSTEM_COLLECTION_COLLECTIONS, @@ -145,7 +123,7 @@ $utopia->post('/v1/database') 'read' => $read, 'write' => $write, ], - 'rules' => $rules, + 'rules' => $parsedRules, ]); } catch (AuthorizationException $exception) { throw new Exception('Unauthorized action', 401); @@ -187,7 +165,7 @@ $utopia->put('/v1/database/:collectionId') ->param('name', null, function () {return new Text(256);}, 'Collection name.') ->param('read', [], function () {return new ArrayList(new Text(64));}, 'An array of read permissions. [Learn more about permissions and roles](/docs/permissions).', true) ->param('write', [], function () {return new ArrayList(new Text(64));}, 'An array of write permissions. [Learn more about permissions and roles](/docs/permissions).', true) - ->param('rules', [], function () use ($projectDB) {return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES]));}, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation', true) + ->param('rules', [], function () use ($projectDB) {return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]]));}, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation', true) ->action( function ($collectionId, $name, $read, $write, $rules) use ($response, $projectDB) { $collection = $projectDB->getDocument($collectionId, false); @@ -195,6 +173,18 @@ $utopia->put('/v1/database/:collectionId') if (empty($collection->getUid()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) { throw new Exception('Collection not found', 404); } + + $parsedRules = []; + + foreach($rules as &$rule) { + $parsedRules[] = array_merge([ + '$collection' => Database::SYSTEM_COLLECTION_RULES, + '$permissions' => [ + 'read' => $read, + 'write' => $write, + ] + ], $rule); + } $collection = $projectDB->updateDocument(array_merge($collection->getArrayCopy(), [ 'name' => $name, @@ -261,7 +251,7 @@ $utopia->get('/v1/database/:collectionId/documents') ->param('first', 0, function () {return new Range(0, 1);}, 'Return only first document. Pass 1 for true or 0 for false. The default value is 0.', true) ->param('last', 0, function () {return new Range(0, 1);}, 'Return only last document. Pass 1 for true or 0 for false. The default value is 0.', true) ->action( - function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $first, $last) use ($response, $request, $projectDB, &$output, $isDev) { + function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $first, $last) use ($response, $projectDB, $isDev) { $collection = $projectDB->getDocument($collectionId, $isDev); if (is_null($collection->getUid()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) { @@ -319,7 +309,7 @@ $utopia->get('/v1/database/:collectionId/documents/:documentId') ->param('collectionId', null, function () {return new UID();}, 'Collection unique ID') ->param('documentId', null, function () {return new UID();}, 'Document unique ID') ->action( - function ($collectionId, $documentId) use ($response, $request, $projectDB, &$output, $isDev) { + function ($collectionId, $documentId) use ($response, $request, $projectDB, $isDev) { $document = $projectDB->getDocument($documentId, $isDev); $collection = $projectDB->getDocument($collectionId, $isDev); @@ -342,7 +332,6 @@ $utopia->get('/v1/database/:collectionId/documents/:documentId') $output = ($output instanceof Document) ? $output->getArrayCopy() : $output; - var_dump($output); if (!is_array($output)) { throw new Exception('No document found', 404); } @@ -370,7 +359,7 @@ $utopia->post('/v1/database/:collectionId/documents') ->param('parentProperty', '', function () {return new Key();}, 'Parent document property name. Use when you want your new document to be a child of a parent document.', true) ->param('parentPropertyType', Document::SET_TYPE_ASSIGN, function () {return new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND]);}, 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true) ->action( - function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType) use ($response, $projectDB, &$output, $webhook, $audit, $isDev) { + function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType) use ($response, $projectDB, $webhook, $audit) { if (empty($data)) { throw new Exception('Missing payload', 400); } diff --git a/app/sdks/dart/lib/client.dart b/app/sdks/dart/lib/client.dart new file mode 100644 index 000000000..0aec1c081 --- /dev/null +++ b/app/sdks/dart/lib/client.dart @@ -0,0 +1,99 @@ +import 'package:dio/dio.dart'; +import 'package:dio_cookie_manager/dio_cookie_manager.dart'; +import 'package:cookie_jar/cookie_jar.dart'; + +class Client { + String endPoint; + Map headers; + bool selfSigned; + Dio http; + + Client() { + this.endPoint = 'https://appwrite.test/v1'; + this.headers = { + 'content-type': 'application/json', + 'x-sdk-version': 'appwrite:dart:v0.0.1', + }; + this.selfSigned = false; + + this.http = Dio(); + this.http.options.baseUrl = this.endPoint; + this.http.options.validateStatus = (status) => status != 404; + this.http.interceptors.add(CookieManager(CookieJar())); + } + + + /// Your Appwrite project ID. You can find your project ID in your Appwrite console project settings. + Client setProject(value) { + this.addHeader('X-Appwrite-Project', value); + + return this; + } + + + /// Your Appwrite project secret key. You can can create a new API key from your Appwrite console API keys dashboard. + Client setKey(value) { + this.addHeader('X-Appwrite-Key', value); + + return this; + } + + + Client setLocale(value) { + this.addHeader('X-Appwrite-Locale', value); + + return this; + } + + + Client setMode(value) { + this.addHeader('X-Appwrite-Mode', value); + + return this; + } + + Client setSelfSigned({bool status = true}) { + this.selfSigned = status; + + return this; + } + + 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(); + + return this; + } + + Future call(String method, {String path = '', Map headers = const {}, Map params = const {}}) { + if(this.selfSigned) { + // Allow self signed requests + } + + String reqPath = path; + bool isGet = method.toUpperCase() == "GET"; + + Options options = Options( + headers: {...this.headers, ...headers}, + method: method.toUpperCase(), + ); + + if (isGet) { + path += "?"; + params.forEach((k, v) { + path += "${k}=${v}&"; + }); + } + + if (!isGet) + return http.request(reqPath, data: params, options: options); + else + return http.request(reqPath, options: options); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/dart_appwrite.dart b/app/sdks/dart/lib/dart_appwrite.dart new file mode 100644 index 000000000..3627df32d --- /dev/null +++ b/app/sdks/dart/lib/dart_appwrite.dart @@ -0,0 +1,11 @@ +export 'package:dart_appwrite/services/account.dart'; +export 'package:dart_appwrite/services/auth.dart'; +export 'package:dart_appwrite/services/avatars.dart'; +export 'package:dart_appwrite/services/database.dart'; +export 'package:dart_appwrite/services/locale.dart'; +export 'package:dart_appwrite/services/projects.dart'; +export 'package:dart_appwrite/services/storage.dart'; +export 'package:dart_appwrite/services/teams.dart'; +export 'package:dart_appwrite/services/users.dart'; +export 'package:dart_appwrite/client.dart'; +export 'package:dio/dio.dart' show Response; \ No newline at end of file diff --git a/app/sdks/dart/lib/service.dart b/app/sdks/dart/lib/service.dart new file mode 100644 index 000000000..11bbeac2a --- /dev/null +++ b/app/sdks/dart/lib/service.dart @@ -0,0 +1,9 @@ +import 'package:dart_appwrite/client.dart'; + +class Service { + Client client; + + Service(Client client) { + this.client = client; + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/account.dart b/app/sdks/dart/lib/services/account.dart new file mode 100644 index 000000000..60a7a2592 --- /dev/null +++ b/app/sdks/dart/lib/services/account.dart @@ -0,0 +1,103 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Account extends Service { + + Account(Client client): super(client); + + /// Get currently logged in user data as JSON object. + Future get() async { + String path = '/account'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Delete currently logged in user account. + Future delete() async { + String path = '/account'; + + Map params = { + }; + + return await this.client.call('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 updateEmail({email, password}) async { + String path = '/account/email'; + + Map params = { + 'email': email, + 'password': password, + }; + + return await this.client.call('patch', path: path, params: params); + } + /// Update currently logged in user account name. + Future updateName({name}) async { + String path = '/account/name'; + + Map params = { + 'name': name, + }; + + return await this.client.call('patch', path: path, params: params); + } + /// Update currently logged in user password. For validation, user is required + /// to pass the password twice. + Future updatePassword({password, oldPassword}) async { + String path = '/account/password'; + + Map params = { + 'password': password, + 'old-password': oldPassword, + }; + + return await this.client.call('patch', path: path, params: params); + } + /// Get currently logged in user preferences key-value object. + Future getPrefs() async { + String path = '/account/prefs'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Update currently logged in user account preferences. You can pass only the + /// specific settings you wish to update. + Future updatePrefs({prefs}) async { + String path = '/account/prefs'; + + Map params = { + 'prefs': prefs, + }; + + return await this.client.call('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 getSecurity() async { + String path = '/account/security'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Get currently logged in user list of active sessions across different + /// devices. + Future getSessions() async { + String path = '/account/sessions'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/auth.dart b/app/sdks/dart/lib/services/auth.dart new file mode 100644 index 000000000..272ece558 --- /dev/null +++ b/app/sdks/dart/lib/services/auth.dart @@ -0,0 +1,179 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Auth extends Service { + + Auth(Client client): super(client); + + /// Allow the user to login into his account by providing a valid email and + /// password combination. Use the success and failure arguments to provide a + /// redirect URL\'s back to your app when login is completed. + /// + /// Please notice that in order to avoid a [Redirect + /// 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. + /// + /// When not using the success or failure redirect arguments this endpoint will + /// result with a 200 status code and the user account object on success and + /// with 401 status error on failure. This behavior was applied to help the web + /// clients deal with browsers who don't allow to set 3rd party HTTP cookies + /// needed for saving the account session token. + Future login({email, password, success, failure}) async { + String path = '/auth/login'; + + Map params = { + 'email': email, + 'password': password, + 'success': success, + 'failure': failure, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Use this endpoint to log out the currently logged in user from his account. + /// When succeed this endpoint will delete the user session and remove the + /// session secret cookie from the user client. + Future logout() async { + String path = '/auth/logout'; + + Map params = { + }; + + return await this.client.call('delete', 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 logoutBySession({id}) async { + String path = '/auth/logout/{id}'.replaceAll(RegExp('{id}'), id); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + Future oauthCallback({projectId, provider, code, state = null}) async { + String path = '/auth/oauth/callback/{provider}/{projectId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{provider}'), provider); + + Map params = { + 'code': code, + 'state': state, + }; + + return await this.client.call('get', path: path, params: params); + } + Future oauth({provider, success = null, failure = null}) async { + String path = '/auth/oauth/{provider}'.replaceAll(RegExp('{provider}'), provider); + + Map params = { + 'success': success, + 'failure': failure, + }; + + return await this.client.call('get', path: path, params: params); + } + /// Sends the user an email with a temporary secret token for password reset. + /// When the user clicks the confirmation link he is redirected back to your + /// app password reset redirect URL with a secret token and email address + /// values attached to the URL query string. Use the query string params to + /// submit a request to the /auth/password/reset endpoint to complete the + /// process. + Future recovery({email, redirect}) async { + String path = '/auth/recovery'; + + Map params = { + 'email': email, + 'redirect': redirect, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Use this endpoint to complete the user account password reset. Both the + /// **userId** and **token** arguments will be passed as query parameters to + /// the redirect URL you have provided when sending your request to the + /// /auth/recovery endpoint. + /// + /// Please notice that in order to avoid a [Redirect + /// 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 recoveryReset({userId, token, passwordA, passwordB}) async { + String path = '/auth/recovery/reset'; + + Map params = { + 'userId': userId, + 'token': token, + 'password-a': passwordA, + 'password-b': passwordB, + }; + + return await this.client.call('put', path: path, params: params); + } + /// Use this endpoint to allow a new user to register an account in your + /// project. Use the success and failure URL's to redirect users back to your + /// application after signup completes. + /// + /// If registration completes successfully user will be sent with a + /// confirmation email in order to confirm he is the owner of the account email + /// address. Use the redirect parameter to redirect the user from the + /// confirmation email back to your app. When the user is redirected, use the + /// /auth/confirm endpoint to complete the account confirmation. + /// + /// Please notice that in order to avoid a [Redirect + /// 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. + /// + /// When not using the success or failure redirect arguments this endpoint will + /// result with a 200 status code and the user account object on success and + /// with 401 status error on failure. This behavior was applied to help the web + /// clients deal with browsers who don't allow to set 3rd party HTTP cookies + /// needed for saving the account session token. + Future register({email, password, redirect, success, failure, name = null}) async { + String path = '/auth/register'; + + Map params = { + 'email': email, + 'password': password, + 'redirect': redirect, + 'success': success, + 'failure': failure, + 'name': name, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Use this endpoint to complete the confirmation of the user account email + /// address. Both the **userId** and **token** arguments will be passed as + /// query parameters to the redirect URL you have provided when sending your + /// request to the /auth/register endpoint. + Future confirm({userId, token}) async { + String path = '/auth/register/confirm'; + + Map params = { + 'userId': userId, + 'token': token, + }; + + return await this.client.call('post', path: path, params: params); + } + /// This endpoint allows the user to request your app to resend him his email + /// confirmation message. The redirect arguments acts the same way as in + /// /auth/register endpoint. + /// + /// Please notice that in order to avoid a [Redirect + /// 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 confirmResend({redirect}) async { + String path = '/auth/register/confirm/resend'; + + Map params = { + 'redirect': redirect, + }; + + return await this.client.call('post', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/avatars.dart b/app/sdks/dart/lib/services/avatars.dart new file mode 100644 index 000000000..ab5d68997 --- /dev/null +++ b/app/sdks/dart/lib/services/avatars.dart @@ -0,0 +1,93 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Avatars extends Service { + + 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 appear in your user + /// /account/sessions endpoint. Use width, height and quality arguments to + /// change the output settings. + Future getBrowser({code, width = 100, height = 100, quality = 100}) async { + String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code); + + Map params = { + 'width': width, + 'height': height, + 'quality': quality, + }; + + return await this.client.call('get', path: path, params: params); + } + /// Need to display your users with your billing method or there 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 getCreditCard({code, width = 100, height = 100, quality = 100}) async { + String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code); + + Map params = { + 'width': width, + 'height': height, + 'quality': quality, + }; + + return await this.client.call('get', path: path, params: params); + } + /// Use this endpoint to fetch the favorite icon (AKA favicon) of a any remote + /// website URL. + Future getFavicon({url}) async { + String path = '/avatars/favicon'; + + Map params = { + 'url': url, + }; + + return await this.client.call('get', path: path, params: params); + } + /// You can use this endpoint to show different country flags icons to your + /// users, The code argument receives the a 2 letter country code. Use width, + /// height and quality arguments to change the output settings. + Future getFlag({code, width = 100, height = 100, quality = 100}) async { + String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code); + + Map params = { + 'width': width, + 'height': height, + 'quality': quality, + }; + + return await this.client.call('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 cases, you want to make sure a 3rd party + /// image is properly served using a TLS protocol. + Future getImage({url, width = 400, height = 400}) async { + String path = '/avatars/image'; + + Map params = { + 'url': url, + 'width': width, + 'height': height, + }; + + return await this.client.call('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 getQR({text, size = 400, margin = 1, download = null}) async { + String path = '/avatars/qr'; + + Map params = { + 'text': text, + 'size': size, + 'margin': margin, + 'download': download, + }; + + return await this.client.call('get', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/database.dart b/app/sdks/dart/lib/services/database.dart new file mode 100644 index 000000000..a1674d818 --- /dev/null +++ b/app/sdks/dart/lib/services/database.dart @@ -0,0 +1,139 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Database extends Service { + + Database(Client client): super(client); + + /// Get a list of all the user collections. You can use the query params to + /// filter your results. On admin mode, this endpoint will return a list of all + /// of the project collections. [Learn more about different API + /// modes](/docs/modes). + Future listCollections({search = null, limit = 25, offset = null, orderType = 'ASC'}) async { + String path = '/database'; + + Map params = { + 'search': search, + 'limit': limit, + 'offset': offset, + 'orderType': orderType, + }; + + return await this.client.call('get', path: path, params: params); + } + /// Create a new Collection. + Future createCollection({name, read = const [], write = const [], rules = const []}) async { + String path = '/database'; + + Map params = { + 'name': name, + 'read': read, + 'write': write, + 'rules': rules, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Get collection by its unique ID. This endpoint response returns a JSON + /// object with the collection metadata. + Future getCollection({collectionId}) async { + String path = '/database/{collectionId}'.replaceAll(RegExp('{collectionId}'), collectionId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Update collection by its unique ID. + Future updateCollection({collectionId, name, read = const [], write = const [], rules = const []}) async { + String path = '/database/{collectionId}'.replaceAll(RegExp('{collectionId}'), collectionId); + + Map params = { + 'name': name, + 'read': read, + 'write': write, + 'rules': rules, + }; + + return await this.client.call('put', path: path, params: params); + } + /// Delete a collection by its unique ID. Only users with write permissions + /// have access to delete this resource. + Future deleteCollection({collectionId}) async { + String path = '/database/{collectionId}'.replaceAll(RegExp('{collectionId}'), collectionId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + /// 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/modes). + Future listDocuments({collectionId, filters = const [], offset = null, limit = 50, orderField = '\$uid', orderType = 'ASC', orderCast = 'string', search = null, first = null, last = null}) async { + String path = '/database/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId); + + Map 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('get', path: path, params: params); + } + /// Create a new Document. + Future createDocument({collectionId, data, read = const [], write = const [], parentDocument = null, parentProperty = null, parentPropertyType = 'assign'}) async { + String path = '/database/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId); + + Map params = { + 'data': data, + 'read': read, + 'write': write, + 'parentDocument': parentDocument, + 'parentProperty': parentProperty, + 'parentPropertyType': parentPropertyType, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Get document by its unique ID. This endpoint response returns a JSON object + /// with the document data. + Future getDocument({collectionId, documentId}) async { + String path = '/database/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updateDocument({collectionId, documentId, data, read = const [], write = const []}) async { + String path = '/database/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId); + + Map params = { + 'data': data, + 'read': read, + 'write': write, + }; + + return await this.client.call('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 deleteDocument({collectionId, documentId}) async { + String path = '/database/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/locale.dart b/app/sdks/dart/lib/services/locale.dart new file mode 100644 index 000000000..5e592b59e --- /dev/null +++ b/app/sdks/dart/lib/services/locale.dart @@ -0,0 +1,63 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Locale extends Service { + + 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 + /// suggested currency. You can use the locale header to get the data in + /// supported language. + Future getLocale() async { + String path = '/locale'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// List of all countries. You can use the locale header to get the data in + /// supported language. + Future getCountries() async { + String path = '/locale/countries'; + + Map params = { + }; + + return await this.client.call('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 supported language. UK brexit date is + /// currently set to 2019-10-31 and will be updated if and when needed. + Future getCountriesEU() async { + String path = '/locale/countries/eu'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// List of all countries phone codes. You can use the locale header to get the + /// data in supported language. + Future getCountriesPhones() async { + String path = '/locale/countries/phones'; + + Map params = { + }; + + return await this.client.call('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 supported language. + Future getCurrencies() async { + String path = '/locale/currencies'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/projects.dart b/app/sdks/dart/lib/services/projects.dart new file mode 100644 index 000000000..c18addaa5 --- /dev/null +++ b/app/sdks/dart/lib/services/projects.dart @@ -0,0 +1,292 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Projects extends Service { + + Projects(Client client): super(client); + + Future listProjects() async { + String path = '/projects'; + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future createProject({name, teamId, description = null, logo = null, url = null, legalName = null, legalCountry = null, legalState = null, legalCity = null, legalAddress = null, legalTaxId = null}) async { + String path = '/projects'; + + Map params = { + 'name': name, + 'teamId': teamId, + 'description': description, + 'logo': logo, + 'url': url, + 'legalName': legalName, + 'legalCountry': legalCountry, + 'legalState': legalState, + 'legalCity': legalCity, + 'legalAddress': legalAddress, + 'legalTaxId': legalTaxId, + }; + + return await this.client.call('post', path: path, params: params); + } + Future getProject({projectId}) async { + String path = '/projects/{projectId}'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updateProject({projectId, name, description = null, logo = null, url = null, legalName = null, legalCountry = null, legalState = null, legalCity = null, legalAddress = null, legalTaxId = null}) async { + String path = '/projects/{projectId}'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'name': name, + 'description': description, + 'logo': logo, + 'url': url, + 'legalName': legalName, + 'legalCountry': legalCountry, + 'legalState': legalState, + 'legalCity': legalCity, + 'legalAddress': legalAddress, + 'legalTaxId': legalTaxId, + }; + + return await this.client.call('patch', path: path, params: params); + } + Future deleteProject({projectId}) async { + String path = '/projects/{projectId}'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + Future listKeys({projectId}) async { + String path = '/projects/{projectId}/keys'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future createKey({projectId, name, scopes}) async { + String path = '/projects/{projectId}/keys'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'name': name, + 'scopes': scopes, + }; + + return await this.client.call('post', path: path, params: params); + } + Future getKey({projectId, keyId}) async { + String path = '/projects/{projectId}/keys/{keyId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{keyId}'), keyId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updateKey({projectId, keyId, name, scopes}) async { + String path = '/projects/{projectId}/keys/{keyId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{keyId}'), keyId); + + Map params = { + 'name': name, + 'scopes': scopes, + }; + + return await this.client.call('put', path: path, params: params); + } + Future deleteKey({projectId, keyId}) async { + String path = '/projects/{projectId}/keys/{keyId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{keyId}'), keyId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + Future updateProjectOAuth({projectId, provider, appId = null, secret = null}) async { + String path = '/projects/{projectId}/oauth'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'provider': provider, + 'appId': appId, + 'secret': secret, + }; + + return await this.client.call('patch', path: path, params: params); + } + Future listPlatforms({projectId}) async { + String path = '/projects/{projectId}/platforms'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future createPlatform({projectId, type, name, key = null, store = null, url = null}) async { + String path = '/projects/{projectId}/platforms'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'type': type, + 'name': name, + 'key': key, + 'store': store, + 'url': url, + }; + + return await this.client.call('post', path: path, params: params); + } + Future getPlatform({projectId, platformId}) async { + String path = '/projects/{projectId}/platforms/{platformId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{platformId}'), platformId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updatePlatform({projectId, platformId, name, key = null, store = null, url = null}) async { + String path = '/projects/{projectId}/platforms/{platformId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{platformId}'), platformId); + + Map params = { + 'name': name, + 'key': key, + 'store': store, + 'url': url, + }; + + return await this.client.call('put', path: path, params: params); + } + Future deletePlatform({projectId, platformId}) async { + String path = '/projects/{projectId}/platforms/{platformId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{platformId}'), platformId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + Future listTasks({projectId}) async { + String path = '/projects/{projectId}/tasks'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future createTask({projectId, name, status, schedule, security, httpMethod, httpUrl, httpHeaders = null, httpUser = null, httpPass = null}) async { + String path = '/projects/{projectId}/tasks'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'name': name, + 'status': status, + 'schedule': schedule, + 'security': security, + 'httpMethod': httpMethod, + 'httpUrl': httpUrl, + 'httpHeaders': httpHeaders, + 'httpUser': httpUser, + 'httpPass': httpPass, + }; + + return await this.client.call('post', path: path, params: params); + } + Future getTask({projectId, taskId}) async { + String path = '/projects/{projectId}/tasks/{taskId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{taskId}'), taskId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updateTask({projectId, taskId, name, status, schedule, security, httpMethod, httpUrl, httpHeaders = null, httpUser = null, httpPass = null}) async { + String path = '/projects/{projectId}/tasks/{taskId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{taskId}'), taskId); + + Map params = { + 'name': name, + 'status': status, + 'schedule': schedule, + 'security': security, + 'httpMethod': httpMethod, + 'httpUrl': httpUrl, + 'httpHeaders': httpHeaders, + 'httpUser': httpUser, + 'httpPass': httpPass, + }; + + return await this.client.call('put', path: path, params: params); + } + Future deleteTask({projectId, taskId}) async { + String path = '/projects/{projectId}/tasks/{taskId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{taskId}'), taskId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + Future getProjectUsage({projectId}) async { + String path = '/projects/{projectId}/usage'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future listWebhooks({projectId}) async { + String path = '/projects/{projectId}/webhooks'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future createWebhook({projectId, name, events, url, security, httpUser = null, httpPass = null}) async { + String path = '/projects/{projectId}/webhooks'.replaceAll(RegExp('{projectId}'), projectId); + + Map params = { + 'name': name, + 'events': events, + 'url': url, + 'security': security, + 'httpUser': httpUser, + 'httpPass': httpPass, + }; + + return await this.client.call('post', path: path, params: params); + } + Future getWebhook({projectId, webhookId}) async { + String path = '/projects/{projectId}/webhooks/{webhookId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{webhookId}'), webhookId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + Future updateWebhook({projectId, webhookId, name, events, url, security, httpUser = null, httpPass = null}) async { + String path = '/projects/{projectId}/webhooks/{webhookId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{webhookId}'), webhookId); + + Map params = { + 'name': name, + 'events': events, + 'url': url, + 'security': security, + 'httpUser': httpUser, + 'httpPass': httpPass, + }; + + return await this.client.call('put', path: path, params: params); + } + Future deleteWebhook({projectId, webhookId}) async { + String path = '/projects/{projectId}/webhooks/{webhookId}'.replaceAll(RegExp('{projectId}'), projectId).replaceAll(RegExp('{webhookId}'), webhookId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/storage.dart b/app/sdks/dart/lib/services/storage.dart new file mode 100644 index 000000000..4c3718ddc --- /dev/null +++ b/app/sdks/dart/lib/services/storage.dart @@ -0,0 +1,111 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Storage extends Service { + + 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/modes). + Future listFiles({search = null, limit = 25, offset = null, orderType = 'ASC'}) async { + String path = '/storage/files'; + + Map params = { + 'search': search, + 'limit': limit, + 'offset': offset, + 'orderType': orderType, + }; + + return await this.client.call('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 createFile({files, read = const [], write = const [], folderId = null}) async { + String path = '/storage/files'; + + Map params = { + 'files': files, + 'read': read, + 'write': write, + 'folderId': folderId, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Get file by its unique ID. This endpoint response returns a JSON object + /// with the file metadata. + Future getFile({fileId}) async { + String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Update file by its unique ID. Only users with write permissions have access + /// to update this resource. + Future updateFile({fileId, read = const [], write = const [], folderId = null}) async { + String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + 'read': read, + 'write': write, + 'folderId': folderId, + }; + + return await this.client.call('put', path: path, params: params); + } + /// Delete a file by its unique ID. Only users with write permissions have + /// access to delete this resource. + Future deleteFile({fileId}) async { + String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + }; + + return await this.client.call('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 getFileDownload({fileId}) async { + String path = '/storage/files/{fileId}/download'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Get 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 file icon image. You can also pass query + /// string arguments for cutting and resizing your preview image. + Future getFilePreview({fileId, width = null, height = null, quality = 100, background = null, output = null}) async { + String path = '/storage/files/{fileId}/preview'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + 'width': width, + 'height': height, + 'quality': quality, + 'background': background, + 'output': output, + }; + + return await this.client.call('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 getFileView({fileId, as = null}) async { + String path = '/storage/files/{fileId}/view'.replaceAll(RegExp('{fileId}'), fileId); + + Map params = { + 'as': as, + }; + + return await this.client.call('get', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/teams.dart b/app/sdks/dart/lib/services/teams.dart new file mode 100644 index 000000000..ad341a30b --- /dev/null +++ b/app/sdks/dart/lib/services/teams.dart @@ -0,0 +1,152 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Teams extends Service { + + 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/modes). + Future listTeams({search = null, limit = 25, offset = null, orderType = 'ASC'}) async { + String path = '/teams'; + + Map params = { + 'search': search, + 'limit': limit, + 'offset': offset, + 'orderType': orderType, + }; + + return await this.client.call('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 createTeam({name, roles = const ["owner"]}) async { + String path = '/teams'; + + Map params = { + 'name': name, + 'roles': roles, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Get team by its unique ID. All team members have read access for this + /// resource. + Future getTeam({teamId}) async { + String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Update team by its unique ID. Only team owners have write access for this + /// resource. + Future updateTeam({teamId, name}) async { + String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId); + + Map params = { + 'name': name, + }; + + return await this.client.call('put', path: path, params: params); + } + /// Delete team by its unique ID. Only team owners have write access for this + /// resource. + Future deleteTeam({teamId}) async { + String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId); + + Map params = { + }; + + return await this.client.call('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 getTeamMembers({teamId}) async { + String path = '/teams/{teamId}/members'.replaceAll(RegExp('{teamId}'), teamId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Use this endpoint to invite a new member to your team. An email with a link + /// to join the team will be sent to the new member email address. If member + /// doesn't exists in the project it will be automatically created. + /// + /// Use the redirect parameter to redirect the user from the invitation email + /// back to your app. When the user is redirected, use the + /// /teams/{teamId}/memberships/{inviteId}/status endpoint to finally join the + /// user to the team. + /// + /// Please notice that in order to avoid a [Redirect + /// 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 createTeamMembership({teamId, email, roles, redirect, name = null}) async { + String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId); + + Map params = { + 'email': email, + 'name': name, + 'roles': roles, + 'redirect': redirect, + }; + + return await this.client.call('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. + Future deleteTeamMembership({teamId, inviteId}) async { + String path = '/teams/{teamId}/memberships/{inviteId}'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + /// Use this endpoint to resend your invitation email for a user to join a + /// team. + Future createTeamMembershipResend({teamId, inviteId, redirect}) async { + String path = '/teams/{teamId}/memberships/{inviteId}/resend'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId); + + Map params = { + 'redirect': redirect, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Use this endpoint to let user accept an invitation to join a team after he + /// is being redirect back to your app from the invitation email. Use the + /// success and failure URL's to redirect users back to your application after + /// the request completes. + /// + /// Please notice that in order to avoid a [Redirect + /// 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. + /// + /// When not using the success or failure redirect arguments this endpoint will + /// result with a 200 status code on success and with 401 status error on + /// failure. This behavior was applied to help the web clients deal with + /// browsers who don't allow to set 3rd party HTTP cookies needed for saving + /// the account session token. + Future updateTeamMembershipStatus({teamId, inviteId, userId, secret, success = null, failure = null}) async { + String path = '/teams/{teamId}/memberships/{inviteId}/status'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId); + + Map params = { + 'userId': userId, + 'secret': secret, + 'success': success, + 'failure': failure, + }; + + return await this.client.call('patch', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/lib/services/users.dart b/app/sdks/dart/lib/services/users.dart new file mode 100644 index 000000000..28ba535a9 --- /dev/null +++ b/app/sdks/dart/lib/services/users.dart @@ -0,0 +1,100 @@ +import "package:dart_appwrite/service.dart"; +import "package:dart_appwrite/client.dart"; +import 'package:dio/dio.dart'; + +class Users extends Service { + + Users(Client client): super(client); + + /// Get a list of all the project users. You can use the query params to filter + /// your results. + Future listUsers({search = null, limit = 25, offset = null, orderType = 'ASC'}) async { + String path = '/users'; + + Map params = { + 'search': search, + 'limit': limit, + 'offset': offset, + 'orderType': orderType, + }; + + return await this.client.call('get', path: path, params: params); + } + /// Create a new user. + Future createUser({email, password, name = null}) async { + String path = '/users'; + + Map params = { + 'email': email, + 'password': password, + 'name': name, + }; + + return await this.client.call('post', path: path, params: params); + } + /// Get user by its unique ID. + Future getUser({userId}) async { + String path = '/users/{userId}'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Get user activity logs list by its unique ID. + Future getUserLogs({userId}) async { + String path = '/users/{userId}/logs'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Get user preferences by its unique ID. + Future getUserPrefs({userId}) async { + String path = '/users/{userId}/prefs'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Get user sessions list by its unique ID. + Future getUserSessions({userId}) async { + String path = '/users/{userId}/sessions'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + }; + + return await this.client.call('get', path: path, params: params); + } + /// Delete all user sessions by its unique ID. + Future deleteUserSessions({userId}) async { + String path = '/users/{userId}/sessions'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + }; + + return await this.client.call('delete', path: path, params: params); + } + /// Delete user sessions by its unique ID. + Future deleteUsersSession({userId, sessionId}) async { + String path = '/users/{userId}/sessions/:session'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + 'sessionId': sessionId, + }; + + return await this.client.call('delete', path: path, params: params); + } + /// Update user status by its unique ID. + Future updateUserStatus({userId, status}) async { + String path = '/users/{userId}/status'.replaceAll(RegExp('{userId}'), userId); + + Map params = { + 'status': status, + }; + + return await this.client.call('patch', path: path, params: params); + } +} \ No newline at end of file diff --git a/app/sdks/dart/pubspec.yaml b/app/sdks/dart/pubspec.yaml new file mode 100644 index 000000000..af5838b4e --- /dev/null +++ b/app/sdks/dart/pubspec.yaml @@ -0,0 +1,11 @@ +name: appwrite +version: v0.0.1 +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 +homepage: https://github.com/appwrite/sdk-for-dart +environment: + sdk: '>=2.2.2 <3.0.0' +dependencies: + dio: ^3.0.0 + cookie_jar: ^1.0.0 + dio_cookie_manager: ^1.0.0 \ No newline at end of file diff --git a/app/sdks/js/README.md b/app/sdks/js/README.md index dae54d3a7..9cbe04dc1 100644 --- a/app/sdks/js/README.md +++ b/app/sdks/js/README.md @@ -1,7 +1,7 @@ # [Appwrite SDK for Javascript](https://appwrite.io)   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Appwrite%20is%20a%20backend%20as%20a%20service%20for%20building%20web%20or%20mobile%20apps&url=http%3A%2F%2Fappwrite.io&via=appwrite_io&hashtags=JS%2Cjavascript%2Creactjs%2Cangular%2Cios%2Candroid) ![License](https://img.shields.io/github/license/appwrite/sdk-for-js.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-latest-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.1.15-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) @@ -9,7 +9,7 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for ![Appwrite](https://appwrite.io/images/github.png) -**API Version: latest** +**API Version: 0.1.15** ## Installation diff --git a/app/sdks/js/docs/examples/auth/login.md b/app/sdks/js/docs/examples/auth/login.md index 517b82691..dc5c769b5 100644 --- a/app/sdks/js/docs/examples/auth/login.md +++ b/app/sdks/js/docs/examples/auth/login.md @@ -5,7 +5,7 @@ sdk setKey('') ; -let promise = sdk.auth.login('email@example.com', 'password'); +let promise = sdk.auth.login('email@example.com', 'password', 'https://example.com', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/js/docs/examples/auth/register.md b/app/sdks/js/docs/examples/auth/register.md index 07eb13650..bf2edc614 100644 --- a/app/sdks/js/docs/examples/auth/register.md +++ b/app/sdks/js/docs/examples/auth/register.md @@ -5,7 +5,7 @@ sdk setKey('') ; -let promise = sdk.auth.register('email@example.com', 'password', 'https://example.com'); +let promise = sdk.auth.register('email@example.com', 'password', 'https://example.com', 'https://example.com', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/js/docs/examples/projects/update-task.md b/app/sdks/js/docs/examples/projects/update-task.md index 693c61ee6..c5bb04d59 100644 --- a/app/sdks/js/docs/examples/projects/update-task.md +++ b/app/sdks/js/docs/examples/projects/update-task.md @@ -5,7 +5,7 @@ sdk setKey('') ; -let promise = sdk.projects.updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 0, 'GET', 'https://example.com'); +let promise = sdk.projects.updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 1, 'GET', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/js/docs/examples/projects/update-webhook.md b/app/sdks/js/docs/examples/projects/update-webhook.md index 514424a68..e8a5bd6c6 100644 --- a/app/sdks/js/docs/examples/projects/update-webhook.md +++ b/app/sdks/js/docs/examples/projects/update-webhook.md @@ -5,7 +5,7 @@ sdk setKey('') ; -let promise = sdk.projects.updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 0); +let promise = sdk.projects.updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 1); promise.then(function (response) { console.log(response); diff --git a/app/sdks/js/src/sdk.js b/app/sdks/js/src/sdk.js index f89576ea1..4d0e01745 100644 --- a/app/sdks/js/src/sdk.js +++ b/app/sdks/js/src/sdk.js @@ -512,7 +512,7 @@ * @param {string} failure * @throws {Error} * @return {null} */ - login: function(email, password, success = '', failure = '') { + login: function(email, password, success, failure) { if(email === undefined) { throw new Error('Missing required parameter: "email"'); } @@ -521,6 +521,14 @@ throw new Error('Missing required parameter: "password"'); } + if(success === undefined) { + throw new Error('Missing required parameter: "success"'); + } + + if(failure === undefined) { + throw new Error('Missing required parameter: "failure"'); + } + let path = '/auth/login'; return iframe('post', path, {project: config.project, @@ -536,7 +544,7 @@ * * Use this endpoint to log out the currently logged in user from his account. * When succeed this endpoint will delete the user session and remove the - * session secret cookie. + * session secret cookie from the user client. * * @throws {Error} * @return {Promise} */ @@ -737,12 +745,12 @@ * @param {string} email * @param {string} password * @param {string} redirect - * @param {string} name * @param {string} success * @param {string} failure + * @param {string} name * @throws {Error} * @return {null} */ - register: function(email, password, redirect, name = '', success = '', failure = '') { + register: function(email, password, redirect, success, failure, name = '') { if(email === undefined) { throw new Error('Missing required parameter: "email"'); } @@ -755,15 +763,23 @@ throw new Error('Missing required parameter: "redirect"'); } + if(success === undefined) { + throw new Error('Missing required parameter: "success"'); + } + + if(failure === undefined) { + throw new Error('Missing required parameter: "failure"'); + } + let path = '/auth/register'; return iframe('post', path, {project: config.project, 'email': email, 'password': password, - 'name': name, 'redirect': redirect, 'success': success, - 'failure': failure + 'failure': failure, + 'name': name }); }, diff --git a/app/sdks/js/src/sdk.min.js b/app/sdks/js/src/sdk.min.js index caffff26f..a152b7e46 100644 --- a/app/sdks/js/src/sdk.min.js +++ b/app/sdks/js/src/sdk.min.js @@ -17,8 +17,10 @@ let path='/account/email';return http.patch(path,{'content-type':'application/js let path='/account/name';return http.patch(path,{'content-type':'application/json'},{'name':name})},updatePassword:function(password,oldPassword){if(password===undefined){throw new Error('Missing required parameter: "password"')} if(oldPassword===undefined){throw new Error('Missing required parameter: "oldPassword"')} let path='/account/password';return http.patch(path,{'content-type':'application/json'},{'password':password,'old-password':oldPassword})},getPrefs:function(){let path='/account/prefs';return http.get(path,{'content-type':'application/json'},{})},updatePrefs:function(prefs){if(prefs===undefined){throw new Error('Missing required parameter: "prefs"')} -let path='/account/prefs';return http.patch(path,{'content-type':'application/json'},{'prefs':prefs})},getSecurity:function(){let path='/account/security';return http.get(path,{'content-type':'application/json'},{})},getSessions:function(){let path='/account/sessions';return http.get(path,{'content-type':'application/json'},{})}};let auth={login:function(email,password,success='',failure=''){if(email===undefined){throw new Error('Missing required parameter: "email"')} +let path='/account/prefs';return http.patch(path,{'content-type':'application/json'},{'prefs':prefs})},getSecurity:function(){let path='/account/security';return http.get(path,{'content-type':'application/json'},{})},getSessions:function(){let path='/account/sessions';return http.get(path,{'content-type':'application/json'},{})}};let auth={login:function(email,password,success,failure){if(email===undefined){throw new Error('Missing required parameter: "email"')} if(password===undefined){throw new Error('Missing required parameter: "password"')} +if(success===undefined){throw new Error('Missing required parameter: "success"')} +if(failure===undefined){throw new Error('Missing required parameter: "failure"')} let path='/auth/login';return iframe('post',path,{project:config.project,'email':email,'password':password,'success':success,'failure':failure})},logout:function(){let path='/auth/logout';return http.delete(path,{'content-type':'application/json'},{})},logoutBySession:function(id){if(id===undefined){throw new Error('Missing required parameter: "id"')} let path='/auth/logout/{id}'.replace(new RegExp('{id}','g'),id);return http.delete(path,{'content-type':'application/json'},{})},oauthCallback:function(projectId,provider,code,state=''){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"')} if(provider===undefined){throw new Error('Missing required parameter: "provider"')} @@ -30,10 +32,12 @@ let path='/auth/recovery';return http.post(path,{'content-type':'application/jso if(token===undefined){throw new Error('Missing required parameter: "token"')} if(passwordA===undefined){throw new Error('Missing required parameter: "passwordA"')} if(passwordB===undefined){throw new Error('Missing required parameter: "passwordB"')} -let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB})},register:function(email,password,redirect,name='',success='',failure=''){if(email===undefined){throw new Error('Missing required parameter: "email"')} +let path='/auth/recovery/reset';return http.put(path,{'content-type':'application/json'},{'userId':userId,'token':token,'password-a':passwordA,'password-b':passwordB})},register:function(email,password,redirect,success,failure,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"')} if(password===undefined){throw new Error('Missing required parameter: "password"')} if(redirect===undefined){throw new Error('Missing required parameter: "redirect"')} -let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'name':name,'redirect':redirect,'success':success,'failure':failure})},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"')} +if(success===undefined){throw new Error('Missing required parameter: "success"')} +if(failure===undefined){throw new Error('Missing required parameter: "failure"')} +let path='/auth/register';return iframe('post',path,{project:config.project,'email':email,'password':password,'redirect':redirect,'success':success,'failure':failure,'name':name})},confirm:function(userId,token){if(userId===undefined){throw new Error('Missing required parameter: "userId"')} if(token===undefined){throw new Error('Missing required parameter: "token"')} let path='/auth/register/confirm';return http.post(path,{'content-type':'application/json'},{'userId':userId,'token':token})},confirmResend:function(redirect){if(redirect===undefined){throw new Error('Missing required parameter: "redirect"')} let path='/auth/register/confirm/resend';return http.post(path,{'content-type':'application/json'},{'redirect':redirect})}};let avatars={getBrowser:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"')} diff --git a/app/sdks/node/README.md b/app/sdks/node/README.md index 409dd7e65..64f3f2312 100644 --- a/app/sdks/node/README.md +++ b/app/sdks/node/README.md @@ -1,7 +1,7 @@ # [Appwrite SDK for NodeJS](https://appwrite.io)   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Appwrite%20is%20a%20backend%20as%20a%20service%20for%20building%20web%20or%20mobile%20apps&url=http%3A%2F%2Fappwrite.io&via=appwrite_io&hashtags=JS%2Cjavascript%2Creactjs%2Cangular%2Cios%2Candroid) ![License](https://img.shields.io/github/license/appwrite/sdk-for-node.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-latest-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.1.15-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) @@ -9,7 +9,7 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for ![Appwrite](https://appwrite.io/images/github.png) -**API Version: latest** +**API Version: 0.1.15** ## Installation diff --git a/app/sdks/node/docs/examples/auth/login.md b/app/sdks/node/docs/examples/auth/login.md index e82e805e8..fa35e3ae0 100644 --- a/app/sdks/node/docs/examples/auth/login.md +++ b/app/sdks/node/docs/examples/auth/login.md @@ -10,7 +10,7 @@ client setKey('') ; -let promise = auth.login('email@example.com', 'password'); +let promise = auth.login('email@example.com', 'password', 'https://example.com', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/node/docs/examples/auth/register.md b/app/sdks/node/docs/examples/auth/register.md index 40cc88438..32871671a 100644 --- a/app/sdks/node/docs/examples/auth/register.md +++ b/app/sdks/node/docs/examples/auth/register.md @@ -10,7 +10,7 @@ client setKey('') ; -let promise = auth.register('email@example.com', 'password', 'https://example.com'); +let promise = auth.register('email@example.com', 'password', 'https://example.com', 'https://example.com', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/node/docs/examples/projects/update-task.md b/app/sdks/node/docs/examples/projects/update-task.md index 3d1effdfd..3f7d89976 100644 --- a/app/sdks/node/docs/examples/projects/update-task.md +++ b/app/sdks/node/docs/examples/projects/update-task.md @@ -10,7 +10,7 @@ client setKey('') ; -let promise = projects.updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 0, 'GET', 'https://example.com'); +let promise = projects.updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 1, 'GET', 'https://example.com'); promise.then(function (response) { console.log(response); diff --git a/app/sdks/node/docs/examples/projects/update-webhook.md b/app/sdks/node/docs/examples/projects/update-webhook.md index a7f36bb18..d1c81b539 100644 --- a/app/sdks/node/docs/examples/projects/update-webhook.md +++ b/app/sdks/node/docs/examples/projects/update-webhook.md @@ -10,7 +10,7 @@ client setKey('') ; -let promise = projects.updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 0); +let promise = projects.updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 1); promise.then(function (response) { console.log(response); diff --git a/app/sdks/node/lib/services/auth.js b/app/sdks/node/lib/services/auth.js index 1e88aba80..464ceab6b 100644 --- a/app/sdks/node/lib/services/auth.js +++ b/app/sdks/node/lib/services/auth.js @@ -27,7 +27,7 @@ class Auth extends Service { * @throws Exception * @return {} */ - async login(email, password, success = '', failure = '') { + async login(email, password, success, failure) { let path = '/auth/login'; return await this.client.call('post', path, {'content-type': 'application/json'}, @@ -44,7 +44,7 @@ class Auth extends Service { * * Use this endpoint to log out the currently logged in user from his account. * When succeed this endpoint will delete the user session and remove the - * session secret cookie. + * session secret cookie from the user client. * * @throws Exception * @return {} @@ -199,23 +199,23 @@ class Auth extends Service { * @param string email * @param string password * @param string redirect - * @param string name * @param string success * @param string failure + * @param string name * @throws Exception * @return {} */ - async register(email, password, redirect, name = '', success = '', failure = '') { + async register(email, password, redirect, success, failure, name = '') { let path = '/auth/register'; return await this.client.call('post', path, {'content-type': 'application/json'}, { 'email': email, 'password': password, - 'name': name, 'redirect': redirect, 'success': success, - 'failure': failure + 'failure': failure, + 'name': name }); } diff --git a/app/sdks/php/README.md b/app/sdks/php/README.md index 3696e1427..674cdf083 100644 --- a/app/sdks/php/README.md +++ b/app/sdks/php/README.md @@ -1,7 +1,7 @@ # [Appwrite SDK for PHP](https://appwrite.io)   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Appwrite%20is%20a%20backend%20as%20a%20service%20for%20building%20web%20or%20mobile%20apps&url=http%3A%2F%2Fappwrite.io&via=appwrite_io&hashtags=JS%2Cjavascript%2Creactjs%2Cangular%2Cios%2Candroid) ![License](https://img.shields.io/github/license/appwrite/sdk-for-php.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-latest-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.1.15-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) @@ -9,7 +9,7 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for ![Appwrite](https://appwrite.io/images/github.png) -**API Version: latest** +**API Version: 0.1.15** ## Installation diff --git a/app/sdks/php/docs/auth.md b/app/sdks/php/docs/auth.md index 241cf7e6c..e82d34395 100644 --- a/app/sdks/php/docs/auth.md +++ b/app/sdks/php/docs/auth.md @@ -27,7 +27,7 @@ When not using the success or failure redirect arguments this endpoint will resu DELETE https://appwrite.test/v1/auth/logout ``` -** Use this endpoint to log out the currently logged in user from his account. When succeed this endpoint will delete the user session and remove the session secret cookie. ** +** Use this endpoint to log out the currently logged in user from his account. When succeed this endpoint will delete the user session and remove the session secret cookie from the user client. ** ## Logout Specific Session @@ -126,10 +126,10 @@ When not using the success or failure redirect arguments this endpoint will resu | --- | --- | --- | --- | | email | string | Account email | | | password | string | User password | | -| name | string | User name | | | redirect | string | Confirmation page to redirect user after confirm token has been sent to user email | | | success | string | Redirect when registration succeed | | | failure | string | Redirect when registration failed | | +| name | string | User name | | ## Confirm User diff --git a/app/sdks/php/docs/database.md b/app/sdks/php/docs/database.md index ffa7db83d..0a5d7812f 100644 --- a/app/sdks/php/docs/database.md +++ b/app/sdks/php/docs/database.md @@ -32,7 +32,7 @@ POST https://appwrite.test/v1/database | name | string | Collection name. | | | read | array | An array of read permissions. [Learn more about permissions and roles](/docs/permissions). | [] | | write | array | An array of write permissions. [Learn more about permissions and roles](/docs/permissions). | [] | -| rules | array | Array of collection structure rules. Each rule define a collection field name, data type and validation | [] | +| rules | array | Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation | [] | ## Get Collection @@ -64,7 +64,7 @@ PUT https://appwrite.test/v1/database/{collectionId} | name | string | Collection name. | | | read | array | An array of read permissions. [Learn more about permissions and roles](/docs/permissions). | [] | | write | array | An array of write permissions. [Learn more about permissions and roles](/docs/permissions). | [] | -| rules | array | Array of collection structure rules. Each rule define a collection field name, data type and validation | [] | +| rules | array | Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation | [] | ## Delete Collection diff --git a/app/sdks/php/docs/examples/auth/login.md b/app/sdks/php/docs/examples/auth/login.md index 629f03852..596d31144 100644 --- a/app/sdks/php/docs/examples/auth/login.md +++ b/app/sdks/php/docs/examples/auth/login.md @@ -12,4 +12,4 @@ $client $auth = new Auth($client); -$result = $auth->login('email@example.com', 'password'); \ No newline at end of file +$result = $auth->login('email@example.com', 'password', 'https://example.com', 'https://example.com'); \ No newline at end of file diff --git a/app/sdks/php/docs/examples/auth/register.md b/app/sdks/php/docs/examples/auth/register.md index 8ecc026f4..becd872b1 100644 --- a/app/sdks/php/docs/examples/auth/register.md +++ b/app/sdks/php/docs/examples/auth/register.md @@ -12,4 +12,4 @@ $client $auth = new Auth($client); -$result = $auth->register('email@example.com', 'password', 'https://example.com'); \ No newline at end of file +$result = $auth->register('email@example.com', 'password', 'https://example.com', 'https://example.com', 'https://example.com'); \ No newline at end of file diff --git a/app/sdks/php/docs/examples/projects/update-task.md b/app/sdks/php/docs/examples/projects/update-task.md index 01a229b7b..409f00486 100644 --- a/app/sdks/php/docs/examples/projects/update-task.md +++ b/app/sdks/php/docs/examples/projects/update-task.md @@ -12,4 +12,4 @@ $client $projects = new Projects($client); -$result = $projects->updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 0, 'GET', 'https://example.com'); \ No newline at end of file +$result = $projects->updateTask('[PROJECT_ID]', '[TASK_ID]', '[NAME]', 'play', '', 1, 'GET', 'https://example.com'); \ No newline at end of file diff --git a/app/sdks/php/docs/examples/projects/update-webhook.md b/app/sdks/php/docs/examples/projects/update-webhook.md index bf0679261..c4fa7864a 100644 --- a/app/sdks/php/docs/examples/projects/update-webhook.md +++ b/app/sdks/php/docs/examples/projects/update-webhook.md @@ -12,4 +12,4 @@ $client $projects = new Projects($client); -$result = $projects->updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 0); \ No newline at end of file +$result = $projects->updateWebhook('[PROJECT_ID]', '[WEBHOOK_ID]', '[NAME]', [], '[URL]', 1); \ No newline at end of file diff --git a/app/sdks/php/src/Appwrite/Services/Auth.php b/app/sdks/php/src/Appwrite/Services/Auth.php index c3bebe8a8..7b7495936 100644 --- a/app/sdks/php/src/Appwrite/Services/Auth.php +++ b/app/sdks/php/src/Appwrite/Services/Auth.php @@ -33,7 +33,7 @@ class Auth extends Service * @throws Exception * @return array */ - public function login($email, $password, $success = '', $failure = '') + public function login($email, $password, $success, $failure) { $path = str_replace([], [], '/auth/login'); $params = []; @@ -52,7 +52,7 @@ class Auth extends Service * * Use this endpoint to log out the currently logged in user from his account. * When succeed this endpoint will delete the user session and remove the - * session secret cookie. + * session secret cookie from the user client. * * @throws Exception * @return array @@ -219,23 +219,23 @@ class Auth extends Service * @param string $email * @param string $password * @param string $redirect - * @param string $name * @param string $success * @param string $failure + * @param string $name * @throws Exception * @return array */ - public function register($email, $password, $redirect, $name = '', $success = '', $failure = '') + public function register($email, $password, $redirect, $success, $failure, $name = '') { $path = str_replace([], [], '/auth/register'); $params = []; $params['email'] = $email; $params['password'] = $password; - $params['name'] = $name; $params['redirect'] = $redirect; $params['success'] = $success; $params['failure'] = $failure; + $params['name'] = $name; return $this->client->call(Client::METHOD_POST, $path, [ ], $params); diff --git a/app/sdks/python/README.md b/app/sdks/python/README.md index 08f7338bf..59928110e 100644 --- a/app/sdks/python/README.md +++ b/app/sdks/python/README.md @@ -1,7 +1,7 @@ # [Appwrite SDK for Python](https://appwrite.io)   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Appwrite%20is%20a%20backend%20as%20a%20service%20for%20building%20web%20or%20mobile%20apps&url=http%3A%2F%2Fappwrite.io&via=appwrite_io&hashtags=JS%2Cjavascript%2Creactjs%2Cangular%2Cios%2Candroid) ![License](https://img.shields.io/github/license/appwrite/sdk-for-python.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-latest-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.1.15-blue.svg?v=1) **WORK IN PROGRESS - NOT READY FOR USAGE - Want to help us improve this client SDK? Send a pull request to Appwrite [SDK generator repository](https://github.com/appwrite/sdk-generator).** @@ -11,7 +11,7 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for ![Appwrite](https://appwrite.io/images/github.png) -**API Version: latest** +**API Version: 0.1.15** ## Installation diff --git a/app/sdks/python/appwrite/services/auth.py b/app/sdks/python/appwrite/services/auth.py index ddf7469c0..f082987d4 100644 --- a/app/sdks/python/appwrite/services/auth.py +++ b/app/sdks/python/appwrite/services/auth.py @@ -3,7 +3,7 @@ from ..service import Service class Auth(Service): - def login(self, email, password, success='', failure=''): + def login(self, email, password, success, failure): """Login User""" params = {} @@ -84,17 +84,17 @@ class Auth(Service): return self.client.call('put', path, { }, params) - def register(self, email, password, redirect, name='', success='', failure=''): + def register(self, email, password, redirect, success, failure, name=''): """Register User""" params = {} path = '/auth/register' params['email'] = email params['password'] = password - params['name'] = name params['redirect'] = redirect params['success'] = success params['failure'] = failure + params['name'] = name return self.client.call('post', path, { }, params) diff --git a/app/sdks/ruby/README.md b/app/sdks/ruby/README.md index a8d5f466b..82892eac6 100644 --- a/app/sdks/ruby/README.md +++ b/app/sdks/ruby/README.md @@ -1,7 +1,7 @@ # [Appwrite SDK for Ruby](https://appwrite.io)   [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Appwrite%20is%20a%20backend%20as%20a%20service%20for%20building%20web%20or%20mobile%20apps&url=http%3A%2F%2Fappwrite.io&via=appwrite_io&hashtags=JS%2Cjavascript%2Creactjs%2Cangular%2Cios%2Candroid) ![License](https://img.shields.io/github/license/appwrite/sdk-for-ruby.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-latest-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.1.15-blue.svg?v=1) **WORK IN PROGRESS - NOT READY FOR USAGE - Want to help us improve this client SDK? Send a pull request to Appwrite [SDK generator repository](https://github.com/appwrite/sdk-generator).** @@ -11,7 +11,7 @@ Appwrite backend as a service cuts up to 70% of the time and costs required for ![Appwrite](https://appwrite.io/images/github.png) -**API Version: latest** +**API Version: 0.1.15** ## Installation diff --git a/app/sdks/ruby/lib/appwrite/services/auth.rb b/app/sdks/ruby/lib/appwrite/services/auth.rb index b896d6e98..b8b6794c2 100644 --- a/app/sdks/ruby/lib/appwrite/services/auth.rb +++ b/app/sdks/ruby/lib/appwrite/services/auth.rb @@ -1,7 +1,7 @@ module Appwrite class Auth < Service - def login(email:, password:, success: '', failure: '') + def login(email:, password:, success:, failure:) path = '/auth/login' params = { @@ -89,16 +89,16 @@ module Appwrite }, params); end - def register(email:, password:, redirect:, name: '', success: '', failure: '') + def register(email:, password:, redirect:, success:, failure:, name: '') path = '/auth/register' params = { 'email': email, 'password': password, - 'name': name, 'redirect': redirect, 'success': success, - 'failure': failure + 'failure': failure, + 'name': name } return @client.call('post', path, { diff --git a/app/tasks/sdks.php b/app/tasks/sdks.php index b41a3b651..ce96644bf 100644 --- a/app/tasks/sdks.php +++ b/app/tasks/sdks.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Language\JS; use Appwrite\SDK\Language\Node; use Appwrite\SDK\Language\Python; use Appwrite\SDK\Language\Ruby; +use Appwrite\SDK\Language\Dart; $cli = new CLI(); @@ -84,6 +85,15 @@ $cli 'gitUserName' => 'appwrite', 'warning' => '**WORK IN PROGRESS - NOT READY FOR USAGE - Want to help us improve this client SDK? Send a pull request to Appwrite [SDK generator repository](https://github.com/appwrite/sdk-generator).**', ], + 'dart' => [ + 'version' => 'v0.0.1', + 'result' => __DIR__.'/../sdks/dart/', + 'gitURL' => 'https://github.com/appwrite/sdk-for-dart', + 'gitRepo' => 'git@github.com:appwrite/sdk-for-dart.git', + 'gitRepoName' => 'sdk-for-dart', + 'gitUserName' => 'appwrite', + 'warning' => '**WORK IN PROGRESS - NOT READY FOR USAGE - Want to help us improve this client SDK? Send a pull request to Appwrite [SDK generator repository](https://github.com/appwrite/sdk-generator).**', + ], ]; foreach ($clients as $name => $client) { @@ -121,6 +131,12 @@ $cli ->setGemPackage('appwrite') ; break; + case 'dart': + $language = new Dart(); + $language + ->setPackageName('appwrite') + ; + break; default: throw new Exception('Language not supported'); break; diff --git a/src/Database/Validator/Collection.php b/src/Database/Validator/Collection.php index 40815ac06..6b9fa7f6c 100644 --- a/src/Database/Validator/Collection.php +++ b/src/Database/Validator/Collection.php @@ -7,23 +7,25 @@ use Database\Document; class Collection extends Structure { - /** - * @var string - */ - protected $message = 'Unknown Error'; - /** * @var array */ protected $collections = []; + /** + * @var array + */ + protected $merge = []; + /** * @param Database $database * @param array $collections + * @param array $merge */ - public function __construct(Database $database, array $collections) + public function __construct(Database $database, array $collections, array $merge = []) { $this->collections = $collections; + $this->merge = $merge; return parent::__construct($database); } @@ -35,8 +37,9 @@ class Collection extends Structure */ public function isValid($document) { - $document = (is_array($document)) ? new Document($document) : $document; - + $document = new Document( + array_merge($this->merge, ($document instanceof Document) ? $document->getArrayCopy() : $document)); + if (is_null($document->getCollection())) { $this->message = 'Missing collection attribute $collection'; diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index 15db5a1de..9c8283966 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -202,13 +202,11 @@ class Structure extends Validator if (empty($validator)) { // Error creating validator for property $this->message = 'Unknown property "'.$key.'"'. '. Make sure to follow '.strtolower($collection->getAttribute('name', 'unknown')).' collection structure'; - return false; } if ($ruleRequired && ('' === $value || null === $value)) { $this->message = 'Required property "'.$key.'" has no value'; - return false; } @@ -222,7 +220,6 @@ class Structure extends Validator if ($ruleArray) { // Array of values validation if (!is_array($value)) { $this->message = 'Property "'.$key.'" must be an array'; - return false; } @@ -231,14 +228,12 @@ class Structure extends Validator foreach ($value as $node) { if (!$validator->isValid($node)) { // Check if property is valid, if not required can also be empty $this->message = 'Property "'.$key.'" has invalid input. '.$validator->getDescription(); - return false; } } } else { // Single value validation if ((!$validator->isValid($value)) && !('' === $value && !$ruleRequired)) { // Error when value is not valid, and is not optional and empty $this->message = 'Property "'.$key.'" has invalid input. '.$validator->getDescription(); - return false; } } diff --git a/tests/e2e/ProjectDatabaseTest.php b/tests/e2e/ProjectDatabaseTest.php index ac6f8f17f..4cd200ea2 100644 --- a/tests/e2e/ProjectDatabaseTest.php +++ b/tests/e2e/ProjectDatabaseTest.php @@ -85,22 +85,64 @@ class ProjectDatabaseTest extends BaseProjects 'x-appwrite-project' => $data['projectUid'], 'x-appwrite-key' => $data['projectAPIKeySecret'], ], [ - 'name' => 'Test Collection', + 'name' => 'Movies', 'read' => ['*'], 'write' => ['role:1', 'role:2'], + 'rules' => [ + [ + 'label' => 'Name', + 'key' => 'name', + 'type' => 'text', + 'default' => '', + 'required' => false, + 'array' => false + ], + [ + 'label' => 'Release Year', + 'key' => 'releaseYear', + 'type' => 'numeric', + 'default' => 0, + 'required' => false, + 'array' => false + ], + ], ]); $this->assertEquals($collection['headers']['status-code'], 201); $this->assertEquals($collection['body']['$collection'], 0); - $this->assertEquals($collection['body']['name'], 'Test Collection'); + $this->assertEquals($collection['body']['name'], 'Movies'); $this->assertIsArray($collection['body']['$permissions']); $this->assertIsArray($collection['body']['$permissions']['read']); $this->assertIsArray($collection['body']['$permissions']['write']); $this->assertEquals(count($collection['body']['$permissions']['read']), 1); $this->assertEquals(count($collection['body']['$permissions']['write']), 2); - return [ - 'collectionId' => $collection['body']['$uid'] - ]; + return array_merge($data, ['collectionId' => $collection['body']['$uid']]); + } + + /** + * @depends testCollectionCreateSuccess + */ + public function testDocumentCreateSuccess($data) { + $collection = $this->client->call(Client::METHOD_POST, '/database/' . $data['collectionId'] . '/documents', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $data['projectUid'], + 'x-appwrite-key' => $data['projectAPIKeySecret'], + ], [ + 'data' => [ + 'name' => 'Avengers', + 'releaseYear' => 2019, + ] + ]); + + $this->assertEquals($collection['headers']['status-code'], 201); + $this->assertEquals($collection['body']['$collection'], $data['collectionId']); + $this->assertEquals($collection['body']['name'], 'Avengers'); + $this->assertEquals($collection['body']['releaseYear'], 2019); + $this->assertIsArray($collection['body']['$permissions']); + $this->assertIsArray($collection['body']['$permissions']['read']); + $this->assertIsArray($collection['body']['$permissions']['write']); + $this->assertEquals(count($collection['body']['$permissions']['read']), 0); + $this->assertEquals(count($collection['body']['$permissions']['write']), 0); } } \ No newline at end of file