diff --git a/CHANGES.md b/CHANGES.md index ff35674625..2f75c92d88 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - Fixed missing validation for database documents key length (32 chars) - Grammer fix for pt-br email templates (@rubensdemelo) - Fixed update form labels and tooltips for Flutter Android apps +- Fixed missing custom scopes param for OAuth2 session create API route ## Security diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 504d2940b8..834fd009ec 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -27,6 +27,7 @@ use Appwrite\OpenSSL\OpenSSL; use Appwrite\URL\URL as URLParser; use DeviceDetector\DeviceDetector; use GeoIp2\Database\Reader; +use Utopia\Validator\ArrayList; include_once __DIR__ . '/../shared/api.php'; @@ -253,8 +254,9 @@ $utopia->get('/v1/account/sessions/oauth2/:provider') ->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', $oauthDefaultSuccess, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true) ->param('failure', $oauthDefaultFailure, function () use ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true) + ->param('scopes', [], function () { return new ArrayList(new Text(128)); }, 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes.', true) ->action( - function ($provider, $success, $failure) use ($response, $request, $project) { + function ($provider, $success, $failure, $scopes) use ($response, $request, $project) { $protocol = Config::getParam('protocol'); $callback = $protocol.'://'.$request->getServer('HTTP_HOST').'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId(); $appId = $project->getAttribute('usersOauth2'.ucfirst($provider).'Appid', ''); @@ -277,7 +279,7 @@ $utopia->get('/v1/account/sessions/oauth2/:provider') throw new Exception('Provider is not supported', 501); } - $oauth2 = new $classname($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure]); + $oauth2 = new $classname($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure], $scopes); $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') diff --git a/app/sdks/client-flutter/README.md b/app/sdks/client-flutter/README.md index b0c261c115..9a5c8c5c1a 100644 --- a/app/sdks/client-flutter/README.md +++ b/app/sdks/client-flutter/README.md @@ -2,9 +2,9 @@ [![pub package](https://img.shields.io/pub/v/appwrite.svg)](https://pub.dartlang.org/packages/appwrite) ![License](https://img.shields.io/github/license/appwrite/sdk-for-flutter.svg?v=1) -![Version](https://img.shields.io/badge/api%20version-0.6.1-blue.svg?v=1) +![Version](https://img.shields.io/badge/api%20version-0.6.2-blue.svg?v=1) -**This SDK is compatible with Appwrite server version 0.6.1. For older versions, please check previous releases.** +**This SDK is compatible with Appwrite server version 0.6.2. For older versions, please check previous releases.** Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Flutter SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. diff --git a/app/sdks/client-flutter/docs/examples/account/create-o-auth2session.md b/app/sdks/client-flutter/docs/examples/account/create-o-auth2session.md index c617c34d4d..0e26dd27af 100644 --- a/app/sdks/client-flutter/docs/examples/account/create-o-auth2session.md +++ b/app/sdks/client-flutter/docs/examples/account/create-o-auth2session.md @@ -10,7 +10,7 @@ void main() { // Init SDK ; Future result = account.createOAuth2Session( - provider: 'bitbucket', + provider: 'amazon', ); result diff --git a/app/sdks/client-flutter/docs/examples/avatars/get-initials.md b/app/sdks/client-flutter/docs/examples/avatars/get-initials.md new file mode 100644 index 0000000000..b2e70788d6 --- /dev/null +++ b/app/sdks/client-flutter/docs/examples/avatars/get-initials.md @@ -0,0 +1,16 @@ +import 'package:appwrite/appwrite.dart'; + +void main() { // Init SDK + Client client = Client(); + Avatars avatars = Avatars(client); + + client + .setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + ; + + String result = avatars.getInitials( + ); + + print(result); // Resource URL string +} \ No newline at end of file diff --git a/app/sdks/client-flutter/docs/examples/locale/get-languages.md b/app/sdks/client-flutter/docs/examples/locale/get-languages.md new file mode 100644 index 0000000000..a4124d3cbd --- /dev/null +++ b/app/sdks/client-flutter/docs/examples/locale/get-languages.md @@ -0,0 +1,20 @@ +import 'package:appwrite/appwrite.dart'; + +void main() { // Init SDK + Client client = Client(); + Locale locale = Locale(client); + + client + .setEndpoint('https://[HOSTNAME_OR_IP]/v1') // Your API Endpoint + .setProject('5df5acd0d48c2') // Your project ID + ; + + Future result = locale.getLanguages( ); + + result + .then((response) { + print(response); + }).catchError((error) { + print(error.response); + }); +} \ No newline at end of file diff --git a/app/sdks/client-flutter/lib/services/account.dart b/app/sdks/client-flutter/lib/services/account.dart index 8cc237d104..c2083da526 100644 --- a/app/sdks/client-flutter/lib/services/account.dart +++ b/app/sdks/client-flutter/lib/services/account.dart @@ -33,10 +33,10 @@ class Account extends Service { /// /// 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 - /// the [/account/verfication](/docs/account#createVerification) route to start - /// 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). + /// the [/account/verfication](/docs/client/account#createVerification) route + /// to start 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/client/account#createSession). /// Future create({@required String email, @required String password, String name = ''}) { final String path = '/account'; @@ -195,7 +195,7 @@ class Account extends Service { /// When the user clicks the confirmation link he is redirected back to your /// app password reset URL with the secret key and email address values /// attached to the URL query string. Use the query string params to submit a - /// request to the [PUT /account/recovery](/docs/account#updateRecovery) + /// request to the [PUT /account/recovery](/docs/client/account#updateRecovery) /// endpoint to complete the process. /// Future createRecovery({@required String email, @required String url}) { @@ -218,7 +218,7 @@ class Account extends Service { /// Use this endpoint to complete the user account password reset. Both the /// **userId** and **secret** arguments will be passed as query parameters to /// the redirect URL you have provided when sending your request to the [POST - /// /account/recovery](/docs/account#createRecovery) endpoint. + /// /account/recovery](/docs/client/account#createRecovery) endpoint. /// /// Please note that in order to avoid a [Redirect /// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) @@ -305,21 +305,36 @@ class Account extends Service { /// first. Use the success and failure arguments to provide a redirect URL's /// back to your app when login is completed. /// - Future createOAuth2Session({@required String provider, String success = 'https://appwrite.io/auth/oauth2/success', String failure = 'https://appwrite.io/auth/oauth2/failure'}) { + Future createOAuth2Session({@required String provider, String success = 'https://appwrite.io/auth/oauth2/success', String failure = 'https://appwrite.io/auth/oauth2/failure', List scopes = const []}) { final String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider); final Map params = { 'success': success, 'failure': failure, + 'scopes': scopes, 'project': client.config['project'], }; + + final List query = []; + + params.forEach((key, value) { + if (value is List) { + for (var item in value) { + query.add(Uri.encodeComponent(key + '[]') + '=' + Uri.encodeComponent(item)); + } + } + else { + query.add(Uri.encodeComponent(key) + '=' + Uri.encodeComponent(value)); + } + }); + Uri endpoint = Uri.parse(client.endPoint); Uri url = new Uri(scheme: endpoint.scheme, host: endpoint.host, port: endpoint.port, path: endpoint.path + path, - queryParameters:params, + query: query.join('&') ); return FlutterWebAuth.authenticate( @@ -361,7 +376,7 @@ class Account extends Service { /// should redirect the user back for your app and allow you to complete the /// verification process by verifying both the **userId** and **secret** /// parameters. Learn more about how to [complete the verification - /// process](/docs/account#updateAccountVerification). + /// process](/docs/client/account#updateAccountVerification). /// /// Please note that in order to avoid a [Redirect /// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) diff --git a/app/sdks/client-flutter/lib/services/avatars.dart b/app/sdks/client-flutter/lib/services/avatars.dart index fc9c403d90..16c7ce59ff 100644 --- a/app/sdks/client-flutter/lib/services/avatars.dart +++ b/app/sdks/client-flutter/lib/services/avatars.dart @@ -145,6 +145,42 @@ class Avatars extends Service { return location.toString(); } + /// Get User Initials + /// + /// Use this endpoint to show your user initials avatar icon on your website or + /// app. By default, this route will try to print your logged-in user name or + /// email initials. You can also overwrite the user name if you pass the 'name' + /// parameter. If no name is given and no user is logged, an empty avatar will + /// be returned. + /// + /// You can use the color and background params to change the avatar colors. By + /// default, a random theme will be selected. The random theme will persist for + /// the user's initials when reloading the same theme will always return for + /// the same initials. + /// + String getInitials({String name = '', int width = 500, int height = 500, String color = '', String background = ''}) { + final String path = '/avatars/initials'; + + final Map params = { + 'name': name, + 'width': width, + 'height': height, + 'color': color, + 'background': background, + 'project': client.config['project'], + }; + + Uri endpoint = Uri.parse(client.endPoint); + Uri location = new Uri(scheme: endpoint.scheme, + host: endpoint.host, + port: endpoint.port, + path: endpoint.path + path, + queryParameters:params, + ); + + return location.toString(); + } + /// Get QR Code /// /// Converts a given plain text to a QR code image. You can use the query diff --git a/app/sdks/client-flutter/lib/services/database.dart b/app/sdks/client-flutter/lib/services/database.dart index 1163c9dbb5..88082feef7 100644 --- a/app/sdks/client-flutter/lib/services/database.dart +++ b/app/sdks/client-flutter/lib/services/database.dart @@ -41,7 +41,10 @@ class Database extends Service { /// Create Document /// - /// Create a new Document. + /// Create a new Document. Before using this route, you should create a new + /// collection resource using either a [server + /// integration](/docs/server/database?sdk=nodejs#createCollection) API or + /// directly from your database console. /// Future createDocument({@required String collectionId, @required dynamic data, @required List read, @required List write, String parentDocument = '', String parentProperty = '', String parentPropertyType = 'assign'}) { final String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId); diff --git a/app/sdks/client-flutter/lib/services/locale.dart b/app/sdks/client-flutter/lib/services/locale.dart index 91ea1567ef..095af4792c 100644 --- a/app/sdks/client-flutter/lib/services/locale.dart +++ b/app/sdks/client-flutter/lib/services/locale.dart @@ -106,9 +106,9 @@ class Locale extends Service { /// List Currencies /// - /// 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. + /// List of all currencies, including currency symbol, 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 getCurrencies() { final String path = '/locale/currencies'; @@ -120,6 +120,24 @@ class Locale extends Service { 'content-type': 'application/json', }; + return client.call(HttpMethod.get, path: path, params: params, headers: headers); + } + + /// List Languages + /// + /// List of all languages classified by ISO 639-1 including 2-letter code, name + /// in English, and name in the respective language. + /// + Future getLanguages() { + final String path = '/locale/languages'; + + final Map params = { + }; + + final Map headers = { + 'content-type': 'application/json', + }; + return client.call(HttpMethod.get, path: path, params: params, headers: headers); } } \ No newline at end of file diff --git a/app/sdks/client-flutter/lib/services/teams.dart b/app/sdks/client-flutter/lib/services/teams.dart index 56e0731687..b9205da455 100644 --- a/app/sdks/client-flutter/lib/services/teams.dart +++ b/app/sdks/client-flutter/lib/services/teams.dart @@ -115,10 +115,14 @@ class Teams extends Service { /// Get team members by the team unique ID. All team members have read access /// for this list of resources. /// - Future getMemberships({@required String teamId}) { + Future getMemberships({@required String teamId, String search = '', int limit = 25, int offset = 0, OrderType orderType = OrderType.asc}) { final String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId); final Map params = { + 'search': search, + 'limit': limit, + 'offset': offset, + 'orderType': orderType.name(), }; final Map headers = { @@ -136,8 +140,8 @@ class Teams extends Service { /// /// Use the 'URL' parameter to redirect the user from the invitation email back /// to your app. When the user is redirected, use the [Update Team Membership - /// Status](/docs/teams#updateMembershipStatus) endpoint to allow the user to - /// accept the invitation to the team. + /// Status](/docs/client/teams#updateMembershipStatus) endpoint to allow the + /// user to accept the invitation to the team. /// /// Please note that in order to avoid a [Redirect /// Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) diff --git a/app/sdks/client-web/src/sdk.js b/app/sdks/client-web/src/sdk.js index f0819912ff..5c98ea89b3 100644 --- a/app/sdks/client-web/src/sdk.js +++ b/app/sdks/client-web/src/sdk.js @@ -708,10 +708,11 @@ * @param {string} provider * @param {string} success * @param {string} failure + * @param {string[]} scopes * @throws {Error} * @return {Promise} */ - createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure') { + createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure', scopes = []) { if(provider === undefined) { throw new Error('Missing required parameter: "provider"'); } @@ -728,9 +729,28 @@ payload['failure'] = failure; } + if(scopes) { + payload['scopes'] = scopes; + } + payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); window.location = config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -882,7 +902,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -925,7 +960,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -955,7 +1005,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -997,7 +1062,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1039,7 +1119,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1093,7 +1188,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1138,7 +1248,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); } @@ -1758,7 +1883,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1811,7 +1951,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1842,7 +1997,22 @@ payload['project'] = config.project; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); } diff --git a/app/sdks/client-web/src/sdk.min.js b/app/sdks/client-web/src/sdk.min.js index e8e6eb368e..7b470dc380 100644 --- a/app/sdks/client-web/src/sdk.min.js +++ b/app/sdks/client-web/src/sdk.min.js @@ -45,10 +45,12 @@ return http.put(path,{'content-type':'application/json',},payload)},getSessions: if(password===undefined){throw new Error('Missing required parameter: "password"')} let path='/account/sessions';let payload={};if(email){payload.email=email} if(password){payload.password=password} -return http.post(path,{'content-type':'application/json',},payload)},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload)},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure'){if(provider===undefined){throw new Error('Missing required parameter: "provider"')} +return http.post(path,{'content-type':'application/json',},payload)},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload)},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure',scopes=[]){if(provider===undefined){throw new Error('Missing required parameter: "provider"')} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload.success=success} if(failure){payload.failure=failure} -payload.project=config.project;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');window.location=config.endpoint+path+((query)?'?'+query:'')},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"')} +if(scopes){payload.scopes=scopes} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getImage:function(url,width=400,height=400){if(url===undefined){throw new Error('Missing required parameter: "url"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getInitials:function(name='',width=500,height=500,color='',background=''){let path='/avatars/initials';let payload={};if(name){payload.name=name} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getQR:function(text,size=400,margin=1,download=0){if(text===undefined){throw new Error('Missing required parameter: "text"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')}};let database={listDocuments:function(collectionId,filters=[],offset=0,limit=50,orderField='$id',orderType='ASC',orderCast='string',search='',first=0,last=0){if(collectionId===undefined){throw new Error('Missing required parameter: "collectionId"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFilePreview:function(fileId,width=0,height=0,quality=100,background='',output=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"')} +let path='/storage/files/{fileId}/download'.replace(new RegExp('{fileId}','g'),fileId);let payload={};payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFileView:function(fileId,as=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"')} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')}};let teams={list:function(search='',limit=25,offset=0,orderType='ASC'){let path='/teams';let payload={};if(search){payload.search=search} +payload.project=config.project;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;index; + createOAuth2Session(provider: string, success: string, failure: string, scopes: string[]): Promise; /** * Delete Account Session diff --git a/app/sdks/console-web/src/sdk.js b/app/sdks/console-web/src/sdk.js index 13ff86337f..27eb23b742 100644 --- a/app/sdks/console-web/src/sdk.js +++ b/app/sdks/console-web/src/sdk.js @@ -744,10 +744,11 @@ * @param {string} provider * @param {string} success * @param {string} failure + * @param {string[]} scopes * @throws {Error} * @return {Promise} */ - createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure') { + createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure', scopes = []) { if(provider === undefined) { throw new Error('Missing required parameter: "provider"'); } @@ -764,11 +765,30 @@ payload['failure'] = failure; } + if(scopes) { + payload['scopes'] = scopes; + } + payload['project'] = config.project; payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); window.location = config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -922,7 +942,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -967,7 +1002,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -999,7 +1049,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1043,7 +1108,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1087,7 +1167,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1143,7 +1238,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1190,7 +1300,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); } @@ -3567,7 +3692,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -3622,7 +3762,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -3655,7 +3810,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); } diff --git a/app/sdks/console-web/src/sdk.min.js b/app/sdks/console-web/src/sdk.min.js index 651bbffeb0..f6a2781f21 100644 --- a/app/sdks/console-web/src/sdk.min.js +++ b/app/sdks/console-web/src/sdk.min.js @@ -45,10 +45,12 @@ return http.put(path,{'content-type':'application/json',},payload)},getSessions: if(password===undefined){throw new Error('Missing required parameter: "password"')} let path='/account/sessions';let payload={};if(email){payload.email=email} if(password){payload.password=password} -return http.post(path,{'content-type':'application/json',},payload)},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload)},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure'){if(provider===undefined){throw new Error('Missing required parameter: "provider"')} +return http.post(path,{'content-type':'application/json',},payload)},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload)},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure',scopes=[]){if(provider===undefined){throw new Error('Missing required parameter: "provider"')} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload.success=success} if(failure){payload.failure=failure} -payload.project=config.project;payload.key=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');window.location=config.endpoint+path+((query)?'?'+query:'')},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"')} +if(scopes){payload.scopes=scopes} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getImage:function(url,width=400,height=400){if(url===undefined){throw new Error('Missing required parameter: "url"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getInitials:function(name='',width=500,height=500,color='',background=''){let path='/avatars/initials';let payload={};if(name){payload.name=name} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getQR:function(text,size=400,margin=1,download=0){if(text===undefined){throw new Error('Missing required parameter: "text"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')}};let database={listCollections:function(search='',limit=25,offset=0,orderType='ASC'){let path='/database/collections';let payload={};if(search){payload.search=search} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFilePreview:function(fileId,width=0,height=0,quality=100,background='',output=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"')} +let path='/storage/files/{fileId}/download'.replace(new RegExp('{fileId}','g'),fileId);let payload={};payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')},getFileView:function(fileId,as=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"')} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'')}};let teams={list:function(search='',limit=25,offset=0,orderType='ASC'){let path='/teams';let payload={};if(search){payload.search=search} +payload.project=config.project;payload.key=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;index; + createOAuth2Session(provider: string, success: string, failure: string, scopes: string[]): Promise; /** * Delete Account Session diff --git a/composer.lock b/composer.lock index f34970a647..266096ddd9 100644 --- a/composer.lock +++ b/composer.lock @@ -485,12 +485,12 @@ "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "23730ab1005ca1e760dcdfbd7d853e6c3f1035d6" + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/23730ab1005ca1e760dcdfbd7d853e6c3f1035d6", - "reference": "23730ab1005ca1e760dcdfbd7d853e6c3f1035d6", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", + "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e", "shasum": "" }, "require": { @@ -544,7 +544,7 @@ "rest", "web service" ], - "time": "2020-06-06T12:11:37+00:00" + "time": "2020-06-16T21:01:06+00:00" }, { "name": "guzzlehttp/promises", @@ -1753,7 +1753,7 @@ "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator", - "reference": "42b2025652507be19807a2dfb78b442fc5ed4102" + "reference": "0125b705aa78e4432972fdcc9de3c42b65ee2024" }, "require": { "ext-curl": "*", @@ -1783,7 +1783,7 @@ } ], "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", - "time": "2020-06-16T06:10:50+00:00" + "time": "2020-06-17T10:09:35+00:00" }, { "name": "doctrine/instantiator", @@ -3382,16 +3382,16 @@ }, { "name": "webmozart/assert", - "version": "1.8.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" + "reference": "9dc4f203e36f2b486149058bade43c851dd97451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451", + "reference": "9dc4f203e36f2b486149058bade43c851dd97451", "shasum": "" }, "require": { @@ -3399,6 +3399,7 @@ "symfony/polyfill-ctype": "^1.8" }, "conflict": { + "phpstan/phpstan": "<0.12.20", "vimeo/psalm": "<3.9.1" }, "require-dev": { @@ -3426,7 +3427,7 @@ "check", "validate" ], - "time": "2020-04-18T12:12:48+00:00" + "time": "2020-06-16T10:16:42+00:00" } ], "aliases": [], diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 37f6a30a69..b7ebbbcccb 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.3 + +- Added support for custom OAuth2 scopes + ## 0.2.2 - Fixed an error that happend when the OAuth session creation request was sent before any other API call diff --git a/public/dist/scripts/app-all.js b/public/dist/scripts/app-all.js index aac804514f..b64a9d423b 100644 --- a/public/dist/scripts/app-all.js +++ b/public/dist/scripts/app-all.js @@ -15,9 +15,9 @@ if(method==='GET'){for(let param in params){if(param.hasOwnProperty(key)){path=a switch(headers['content-type']){case'application/json':params=JSON.stringify(params);break;case'multipart/form-data':let formData=new FormData();Object.keys(params).forEach(function(key){let param=params[key];formData.append(key+(Array.isArray(param)?'[]':''),param);});params=formData;break;} return new Promise(function(resolve,reject){let request=new XMLHttpRequest(),key;request.withCredentials=true;request.open(method,path,true);for(key in headers){if(headers.hasOwnProperty(key)){if(key==='content-type'&&headers[key]==='multipart/form-data'){continue;} request.setRequestHeader(key,headers[key]);}} -request.onload=function(){if(4===request.readyState&&399>=request.status){let data=request.response;let contentType=this.getResponseHeader('content-type')||'';contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;} +request.onload=function(){let data=request.response;let contentType=this.getResponseHeader('content-type')||'';contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;} let cookieFallback=this.getResponseHeader('X-Fallback-Cookies')||'';if(window.localStorage&&cookieFallback){window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');window.localStorage.setItem('cookieFallback',cookieFallback);} -resolve(data);}else{reject(new Error(request.statusText));}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);} +if(4===request.readyState&&399>=request.status){resolve(data);}else{reject(data);}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);} request.onerror=function(){reject(new Error("Network Error"));};request.send(params);})};return{'get':function(path,headers={},params={}){return call('GET',path+((Object.keys(params).length>0)?'?'+buildQuery(params):''),headers,{});},'post':function(path,headers={},params={},progress=null){return call('POST',path,headers,params,progress);},'put':function(path,headers={},params={},progress=null){return call('PUT',path,headers,params,progress);},'patch':function(path,headers={},params={},progress=null){return call('PATCH',path,headers,params,progress);},'delete':function(path,headers={},params={},progress=null){return call('DELETE',path,headers,params,progress);},'addGlobalParam':addGlobalParam,'addGlobalHeader':addGlobalHeader}}(window.document);let account={get:function(){let path='/account';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(email,password,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');} if(password===undefined){throw new Error('Missing required parameter: "password"');} let path='/account';let payload={};if(email){payload['email']=email;} @@ -51,10 +51,13 @@ return http.put(path,{'content-type':'application/json',},payload);},getSessions if(password===undefined){throw new Error('Missing required parameter: "password"');} let path='/account/sessions';let payload={};if(email){payload['email']=email;} if(password){payload['password']=password;} -return http.post(path,{'content-type':'application/json',},payload);},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure'){if(provider===undefined){throw new Error('Missing required parameter: "provider"');} +return http.post(path,{'content-type':'application/json',},payload);},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure',scopes=[]){if(provider===undefined){throw new Error('Missing required parameter: "provider"');} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;} if(failure){payload['failure']=failure;} -payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');window.location=config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');} +if(scopes){payload['scopes']=scopes;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getImage:function(url,width=400,height=400){if(url===undefined){throw new Error('Missing required parameter: "url"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getQR:function(text,size=400,margin=1,download=0){if(text===undefined){throw new Error('Missing required parameter: "text"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');}};let database={listCollections:function(search='',limit=25,offset=0,orderType='ASC'){let path='/database/collections';let payload={};if(search){payload['search']=search;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFilePreview:function(fileId,width=0,height=0,quality=100,background='',output=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"');} +let path='/storage/files/{fileId}/download'.replace(new RegExp('{fileId}','g'),fileId);let payload={};payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFileView:function(fileId,as=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');}};let teams={list:function(search='',limit=25,offset=0,orderType='ASC'){let path='/teams';let payload={};if(search){payload['search']=search;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;index=request.status){let data=request.response;let contentType=this.getResponseHeader('content-type')||'';contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;} +request.onload=function(){let data=request.response;let contentType=this.getResponseHeader('content-type')||'';contentType=contentType.substring(0,contentType.indexOf(';'));switch(contentType){case'application/json':data=JSON.parse(data);break;} let cookieFallback=this.getResponseHeader('X-Fallback-Cookies')||'';if(window.localStorage&&cookieFallback){window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.');window.localStorage.setItem('cookieFallback',cookieFallback);} -resolve(data);}else{reject(new Error(request.statusText));}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);} +if(4===request.readyState&&399>=request.status){resolve(data);}else{reject(data);}};if(progress){request.addEventListener('progress',progress);request.upload.addEventListener('progress',progress,false);} request.onerror=function(){reject(new Error("Network Error"));};request.send(params);})};return{'get':function(path,headers={},params={}){return call('GET',path+((Object.keys(params).length>0)?'?'+buildQuery(params):''),headers,{});},'post':function(path,headers={},params={},progress=null){return call('POST',path,headers,params,progress);},'put':function(path,headers={},params={},progress=null){return call('PUT',path,headers,params,progress);},'patch':function(path,headers={},params={},progress=null){return call('PATCH',path,headers,params,progress);},'delete':function(path,headers={},params={},progress=null){return call('DELETE',path,headers,params,progress);},'addGlobalParam':addGlobalParam,'addGlobalHeader':addGlobalHeader}}(window.document);let account={get:function(){let path='/account';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(email,password,name=''){if(email===undefined){throw new Error('Missing required parameter: "email"');} if(password===undefined){throw new Error('Missing required parameter: "password"');} let path='/account';let payload={};if(email){payload['email']=email;} @@ -51,10 +51,13 @@ return http.put(path,{'content-type':'application/json',},payload);},getSessions if(password===undefined){throw new Error('Missing required parameter: "password"');} let path='/account/sessions';let payload={};if(email){payload['email']=email;} if(password){payload['password']=password;} -return http.post(path,{'content-type':'application/json',},payload);},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure'){if(provider===undefined){throw new Error('Missing required parameter: "provider"');} +return http.post(path,{'content-type':'application/json',},payload);},deleteSessions:function(){let path='/account/sessions';let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createOAuth2Session:function(provider,success='https://appwrite.io/auth/oauth2/success',failure='https://appwrite.io/auth/oauth2/failure',scopes=[]){if(provider===undefined){throw new Error('Missing required parameter: "provider"');} let path='/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}','g'),provider);let payload={};if(success){payload['success']=success;} if(failure){payload['failure']=failure;} -payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');window.location=config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');} +if(scopes){payload['scopes']=scopes;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getCreditCard:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFlag:function(code,width=100,height=100,quality=100){if(code===undefined){throw new Error('Missing required parameter: "code"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getImage:function(url,width=400,height=400){if(url===undefined){throw new Error('Missing required parameter: "url"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getQR:function(text,size=400,margin=1,download=0){if(text===undefined){throw new Error('Missing required parameter: "text"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');}};let database={listCollections:function(search='',limit=25,offset=0,orderType='ASC'){let path='/database/collections';let payload={};if(search){payload['search']=search;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFilePreview:function(fileId,width=0,height=0,quality=100,background='',output=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"');} +let path='/storage/files/{fileId}/download'.replace(new RegExp('{fileId}','g'),fileId);let payload={};payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFileView:function(fileId,as=''){if(fileId===undefined){throw new Error('Missing required parameter: "fileId"');} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;indexkey+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');}};let teams={list:function(search='',limit=25,offset=0,orderType='ASC'){let path='/teams';let payload={};if(search){payload['search']=search;} +payload['project']=config.project;payload['key']=config.key;let query=[];for(let p in payload){if(Array.isArray(payload[p])){for(let index=0;index= request.status) { - let data = request.response; - let contentType = this.getResponseHeader('content-type') || ''; - contentType = contentType.substring(0, contentType.indexOf(';')); - - switch (contentType) { - case 'application/json': - data = JSON.parse(data); - break; - } - - let cookieFallback = this.getResponseHeader('X-Fallback-Cookies') || ''; - - if(window.localStorage && cookieFallback) { - window.console.warn('Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.'); - window.localStorage.setItem('cookieFallback', cookieFallback); - } - resolve(data); - } else { - reject(new Error(request.statusText)); + reject(data); } }; @@ -745,10 +744,11 @@ * @param {string} provider * @param {string} success * @param {string} failure + * @param {string[]} scopes * @throws {Error} * @return {Promise} */ - createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure') { + createOAuth2Session: function(provider, success = 'https://appwrite.io/auth/oauth2/success', failure = 'https://appwrite.io/auth/oauth2/failure', scopes = []) { if(provider === undefined) { throw new Error('Missing required parameter: "provider"'); } @@ -765,11 +765,30 @@ payload['failure'] = failure; } + if(scopes) { + payload['scopes'] = scopes; + } + payload['project'] = config.project; payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); window.location = config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -923,7 +942,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -968,7 +1002,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1000,7 +1049,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1044,7 +1108,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1088,7 +1167,93 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); + + return config.endpoint + path + ((query) ? '?' + query : ''); + }, + + /** + * Get User Initials + * + * Use this endpoint to show your user initials avatar icon on your website or + * app. By default, this route will try to print your logged-in user name or + * email initials. You can also overwrite the user name if you pass the 'name' + * parameter. If no name is given and no user is logged, an empty avatar will + * be returned. + * + * You can use the color and background params to change the avatar colors. By + * default, a random theme will be selected. The random theme will persist for + * the user's initials when reloading the same theme will always return for + * the same initials. + * + * @param {string} name + * @param {number} width + * @param {number} height + * @param {string} color + * @param {string} background + * @throws {Error} + * @return {string} + */ + getInitials: function(name = '', width = 500, height = 500, color = '', background = '') { + let path = '/avatars/initials'; + + let payload = {}; + + if(name) { + payload['name'] = name; + } + + if(width) { + payload['width'] = width; + } + + if(height) { + payload['height'] = height; + } + + if(color) { + payload['color'] = color; + } + + if(background) { + payload['background'] = background; + } + + payload['project'] = config.project; + + payload['key'] = config.key; + + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -1135,7 +1300,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); } @@ -1979,9 +2159,9 @@ /** * List Currencies * - * 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. + * List of all currencies, including currency symbol, 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. * * @throws {Error} * @return {Promise} @@ -1991,6 +2171,26 @@ let payload = {}; + return http + .get(path, { + 'content-type': 'application/json', + }, payload); + }, + + /** + * List Languages + * + * List of all languages classified by ISO 639-1 including 2-letter code, name + * in English, and name in the respective language. + * + * @throws {Error} + * @return {Promise} + */ + getLanguages: function() { + let path = '/locale/languages'; + + let payload = {}; + return http .get(path, { 'content-type': 'application/json', @@ -3492,7 +3692,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -3547,7 +3762,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }, @@ -3580,7 +3810,22 @@ payload['key'] = config.key; - let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&'); + + let query = []; + + for (let p in payload) { + if(Array.isArray(payload[p])) { + for (let index = 0; index < payload[p].length; index++) { + let param = payload[p][index]; + query.push(encodeURIComponent(p + '[]') + "=" + encodeURIComponent(param)); + } + } + else { + query.push(encodeURIComponent(p) + "=" + encodeURIComponent(payload[p])); + } + } + + query = query.join("&"); return config.endpoint + path + ((query) ? '?' + query : ''); }