1
0
Fork 0
mirror of synced 2024-06-29 03:30:34 +12:00

Merge pull request #399 from appwrite/team-features

Team features
This commit is contained in:
Eldad A. Fux 2020-06-11 11:24:48 +03:00 committed by GitHub
commit 50d934bac2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 878 additions and 281 deletions

View file

@ -6,10 +6,14 @@
- Added option to force HTTPS connection to the Appwrite server (_APP_OPTIONS_FORCE_HTTPS)
- Added Google Fonts to Appwrite for offline availability
- Added a new route in the Avatars API to get user initials avatar
- Added option to delete team from the console
- Added option to view team members from the console
- Added option to join a user to any team from the console
## Bug Fixes
- Fixed output of /v1/health/queue/certificates returning wrong data
- Fixed bug where team members count was wrong in some cases
- Fixed network calculation for uploaded files
- Fixed a UI bug preventing float values in numeric fields

View file

@ -215,7 +215,7 @@ $utopia->post('/v1/teams/:teamId/memberships')
->param('roles', [], function () { return new ArrayList(new Text(128)); }, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions).')
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. 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.') // TODO add our own built-in confirm page
->action(
function ($teamId, $email, $name, $roles, $url) use ($response, $register, $project, $user, $audit, $projectDB) {
function ($teamId, $email, $name, $roles, $url) use ($response, $register, $project, $user, $audit, $projectDB, $mode) {
$name = (empty($name)) ? $email : $name;
$team = $projectDB->getDocument($teamId);
@ -285,7 +285,7 @@ $utopia->post('/v1/teams/:teamId/memberships')
}
}
if (!$isOwner) {
if (!$isOwner && (APP_MODE_ADMIN !== $mode)) {
throw new Exception('User is not allowed to send invitations for this team', 401);
}
@ -302,11 +302,18 @@ $utopia->post('/v1/teams/:teamId/memberships')
'roles' => $roles,
'invited' => time(),
'joined' => 0,
'confirm' => false,
'confirm' => (APP_MODE_ADMIN === $mode),
'secret' => Auth::hash($secret),
]);
$membership = $projectDB->createDocument($membership->getArrayCopy());
if(APP_MODE_ADMIN === $mode) { // Allow admin to create membership
Authorization::disable();
$membership = $projectDB->createDocument($membership->getArrayCopy());
Authorization::reset();
}
else {
$membership = $projectDB->createDocument($membership->getArrayCopy());
}
if (false === $membership) {
throw new Exception('Failed saving membership to DB', 500);
@ -334,7 +341,9 @@ $utopia->post('/v1/teams/:teamId/memberships')
$mail->AltBody = strip_tags($body->render());
try {
$mail->send();
if(APP_MODE_ADMIN !== $mode) { // No need in comfirmation when in admin mode
$mail->send();
}
} catch (\Exception $error) {
throw new Exception('Error sending mail: ' . $error->getMessage(), 500);
}
@ -371,8 +380,12 @@ $utopia->get('/v1/teams/:teamId/memberships')
->label('sdk.method', 'getMemberships')
->label('sdk.description', '/docs/references/teams/get-team-members.md')
->param('teamId', '', function () { return new UID(); }, 'Team unique ID.')
->param('search', '', function () { return new Text(256); }, 'Search term to filter your list results.', true)
->param('limit', 25, function () { return new Range(0, 100); }, 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true)
->param('offset', 0, function () { return new Range(0, 2000); }, 'Results offset. The default value is 0. Use this param to manage pagination.', true)
->param('orderType', 'ASC', function () { return new WhiteList(['ASC', 'DESC']); }, 'Order result by ASC or DESC order.', true)
->action(
function ($teamId) use ($response, $projectDB) {
function ($teamId, $search, $limit, $offset, $orderType) use ($response, $projectDB) {
$team = $projectDB->getDocument($teamId);
if (empty($team->getId()) || Database::SYSTEM_COLLECTION_TEAMS != $team->getCollection()) {
@ -380,8 +393,12 @@ $utopia->get('/v1/teams/:teamId/memberships')
}
$memberships = $projectDB->getCollection([
'limit' => 50,
'offset' => 0,
'limit' => $limit,
'offset' => $offset,
'orderField' => 'joined',
'orderType' => $orderType,
'orderCast' => 'int',
'search' => $search,
'filters' => [
'$collection='.Database::SYSTEM_COLLECTION_MEMBERSHIPS,
'teamId='.$teamId,
@ -408,15 +425,8 @@ $utopia->get('/v1/teams/:teamId/memberships')
]));
}
usort($users, function ($a, $b) {
if ($a['joined'] === 0 || $b['joined'] === 0) {
return $b['joined'] - $a['joined'];
}
$response->json(['sum' => $projectDB->getSum(), 'memberships' => $users]);
return $a['joined'] - $b['joined'];
});
$response->json($users);
}
);
@ -583,9 +593,11 @@ $utopia->delete('/v1/teams/:teamId/memberships/:inviteId')
throw new Exception('Failed to remove membership from DB', 500);
}
$team = $projectDB->updateDocument(array_merge($team->getArrayCopy(), [
'sum' => $team->getAttribute('sum', 0) - 1,
]));
if ($membership->getAttribute('confirm')) { // Count only confirmed members
$team = $projectDB->updateDocument(array_merge($team->getArrayCopy(), [
'sum' => $team->getAttribute('sum', 0) - 1,
]));
}
if (false === $team) {
throw new Exception('Failed saving team to DB', 500);

View file

@ -277,14 +277,26 @@ $utopia->get('/console/users')
->setParam('body', $page);
});
$utopia->get('/console/users/view')
$utopia->get('/console/users/user')
->desc('Platform console project user')
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
$page = new View(__DIR__.'/../../views/console/users/view.phtml');
$page = new View(__DIR__.'/../../views/console/users/user.phtml');
$layout
->setParam('title', APP_NAME.' - View User')
->setParam('title', APP_NAME.' - User')
->setParam('body', $page);
});
$utopia->get('/console/users/teams/team')
->desc('Platform console project team')
->label('permission', 'public')
->label('scope', 'console')
->action(function () use ($layout) {
$page = new View(__DIR__.'/../../views/console/users/team.phtml');
$layout
->setParam('title', APP_NAME.' - Team')
->setParam('body', $page);
});

View file

@ -1,7 +1,7 @@
# Appwrite Web SDK
![License](https://img.shields.io/github/license/appwrite/sdk-for-js.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)
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 Web SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools.

View file

@ -5,7 +5,7 @@ sdk
.setProject('5df5acd0d48c2') // Your project ID
;
let promise = sdk.account.createOAuth2Session('bitbucket');
let promise = sdk.account.createOAuth2Session('amazon');
promise.then(function (response) {
console.log(response); // Success

View file

@ -276,10 +276,10 @@
*
* 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).
*
* @param {string} email
* @param {string} password
@ -522,7 +522,7 @@
* 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.
*
* @param {string} email
@ -563,7 +563,7 @@
* 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)
@ -772,7 +772,7 @@
* 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)
@ -1168,7 +1168,10 @@
/**
* 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.
*
* @param {string} collectionId
* @param {object} data
@ -1942,10 +1945,14 @@
* for this list of resources.
*
* @param {string} teamId
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} orderType
* @throws {Error}
* @return {Promise}
*/
getMemberships: function(teamId) {
getMemberships: function(teamId, search = '', limit = 25, offset = 0, orderType = 'ASC') {
if(teamId === undefined) {
throw new Error('Missing required parameter: "teamId"');
}
@ -1954,6 +1961,22 @@
let payload = {};
if(search) {
payload['search'] = search;
}
if(limit) {
payload['limit'] = limit;
}
if(offset) {
payload['offset'] = offset;
}
if(orderType) {
payload['orderType'] = orderType;
}
return http
.get(path, {
'content-type': 'application/json',
@ -1969,8 +1992,8 @@
*
* 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)

View file

@ -148,8 +148,12 @@ let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payloa
if(name===undefined){throw new Error('Missing required parameter: "name"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(name){payload.name=name}
return http.put(path,{'content-type':'application/json',},payload)},delete:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload)},getMemberships:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.get(path,{'content-type':'application/json',},payload)},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload)},getMemberships:function(teamId,search='',limit=25,offset=0,orderType='ASC'){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(search){payload.search=search}
if(limit){payload.limit=limit}
if(offset){payload.offset=offset}
if(orderType){payload.orderType=orderType}
return http.get(path,{'content-type':'application/json',},payload)},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
if(email===undefined){throw new Error('Missing required parameter: "email"')}
if(roles===undefined){throw new Error('Missing required parameter: "roles"')}
if(url===undefined){throw new Error('Missing required parameter: "url"')}

View file

@ -64,10 +64,10 @@ declare namespace Appwrite {
*
* 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).
*
* @param {string} email
* @param {string} password
@ -170,7 +170,7 @@ declare namespace Appwrite {
* 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.
*
* @param {string} email
@ -186,7 +186,7 @@ declare namespace Appwrite {
* 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)
@ -276,7 +276,7 @@ declare namespace Appwrite {
* 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)
@ -431,7 +431,10 @@ declare namespace Appwrite {
/**
* 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.
*
* @param {string} collectionId
* @param {object} data
@ -758,10 +761,14 @@ declare namespace Appwrite {
* for this list of resources.
*
* @param {string} teamId
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} orderType
* @throws {Error}
* @return {Promise}
*/
getMemberships(teamId: string): Promise<object>;
getMemberships(teamId: string, search: string, limit: number, offset: number, orderType: string): Promise<object>;
/**
* Create Team Membership
@ -772,8 +779,8 @@ declare namespace Appwrite {
*
* 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)

View file

@ -1,7 +1,7 @@
# Appwrite Console SDK
![License](https://img.shields.io/github/license/appwrite/sdk-for-console.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)
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 Console SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools.

View file

@ -6,7 +6,7 @@ sdk
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
let promise = sdk.account.createOAuth2Session('bitbucket');
let promise = sdk.account.createOAuth2Session('amazon');
promise.then(function (response) {
console.log(response); // Success

View file

@ -6,7 +6,7 @@ sdk
.setKey('919c2d18fb5d4...a2ae413da83346ad2') // Your secret API key
;
let promise = sdk.projects.updateOAuth2('[PROJECT_ID]', 'bitbucket');
let promise = sdk.projects.updateOAuth2('[PROJECT_ID]', 'amazon');
promise.then(function (response) {
console.log(response); // Success

View file

@ -312,10 +312,10 @@
*
* 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).
*
* @param {string} email
* @param {string} password
@ -558,7 +558,7 @@
* 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.
*
* @param {string} email
@ -599,7 +599,7 @@
* 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)
@ -810,7 +810,7 @@
* 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)
@ -1421,7 +1421,10 @@
/**
* 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.
*
* @param {string} collectionId
* @param {object} data
@ -3753,10 +3756,14 @@
* for this list of resources.
*
* @param {string} teamId
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} orderType
* @throws {Error}
* @return {Promise}
*/
getMemberships: function(teamId) {
getMemberships: function(teamId, search = '', limit = 25, offset = 0, orderType = 'ASC') {
if(teamId === undefined) {
throw new Error('Missing required parameter: "teamId"');
}
@ -3765,6 +3772,22 @@
let payload = {};
if(search) {
payload['search'] = search;
}
if(limit) {
payload['limit'] = limit;
}
if(offset) {
payload['offset'] = offset;
}
if(orderType) {
payload['orderType'] = orderType;
}
return http
.get(path, {
'content-type': 'application/json',
@ -3780,8 +3803,8 @@
*
* 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)

View file

@ -319,8 +319,12 @@ let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payloa
if(name===undefined){throw new Error('Missing required parameter: "name"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(name){payload.name=name}
return http.put(path,{'content-type':'application/json',},payload)},delete:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload)},getMemberships:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.get(path,{'content-type':'application/json',},payload)},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload)},getMemberships:function(teamId,search='',limit=25,offset=0,orderType='ASC'){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(search){payload.search=search}
if(limit){payload.limit=limit}
if(offset){payload.offset=offset}
if(orderType){payload.orderType=orderType}
return http.get(path,{'content-type':'application/json',},payload)},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"')}
if(email===undefined){throw new Error('Missing required parameter: "email"')}
if(roles===undefined){throw new Error('Missing required parameter: "roles"')}
if(url===undefined){throw new Error('Missing required parameter: "url"')}

View file

@ -85,10 +85,10 @@ declare namespace Appwrite {
*
* 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).
*
* @param {string} email
* @param {string} password
@ -191,7 +191,7 @@ declare namespace Appwrite {
* 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.
*
* @param {string} email
@ -207,7 +207,7 @@ declare namespace Appwrite {
* 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)
@ -297,7 +297,7 @@ declare namespace Appwrite {
* 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)
@ -522,7 +522,10 @@ declare namespace Appwrite {
/**
* 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.
*
* @param {string} collectionId
* @param {object} data
@ -1402,10 +1405,14 @@ declare namespace Appwrite {
* for this list of resources.
*
* @param {string} teamId
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} orderType
* @throws {Error}
* @return {Promise}
*/
getMemberships(teamId: string): Promise<object>;
getMemberships(teamId: string, search: string, limit: number, offset: number, orderType: string): Promise<object>;
/**
* Create Team Membership
@ -1416,8 +1423,8 @@ declare namespace Appwrite {
*
* 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)

View file

@ -24,13 +24,13 @@
<div class="col span-3 text-align-center margin-bottom">
<img src="" data-ls-attrs="src={{account|gravatar}}" data-size="200" height="150" alt="User Avatar" class="avatar huge huge margin-bottom-small" />
<br />
<!-- <br /> -->
<a href="https://en.gravatar.com/gravatars/new/" rel="noopener" class="button margin-bottom-small link-animation-disabled" target="_blank"><i class="icon-upload"></i> Upload</a>
<!-- <a href="https://en.gravatar.com/gravatars/new/" rel="noopener" class="button margin-bottom-small link-animation-disabled" target="_blank"><i class="icon-upload"></i> Upload</a> -->
<br />
<!-- <br /> -->
<small class="text-size-small">(via <a href="https://gravatar.com/" target="_blank" rel="noopener">gravatar.com <i class="icon-link-ext"></i></a>)</small>
<!-- <small class="text-size-small">(via <a href="https://gravatar.com/" target="_blank" rel="noopener">gravatar.com <i class="icon-link-ext"></i></a>)</small> -->
</div>
<div class="col span-9">
@ -57,7 +57,7 @@
<input name="name" id="name" type="text" autocomplete="off" data-ls-bind="{{account.name}}" required class="margin-bottom-no">
</div>
<div class="col span-4">
<button type="submit" class="fill reverse margin-bottom-no">Update Name</button>
<button type="submit" class="fill margin-bottom-no">Update Name</button>
</div>
</div>
</form>
@ -85,7 +85,7 @@
<input name="email" type="email" class="margin-bottom-no" autocomplete="off" placeholder="me@example.com" data-ls-bind="{{account.email}}" required>
</div>
<div class="col span-4">
<div data-ui-modal class="modal box close width-small height-small" data-button-text="Update Email" data-button-class="fill reverse">
<div data-ui-modal class="modal box close width-small height-small" data-button-text="Update Email" data-button-class="fill">
<h3>Confirm Password</h3>
<hr />
@ -103,7 +103,7 @@
<hr />
<div data-ui-modal class="modal box close width-small" data-button-text="Update Password" data-button-class="reverse">
<div data-ui-modal class="modal box close width-small" data-button-text="Update Password" data-button-class="">
<h1>Update Password</h1>
<form name="update-password"

View file

@ -385,7 +385,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
data-success-param-trigger-events="teams.getMemberships">
<div class="box margin-bottom">
<ul data-ls-loop="members" data-ls-as="member" class="list">
<ul data-ls-loop="members.memberships" data-ls-as="member" class="list">
<li class="clear">
<form class="pull-end"
data-analytics-event="submit"
@ -432,10 +432,10 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
data-scope="console"
data-event="teams.deleteMembership.resend"
data-success="alert,trigger"
data-success-param-alert-text="Invitation Sent Successfully"
data-success-param-alert-text="Invitation sent successfully"
data-success-param-trigger-events="teams.createMembership.resent"
data-failure="alert"
data-failure-param-alert-text="Failed to Send inivitation"
data-failure-param-alert-text="Failed to send inivitation"
data-failure-param-alert-classname="error">
<input name="teamId" type="hidden" data-ls-bind="{{member.teamId}}">
@ -470,10 +470,10 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
data-event="submit"
data-loading="Sending invitation, please wait..."
data-success="alert,trigger,reset"
data-success-param-alert-text="Invitation Sent Successfully"
data-success-param-alert-text="Invitation sent successfully"
data-success-param-trigger-events="teams.createMembership"
data-failure="alert"
data-failure-param-alert-text="Failed to Send Invite"
data-failure-param-alert-text="Failed to send invite"
data-failure-param-alert-classname="error">
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{console-project.teamId}}">

View file

@ -107,7 +107,7 @@ $providers = $this->getParam('providers', []);
<img src="" data-ls-attrs="src={{user|gravatar}}" data-size="45" alt="User Avatar" class="avatar pull-start" loading="lazy" width="30" height="30" />
</td>
<td data-title="Name: ">
<a data-ls-attrs="href=/console/users/view?id={{user.$id}}&project={{router.params.project}}">
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
<span data-ls-bind="{{user.name}}"></span>
<span data-ls-if="{{user.name}} === ''">-----</span>
</a>
@ -253,36 +253,7 @@ $providers = $this->getParam('providers', []);
<img src="" data-ls-attrs="src={{team.name|gravatar}}" data-size="45" alt="Collection Avatar" class="avatar margin-end pull-start" loading="lazy" width="30" height="30" />
</td>
<td data-title="Name: ">
<div data-ui-modal class="box modal close" data-button-text="{{team.name}}" data-button-class="link">
<h1>Update Team</h1>
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Team"
data-service="teams.update"
data-scope="sdk"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated team successfully"
data-success-param-trigger-events="teams.update"
data-failure="alert"
data-failure-param-alert-text="Failed to update team"
data-failure-param-alert-classname="error">
<label for="name">ID</label>
<div class="input-copy">
<input data-ls-attrs="id=team-id-{{team.$id}}" name="teamId" data-forms-copy type="text" disabled data-ls-bind="{{team.$id}}" />
</div>
<label for="name">Name</label>
<input data-ls-attrs="id=team-name-{{team.$id}}" name="name" type="text" autocomplete="off" data-ls-bind="{{team.name}}">
<hr />
<button>Update</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</form>
</div>
<a data-ls-attrs="href=/console/users/teams/team?id={{team.$id}}&project={{router.params.project}}" data-ls-bind="{{team.name}}"></a>
</td>
<td data-title="Members: "><span data-ls-bind="{{team.sum}} members"></span></td>
<td data-title="Date Created: "><small data-ls-bind="{{team.dateCreated|date-text}}"></small></td>

View file

@ -0,0 +1,230 @@
<div
data-service="teams.get"
data-name="team"
data-event="load,teams.update,teams.deleteMembership,teams.createMembership"
data-param-team-id="{{router.params.id}}"
data-success="trigger"
data-success-param-trigger-events="teams.get">
<div class="cover">
<h1 class="zone xl margin-bottom-large">
<a data-ls-attrs="href=/console/users/teams?project={{router.params.project}}" class="back text-size-small"><i class="icon-left-open"></i> Teams</a>
<br />
<span data-ls-bind="{{team.name}}">&nbsp;</span>
<span data-ls-if="{{team.name}} === ''">Unknown</span>
</h1>
</div>
<div data-ui-modal class="modal width-large box close" data-button-hide="on" data-open-event="open-json">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h2>JSON View</h2>
<div class="margin-bottom">
<input type="hidden" data-ls-bind="{{team}}" data-forms-code />
</div>
<button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</div>
<div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
<li data-state="/console/users/teams/team?id={{router.params.id}}&project={{router.params.project}}">
<h2>General</h2>
<div class="row responsive margin-top-negative">
<div class="col span-8 margin-bottom-large">
<label>&nbsp;</label>
<div class="box margin-bottom-large">
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Team"
data-service="teams.update"
data-scope="sdk"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated team successfully"
data-success-param-trigger-events="teams.update"
data-failure="alert"
data-failure-param-alert-text="Failed to update team"
data-failure-param-alert-classname="error">
<input data-ls-attrs="id=team-id-{{team.$id}}" name="teamId" type="hidden" disabled data-ls-bind="{{team.$id}}" />
<label for="name">Name</label>
<input data-ls-attrs="id=team-name-{{team.$id}}" name="name" type="text" autocomplete="off" data-ls-bind="{{team.name}}">
<hr />
<button>Update</button>
</form>
</div>
<h3 class="margin-bottom">Members</h3>
<div
data-service="teams.getMemberships"
data-event="load,teams.create,teams.update,teams.delete,teams.deleteMembership,teams.createMembership"
data-param-team-id="{{router.params.id}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-offset="{{router.params.offset}}"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-members">
<div data-ls-if="0 == {{project-members.sum}}" class="box margin-bottom">
<h3 class="margin-bottom-small text-bold">No Memberships Found</h3>
<p class="margin-bottom-no">Add your first team member to get started</p>
</div>
<div data-ls-if="0 != {{project-members.sum}}">
<div class="margin-bottom-small margin-end-small text-align-end text-size-small margin-top-negative"><span data-ls-bind="{{project-members.sum}}"></span> memberships found</div>
<div class="box margin-bottom">
<ul data-ls-loop="project-members.memberships" data-ls-as="member" class="list">
<li class="clear">
<form class="pull-end"
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Delete Team Membership"
data-service="teams.deleteMembership"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Member Removed Successfully"
data-success-param-trigger-events="teams.deleteMembership"
data-failure="alert"
data-failure-param-alert-text="Failed to Remove Member"
data-failure-param-alert-classname="error">
<input name="teamId" data-ls-attrs="id={{member.$id}}" type="hidden" data-ls-bind="{{router.params.id}}">
<input name="inviteId" data-ls-attrs="id=leave-inviteId-{{member.$id}}" type="hidden" data-ls-bind="{{member.$id}}">
<button class="danger">Remove</button>
</form>
<img src="" data-ls-attrs="src={{member|gravatar}}" data-size="200" alt="User Avatar" class="avatar pull-start margin-end" loading="lazy" width="60" height="60" />
<div class="margin-bottom-tiny">
<a data-ls-attrs="href=/console/users/user?id={{member.userId}}&project={{router.params.project}}"><span data-ls-bind="{{member.name}}"></span></a> &nbsp;&nbsp;
<span data-ls-if="1 == {{member.roles.length}}" class="text-fade tooltip" data-ls-bind="({{member.roles.length}} role)" data-ls-attrs="data-tooltip={{member.roles|arraySentence}}"></span>
<span data-ls-if="2 <= {{member.roles.length}}" class="text-fade tooltip" data-ls-bind="({{member.roles.length}} roles)" data-ls-attrs="data-tooltip={{member.roles|arraySentence}}"></span>
</div>
<small class="text-size-small text-fade" data-ls-bind="{{member.email}}"></small> &nbsp;&nbsp;<span data-ls-if="false === {{member.confirm}}" class="text-danger text-size-small">Pending Approval</span>
</li>
</ul>
</div>
</div>
<div data-ui-modal class="box modal close" data-button-text="Add Member" data-button-class="pull-start">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Add Member</h1>
<form name="teams.createTeamMembership"
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Create Team Membership"
data-service="teams.createMembership"
data-event="submit"
data-loading="Sending invitation, please wait..."
data-success="alert,trigger,reset"
data-success-param-alert-text="Invitation sent successfully"
data-success-param-trigger-events="teams.createMembership"
data-failure="alert"
data-failure-param-alert-text="Failed to send invite"
data-failure-param-alert-classname="error">
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{team.$id}}">
<input name="url" type="hidden" data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}" />
<label for="email">Email</label>
<input name="email" id="email" type="email" autocomplete="email" required>
<label for="team-name">Name <small>(optional)</small></label>
<input name="name" id="team-name" type="text" autocomplete="name">
<label for="roles">Roles</label>
<input type="hidden" id="team-roles" name="roles" data-forms-tags data-cast-to="json" data-ls-bind="<?php echo $this->escape(json_encode(['owner'])); ?>" placeholder="Add any role you like" />
<hr />
<div class="clear">
<button>Add Member</button>
&nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</div>
</form>
</div>
<div class="clear text-align-center paging pull-end">
<form
data-service="teams.getMemberships"
data-event="submit"
data-param-team-id="{{router.params.id}}"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-members"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-back data-offset="{{router.params.offset}}" data-sum="{{project-members.sum}}" class="margin-end round small" aria-label="Back"><i class="icon-left-open"></i></button>
</form>
<span data-ls-bind="{{router.params.offset|pageCurrent}} / {{project-members.sum|pageTotal}}"></span>
<form
data-service="teams.getMemberships"
data-event="submit"
data-param-team-id="{{router.params.id}}"
data-param-search="{{router.params.search}}"
data-param-limit="<?php echo APP_PAGING_LIMIT; ?>"
data-param-order-type="DESC"
data-scope="sdk"
data-name="project-members"
data-success="state"
data-success-param-state-keys="search,offset">
<button name="offset" data-paging-next data-offset="{{router.params.offset}}" data-sum="{{project-members.sum}}" class="margin-start round small" aria-label="Next"><i class="icon-right-open"></i></button>
</form>
</div>
</div>
</div>
<div class="col span-4 sticky-top">
<label>Team ID</label>
<div class="input-copy margin-bottom">
<input id="uid" type="text" autocomplete="off" placeholder="" data-ls-bind="{{team.$id}}" disabled data-forms-copy>
</div>
<ul class="margin-bottom-large text-fade text-size-small">
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> <button data-ls-ui-trigger="open-json" class="link text-size-small">View as JSON</button></li>
<li class="margin-bottom-small"><i class="icon-angle-circled-right margin-start-tiny margin-end-tiny"></i> Created: <span data-ls-bind="{{team.dateCreated|date-text}}"></span></li>
</ul>
<form name="teams.delete" class="margin-bottom"
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Delete Team"
data-service="teams.delete"
data-event="submit"
data-confirm="Are you sure you want to delete this team?"
data-param-team-id="{{router.params.id}}"
data-success="alert,trigger,redirect"
data-success-param-alert-text="Team deleted successfully"
data-success-param-trigger-events="users.update"
data-success-param-redirect-url="/console/users/teams?project={{router.params.project}}"
data-failure="alert"
data-failure-param-alert-text="Failed to delete team"
data-failure-param-alert-classname="error">
<button type="submit" class="danger fill">Delete Team</button>
</form>
</div>
</div>
</li>
</ul>
</div>
</div>

View file

@ -30,7 +30,7 @@
<div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
<li data-state="/console/users/view?id={{router.params.id}}&project={{router.params.project}}">
<li data-state="/console/users/user?id={{router.params.id}}&project={{router.params.project}}">
<h2>General</h2>
<div data-ls-if="{{user.status}} === <?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>" style="display: none" class="box padding-small danger margin-bottom-xxl text-align-center">
@ -113,10 +113,10 @@
data-event="submit"
data-param-user-id="{{router.params.id}}"
data-success="alert,trigger"
data-success-param-alert-text="Blocked User Successfully"
data-success-param-alert-text="Blocked user successfully"
data-success-param-trigger-events="users.update"
data-failure="alert"
data-failure-param-alert-text="Failed to Block User"
data-failure-param-alert-text="Failed to block user"
data-failure-param-alert-classname="error">
<button name="status" type="submit" class="danger fill" value="<?php echo \Appwrite\Auth\Auth::USER_STATUS_BLOCKED; ?>">Block Account</button>
@ -132,10 +132,10 @@
data-event="submit"
data-param-user-id="{{router.params.id}}"
data-success="alert,trigger"
data-success-param-alert-text="Activated User Successfully"
data-success-param-alert-text="Activated user successfully"
data-success-param-trigger-events="users.update"
data-failure="alert"
data-failure-param-alert-text="Failed to Activate User"
data-failure-param-alert-text="Failed to activate user"
data-failure-param-alert-classname="error">
<button name="status" type="submit" class="fill" value="<?php echo \Appwrite\Auth\Auth::USER_STATUS_ACTIVATED; ?>">Activate Account</button>
@ -144,7 +144,7 @@
</div>
</div>
</li>
<li data-state="/console/users/view/devices?id={{router.params.id}}&project={{router.params.project}}">
<li data-state="/console/users/user/devices?id={{router.params.id}}&project={{router.params.project}}">
<h2>Devices</h2>
<div
@ -210,7 +210,7 @@
</div>
</li>
<li data-state="/console/users/view/audit?id={{router.params.id}}&project={{router.params.project}}">
<li data-state="/console/users/user/audit?id={{router.params.id}}&project={{router.params.project}}">
<h2>Activity</h2>
<div

View file

@ -12,7 +12,7 @@
data-param-secret="{{router.params.secret}}"
data-success="redirect,alert,trigger"
data-success-param-redirect-url="/console?project={{router.params.project}}"
data-success-param-alert-text="Joined Team Successfully"
data-success-param-alert-text="Joined team successfully"
data-success-param-trigger-events="teams.updateMembershipStatus"
data-failure="redirect,alert"
data-success-param-redirect-url="/console"

View file

@ -18,8 +18,7 @@ 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;}
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);}
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 iframe=function(method,url,params){let form=document.createElement('form');form.setAttribute('method',method);form.setAttribute('action',config.endpoint+url);for(let key in params){if(params.hasOwnProperty(key)){let hiddenField=document.createElement("input");hiddenField.setAttribute("type","hidden");hiddenField.setAttribute("name",key);hiddenField.setAttribute("value",params[key]);form.appendChild(hiddenField);}}
document.body.appendChild(form);return form.submit();};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"');}
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;}
if(password){payload['password']=password;}
@ -52,12 +51,10 @@ 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,failure){if(provider===undefined){throw new Error('Missing required parameter: "provider"');}
if(success===undefined){throw new Error('Missing required parameter: "success"');}
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
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"');}
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('&');return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
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"');}
let path='/account/sessions/{sessionId}'.replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createVerification:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/account/verification';let payload={};if(url){payload['url']=url;}
return http.post(path,{'content-type':'application/json',},payload);},updateVerification:function(userId,secret){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
@ -68,26 +65,26 @@ return http.put(path,{'content-type':'application/json',},payload);}};let avatar
let path='/avatars/browsers/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/credit-cards/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/avatars/favicon';let payload={};if(url){payload['url']=url;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/flags/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/image';let payload={};if(url){payload['url']=url;}
if(width){payload['width']=width;}
if(height){payload['height']=height;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/qr';let payload={};if(text){payload['text']=text;}
if(size){payload['size']=size;}
if(margin){payload['margin']=margin;}
if(download){payload['download']=download;}
return http.get(path,{'content-type':'application/json',},payload);}};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=Object.keys(payload).map(key=>key+'='+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;}
if(limit){payload['limit']=limit;}
if(offset){payload['offset']=offset;}
if(orderType){payload['orderType']=orderType;}
@ -141,7 +138,8 @@ if(read){payload['read']=read;}
if(write){payload['write']=write;}
return http.patch(path,{'content-type':'application/json',},payload);},deleteDocument:function(collectionId,documentId){if(collectionId===undefined){throw new Error('Missing required parameter: "collectionId"');}
if(documentId===undefined){throw new Error('Missing required parameter: "documentId"');}
let path='/database/collections/{collectionId}/documents/{documentId}'.replace(new RegExp('{collectionId}','g'),collectionId).replace(new RegExp('{documentId}','g'),documentId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);}};let locale={get:function(){let path='/locale';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getContinents:function(){let path='/locale/continents';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountries:function(){let path='/locale/countries';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesEU:function(){let path='/locale/countries/eu';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesPhones:function(){let path='/locale/countries/phones';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCurrencies:function(){let path='/locale/currencies';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let projects={list:function(){let path='/projects';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(name,teamId,description='',logo='',url='',legalName='',legalCountry='',legalState='',legalCity='',legalAddress='',legalTaxId=''){if(name===undefined){throw new Error('Missing required parameter: "name"');}
let path='/database/collections/{collectionId}/documents/{documentId}'.replace(new RegExp('{collectionId}','g'),collectionId).replace(new RegExp('{documentId}','g'),documentId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getCollectionLogs:function(collectionId){if(collectionId===undefined){throw new Error('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}/logs'.replace(new RegExp('{collectionId}','g'),collectionId);let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let health={get:function(){let path='/health';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getAntiVirus:function(){let path='/health/anti-virus';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCache:function(){let path='/health/cache';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getDB:function(){let path='/health/db';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueCertificates:function(){let path='/health/queue/certificates';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueFunctions:function(){let path='/health/queue/functions';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueLogs:function(){let path='/health/queue/logs';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueTasks:function(){let path='/health/queue/tasks';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueUsage:function(){let path='/health/queue/usage';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueWebhooks:function(){let path='/health/queue/webhooks';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getStorageLocal:function(){let path='/health/storage/local';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getTime:function(){let path='/health/time';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let locale={get:function(){let path='/locale';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getContinents:function(){let path='/locale/continents';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountries:function(){let path='/locale/countries';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesEU:function(){let path='/locale/countries/eu';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesPhones:function(){let path='/locale/countries/phones';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCurrencies:function(){let path='/locale/currencies';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let projects={list:function(){let path='/projects';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(name,teamId,description='',logo='',url='',legalName='',legalCountry='',legalState='',legalCity='',legalAddress='',legalTaxId=''){if(name===undefined){throw new Error('Missing required parameter: "name"');}
if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/projects';let payload={};if(name){payload['name']=name;}
if(teamId){payload['teamId']=teamId;}
@ -259,7 +257,7 @@ if(httpUser){payload['httpUser']=httpUser;}
if(httpPass){payload['httpPass']=httpPass;}
return http.put(path,{'content-type':'application/json',},payload);},deleteTask:function(projectId,taskId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
if(taskId===undefined){throw new Error('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='monthly'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='last30'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};if(range){payload['range']=range;}
return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/webhooks'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createWebhook:function(projectId,name,events,url,security,httpUser='',httpPass=''){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
@ -327,8 +325,12 @@ let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payloa
if(name===undefined){throw new Error('Missing required parameter: "name"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(name){payload['name']=name;}
return http.put(path,{'content-type':'application/json',},payload);},delete:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getMemberships:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getMemberships:function(teamId,search='',limit=25,offset=0,orderType='ASC'){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(search){payload['search']=search;}
if(limit){payload['limit']=limit;}
if(offset){payload['offset']=offset;}
if(orderType){payload['orderType']=orderType;}
return http.get(path,{'content-type':'application/json',},payload);},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
if(email===undefined){throw new Error('Missing required parameter: "email"');}
if(roles===undefined){throw new Error('Missing required parameter: "roles"');}
if(url===undefined){throw new Error('Missing required parameter: "url"');}
@ -366,7 +368,7 @@ if(sessionId===undefined){throw new Error('Missing required parameter: "sessionI
let path='/users/{userId}/sessions/{sessionId}'.replace(new RegExp('{userId}','g'),userId).replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},updateStatus:function(userId,status){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
if(status===undefined){throw new Error('Missing required parameter: "status"');}
let path='/users/{userId}/status'.replace(new RegExp('{userId}','g'),userId);let payload={};if(status){payload['status']=status;}
return http.patch(path,{'content-type':'application/json',},payload);}};return{setEndpoint:setEndpoint,setProject:setProject,setKey:setKey,setLocale:setLocale,setMode:setMode,account:account,avatars:avatars,database:database,locale:locale,projects:projects,storage:storage,teams:teams,users:users};};if(typeof module!=="undefined"){module.exports=window.Appwrite;}})((typeof window!=="undefined")?window:{});(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart=f()}})(function(){var define,module,exports;return(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){var colorNames=require(5);module.exports={getRgba:getRgba,getHsla:getHsla,getRgb:getRgb,getHsl:getHsl,getHwb:getHwb,getAlpha:getAlpha,hexString:hexString,rgbString:rgbString,rgbaString:rgbaString,percentString:percentString,percentaString:percentaString,hslString:hslString,hslaString:hslaString,hwbString:hwbString,keyword:keyword}
return http.patch(path,{'content-type':'application/json',},payload);}};return{setEndpoint:setEndpoint,setProject:setProject,setKey:setKey,setLocale:setLocale,setMode:setMode,account:account,avatars:avatars,database:database,health:health,locale:locale,projects:projects,storage:storage,teams:teams,users:users};};if(typeof module!=="undefined"){module.exports=window.Appwrite;}})((typeof window!=="undefined")?window:{});(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart=f()}})(function(){var define,module,exports;return(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){var colorNames=require(5);module.exports={getRgba:getRgba,getHsla:getHsla,getRgb:getRgb,getHsl:getHsl,getHwb:getHwb,getAlpha:getAlpha,hexString:hexString,rgbString:rgbString,rgbaString:rgbaString,percentString:percentString,percentaString:percentaString,hslString:hslString,hslaString:hslaString,hwbString:hwbString,keyword:keyword}
function getRgba(string){if(!string){return;}
var abbr=/^#([a-fA-F0-9]{3})$/i,hex=/^#([a-fA-F0-9]{6})$/i,rgba=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,per=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,keyword=/(\w+)/;var rgb=[0,0,0],a=1,match=string.match(abbr);if(match){match=match[1];for(var i=0;i<rgb.length;i++){rgb[i]=parseInt(match[i]+match[i],16);}}
else if(match=string.match(hex)){match=match[1];for(var i=0;i<rgb.length;i++){rgb[i]=parseInt(match.slice(i*2,i*2+2),16);}}
@ -2532,7 +2534,7 @@ return slf.renderToken(tokens,idx,opts);}
md.renderer.rules.strong_open=renderEm;md.renderer.rules.strong_close=renderEm;return md;},true);})(window);(function(window){"use strict";window.ls.container.set('rtl',function(){var rtlStock="^ا^ب^ت^ث^ج^ح^خ^د^ذ^ر^ز^س^ش^ص^ض^ط^ظ^ع^غ^ف^ق^ك^ل^م^ن^ه^و^ي^א^ב^ג^ד^ה^ו^ז^ח^ט^י^כ^ך^ל^מ^ם^נ^ן^ס^ע^פ^ף^צ^ץ^ק^ר^ש^ת^";var special=["\n"," "," ","״",'"',"_","'","!","@","#","$","^","&","%","*","(",")","+","=","-","[","]","\\","/","{","}","|",":","<",">","?",",",".","0","1","2","3","4","5","6","7","8","9"];var isRTL=function(value){for(var i=0;i<value.length;i++){if(/\s/g.test(value[i])){continue;}
if(-1===special.indexOf(value[i])){var firstChar=value[i];break;}}
if(-1<rtlStock.indexOf("^"+firstChar+"^")){return true;}
return false;};return{isRTL:isRTL,};},true);})(window);(function(window){"use strict";window.ls.container.set('sdk',function(window,router){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject(router.params.project||'').setLocale(APP_ENV.LOCALE).setMode('admin');return sdk;},false);})(window);(function(window){"use strict";window.ls.container.set('search',function(window){return{params:{},path:'',pointer:'',selected:'',};},true,true);})(window);(function(window){"use strict";window.ls.container.set('timezone',function(){return{convert:function(unixTime){var timezoneMinutes=new Date().getTimezoneOffset();timezoneMinutes=(timezoneMinutes===0)?0:-timezoneMinutes;return parseInt(unixTime)+(timezoneMinutes*60);}};},true);})(window);window.ls.router.add("/auth/signin",{template:"/auth/signin?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/signup",{template:"/auth/signup?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery",{template:"/auth/recovery?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery/reset",{template:"/auth/recovery/reset?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/confirm",{template:"/auth/confirm?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/join",{template:"/auth/join?version="+APP_ENV.VERSION,scope:"home"}).add("/console",{template:"/console?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account/:tab",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/home",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/home/:tab",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/platforms/:platform",{template:function(window){return window.location.pathname+"?version="+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/notifications",{template:"/console/notifications?version="+APP_ENV.VERSION,scope:"console"}).add("/console/settings",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/settings/:tab",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks/:tab",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys/:tab",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks/:tab",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database",{template:"/console/database?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database/collection",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/collection/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/storage",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/storage/:tab",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/view",{template:"/console/users/view?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/view/:tab",{template:"/console/users/view?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/:tab",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true});window.ls.filter.add("gravatar",function($value,element){if(!$value){return"";}
return false;};return{isRTL:isRTL,};},true);})(window);(function(window){"use strict";window.ls.container.set('sdk',function(window,router){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject(router.params.project||'').setLocale(APP_ENV.LOCALE).setMode('admin');return sdk;},false);})(window);(function(window){"use strict";window.ls.container.set('search',function(window){return{params:{},path:'',pointer:'',selected:'',};},true,true);})(window);(function(window){"use strict";window.ls.container.set('timezone',function(){return{convert:function(unixTime){var timezoneMinutes=new Date().getTimezoneOffset();timezoneMinutes=(timezoneMinutes===0)?0:-timezoneMinutes;return parseInt(unixTime)+(timezoneMinutes*60);}};},true);})(window);window.ls.router.add("/auth/signin",{template:"/auth/signin?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/signup",{template:"/auth/signup?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery",{template:"/auth/recovery?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery/reset",{template:"/auth/recovery/reset?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/confirm",{template:"/auth/confirm?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/join",{template:"/auth/join?version="+APP_ENV.VERSION,scope:"home"}).add("/console",{template:"/console?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account/:tab",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/home",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/home/:tab",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/platforms/:platform",{template:function(window){return window.location.pathname+"?version="+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/notifications",{template:"/console/notifications?version="+APP_ENV.VERSION,scope:"console"}).add("/console/settings",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/settings/:tab",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks/:tab",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys/:tab",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks/:tab",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database",{template:"/console/database?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database/collection",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/collection/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/storage",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/storage/:tab",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/user",{template:"/console/users/user?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/user/:tab",{template:"/console/users/user?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/teams/team",{template:"/console/users/teams/team?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/teams/team/:tab",{template:"/console/users/teams/team?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/:tab",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true});window.ls.filter.add("gravatar",function($value,element){if(!$value){return"";}
let MD5=function(s){function L(k,d){return(k<<d)|(k>>>(32-d));}
function K(G,k){let I,d,F,H,x;F=G&2147483648;H=k&2147483648;I=G&1073741824;d=k&1073741824;x=(G&1073741823)+(k&1073741823);if(I&d){return x^2147483648^F^H;}
if(I|d){if(x&1073741824){return x^3221225472^F^H;}else{return x^1073741824^F^H;}}else{return x^F^H;}}
@ -2567,7 +2569,8 @@ $value=abbreviate($value,0,false,false);return $value==="0"?"N/A":$value;}).add(
return result.length;}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return $value;}).add("platformsLimit",function($value){return $value;}).add("limit",function($value){let postfix=($value.length>=50)?'...':'';return $value.substring(0,50)+postfix;;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
return $value;}).add("platformsLimit",function($value){return $value;}).add("limit",function($value){let postfix=($value.length>=50)?'...':'';return $value.substring(0,50)+postfix;;}).add("arraySentence",function($value){if(!Array.isArray($value)){return'';}
return $value.join(", ").replace(/,\s([^,]+)$/,' and $1');});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
function annotate(number,maxPlaces,forcePlaces,abbr){let rounded=0;switch(abbr){case"T":rounded=number/1e12;break;case"B":rounded=number/1e9;break;case"M":rounded=number/1e6;break;case"K":rounded=number/1e3;break;case"":rounded=number;break;}

View file

@ -18,8 +18,7 @@ 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;}
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);}
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 iframe=function(method,url,params){let form=document.createElement('form');form.setAttribute('method',method);form.setAttribute('action',config.endpoint+url);for(let key in params){if(params.hasOwnProperty(key)){let hiddenField=document.createElement("input");hiddenField.setAttribute("type","hidden");hiddenField.setAttribute("name",key);hiddenField.setAttribute("value",params[key]);form.appendChild(hiddenField);}}
document.body.appendChild(form);return form.submit();};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"');}
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;}
if(password){payload['password']=password;}
@ -52,12 +51,10 @@ 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,failure){if(provider===undefined){throw new Error('Missing required parameter: "provider"');}
if(success===undefined){throw new Error('Missing required parameter: "success"');}
if(failure===undefined){throw new Error('Missing required parameter: "failure"');}
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"');}
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('&');return config.endpoint+path+((query)?'?'+query:'');},deleteSession:function(sessionId){if(sessionId===undefined){throw new Error('Missing required parameter: "sessionId"');}
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"');}
let path='/account/sessions/{sessionId}'.replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},createVerification:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/account/verification';let payload={};if(url){payload['url']=url;}
return http.post(path,{'content-type':'application/json',},payload);},updateVerification:function(userId,secret){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
@ -68,26 +65,26 @@ return http.put(path,{'content-type':'application/json',},payload);}};let avatar
let path='/avatars/browsers/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/credit-cards/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
payload['project']=config.project;payload['key']=config.key;let query=Object.keys(payload).map(key=>key+'='+encodeURIComponent(payload[key])).join('&');return config.endpoint+path+((query)?'?'+query:'');},getFavicon:function(url){if(url===undefined){throw new Error('Missing required parameter: "url"');}
let path='/avatars/favicon';let payload={};if(url){payload['url']=url;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/flags/{code}'.replace(new RegExp('{code}','g'),code);let payload={};if(width){payload['width']=width;}
if(height){payload['height']=height;}
if(quality){payload['quality']=quality;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/image';let payload={};if(url){payload['url']=url;}
if(width){payload['width']=width;}
if(height){payload['height']=height;}
return http.get(path,{'content-type':'application/json',},payload);},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=Object.keys(payload).map(key=>key+'='+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"');}
let path='/avatars/qr';let payload={};if(text){payload['text']=text;}
if(size){payload['size']=size;}
if(margin){payload['margin']=margin;}
if(download){payload['download']=download;}
return http.get(path,{'content-type':'application/json',},payload);}};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=Object.keys(payload).map(key=>key+'='+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;}
if(limit){payload['limit']=limit;}
if(offset){payload['offset']=offset;}
if(orderType){payload['orderType']=orderType;}
@ -141,7 +138,8 @@ if(read){payload['read']=read;}
if(write){payload['write']=write;}
return http.patch(path,{'content-type':'application/json',},payload);},deleteDocument:function(collectionId,documentId){if(collectionId===undefined){throw new Error('Missing required parameter: "collectionId"');}
if(documentId===undefined){throw new Error('Missing required parameter: "documentId"');}
let path='/database/collections/{collectionId}/documents/{documentId}'.replace(new RegExp('{collectionId}','g'),collectionId).replace(new RegExp('{documentId}','g'),documentId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);}};let locale={get:function(){let path='/locale';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getContinents:function(){let path='/locale/continents';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountries:function(){let path='/locale/countries';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesEU:function(){let path='/locale/countries/eu';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesPhones:function(){let path='/locale/countries/phones';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCurrencies:function(){let path='/locale/currencies';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let projects={list:function(){let path='/projects';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(name,teamId,description='',logo='',url='',legalName='',legalCountry='',legalState='',legalCity='',legalAddress='',legalTaxId=''){if(name===undefined){throw new Error('Missing required parameter: "name"');}
let path='/database/collections/{collectionId}/documents/{documentId}'.replace(new RegExp('{collectionId}','g'),collectionId).replace(new RegExp('{documentId}','g'),documentId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getCollectionLogs:function(collectionId){if(collectionId===undefined){throw new Error('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}/logs'.replace(new RegExp('{collectionId}','g'),collectionId);let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let health={get:function(){let path='/health';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getAntiVirus:function(){let path='/health/anti-virus';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCache:function(){let path='/health/cache';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getDB:function(){let path='/health/db';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueCertificates:function(){let path='/health/queue/certificates';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueFunctions:function(){let path='/health/queue/functions';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueLogs:function(){let path='/health/queue/logs';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueTasks:function(){let path='/health/queue/tasks';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueUsage:function(){let path='/health/queue/usage';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getQueueWebhooks:function(){let path='/health/queue/webhooks';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getStorageLocal:function(){let path='/health/storage/local';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getTime:function(){let path='/health/time';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let locale={get:function(){let path='/locale';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getContinents:function(){let path='/locale/continents';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountries:function(){let path='/locale/countries';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesEU:function(){let path='/locale/countries/eu';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCountriesPhones:function(){let path='/locale/countries/phones';let payload={};return http.get(path,{'content-type':'application/json',},payload);},getCurrencies:function(){let path='/locale/currencies';let payload={};return http.get(path,{'content-type':'application/json',},payload);}};let projects={list:function(){let path='/projects';let payload={};return http.get(path,{'content-type':'application/json',},payload);},create:function(name,teamId,description='',logo='',url='',legalName='',legalCountry='',legalState='',legalCity='',legalAddress='',legalTaxId=''){if(name===undefined){throw new Error('Missing required parameter: "name"');}
if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/projects';let payload={};if(name){payload['name']=name;}
if(teamId){payload['teamId']=teamId;}
@ -259,7 +257,7 @@ if(httpUser){payload['httpUser']=httpUser;}
if(httpPass){payload['httpPass']=httpPass;}
return http.put(path,{'content-type':'application/json',},payload);},deleteTask:function(projectId,taskId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
if(taskId===undefined){throw new Error('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='monthly'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace(new RegExp('{projectId}','g'),projectId).replace(new RegExp('{taskId}','g'),taskId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getUsage:function(projectId,range='last30'){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/usage'.replace(new RegExp('{projectId}','g'),projectId);let payload={};if(range){payload['range']=range;}
return http.get(path,{'content-type':'application/json',},payload);},listWebhooks:function(projectId){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/webhooks'.replace(new RegExp('{projectId}','g'),projectId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createWebhook:function(projectId,name,events,url,security,httpUser='',httpPass=''){if(projectId===undefined){throw new Error('Missing required parameter: "projectId"');}
@ -327,8 +325,12 @@ let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payloa
if(name===undefined){throw new Error('Missing required parameter: "name"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(name){payload['name']=name;}
return http.put(path,{'content-type':'application/json',},payload);},delete:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getMemberships:function(teamId){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.get(path,{'content-type':'application/json',},payload);},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace(new RegExp('{teamId}','g'),teamId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},getMemberships:function(teamId,search='',limit=25,offset=0,orderType='ASC'){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
let path='/teams/{teamId}/memberships'.replace(new RegExp('{teamId}','g'),teamId);let payload={};if(search){payload['search']=search;}
if(limit){payload['limit']=limit;}
if(offset){payload['offset']=offset;}
if(orderType){payload['orderType']=orderType;}
return http.get(path,{'content-type':'application/json',},payload);},createMembership:function(teamId,email,roles,url,name=''){if(teamId===undefined){throw new Error('Missing required parameter: "teamId"');}
if(email===undefined){throw new Error('Missing required parameter: "email"');}
if(roles===undefined){throw new Error('Missing required parameter: "roles"');}
if(url===undefined){throw new Error('Missing required parameter: "url"');}
@ -366,7 +368,7 @@ if(sessionId===undefined){throw new Error('Missing required parameter: "sessionI
let path='/users/{userId}/sessions/{sessionId}'.replace(new RegExp('{userId}','g'),userId).replace(new RegExp('{sessionId}','g'),sessionId);let payload={};return http.delete(path,{'content-type':'application/json',},payload);},updateStatus:function(userId,status){if(userId===undefined){throw new Error('Missing required parameter: "userId"');}
if(status===undefined){throw new Error('Missing required parameter: "status"');}
let path='/users/{userId}/status'.replace(new RegExp('{userId}','g'),userId);let payload={};if(status){payload['status']=status;}
return http.patch(path,{'content-type':'application/json',},payload);}};return{setEndpoint:setEndpoint,setProject:setProject,setKey:setKey,setLocale:setLocale,setMode:setMode,account:account,avatars:avatars,database:database,locale:locale,projects:projects,storage:storage,teams:teams,users:users};};if(typeof module!=="undefined"){module.exports=window.Appwrite;}})((typeof window!=="undefined")?window:{});(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart=f()}})(function(){var define,module,exports;return(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){var colorNames=require(5);module.exports={getRgba:getRgba,getHsla:getHsla,getRgb:getRgb,getHsl:getHsl,getHwb:getHwb,getAlpha:getAlpha,hexString:hexString,rgbString:rgbString,rgbaString:rgbaString,percentString:percentString,percentaString:percentaString,hslString:hslString,hslaString:hslaString,hwbString:hwbString,keyword:keyword}
return http.patch(path,{'content-type':'application/json',},payload);}};return{setEndpoint:setEndpoint,setProject:setProject,setKey:setKey,setLocale:setLocale,setMode:setMode,account:account,avatars:avatars,database:database,health:health,locale:locale,projects:projects,storage:storage,teams:teams,users:users};};if(typeof module!=="undefined"){module.exports=window.Appwrite;}})((typeof window!=="undefined")?window:{});(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart=f()}})(function(){var define,module,exports;return(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){var colorNames=require(5);module.exports={getRgba:getRgba,getHsla:getHsla,getRgb:getRgb,getHsl:getHsl,getHwb:getHwb,getAlpha:getAlpha,hexString:hexString,rgbString:rgbString,rgbaString:rgbaString,percentString:percentString,percentaString:percentaString,hslString:hslString,hslaString:hslaString,hwbString:hwbString,keyword:keyword}
function getRgba(string){if(!string){return;}
var abbr=/^#([a-fA-F0-9]{3})$/i,hex=/^#([a-fA-F0-9]{6})$/i,rgba=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,per=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i,keyword=/(\w+)/;var rgb=[0,0,0],a=1,match=string.match(abbr);if(match){match=match[1];for(var i=0;i<rgb.length;i++){rgb[i]=parseInt(match[i]+match[i],16);}}
else if(match=string.match(hex)){match=match[1];for(var i=0;i<rgb.length;i++){rgb[i]=parseInt(match.slice(i*2,i*2+2),16);}}

View file

@ -248,7 +248,7 @@ return slf.renderToken(tokens,idx,opts);}
md.renderer.rules.strong_open=renderEm;md.renderer.rules.strong_close=renderEm;return md;},true);})(window);(function(window){"use strict";window.ls.container.set('rtl',function(){var rtlStock="^ا^ب^ت^ث^ج^ح^خ^د^ذ^ر^ز^س^ش^ص^ض^ط^ظ^ع^غ^ف^ق^ك^ل^م^ن^ه^و^ي^א^ב^ג^ד^ה^ו^ז^ח^ט^י^כ^ך^ל^מ^ם^נ^ן^ס^ע^פ^ף^צ^ץ^ק^ר^ש^ת^";var special=["\n"," "," ","״",'"',"_","'","!","@","#","$","^","&","%","*","(",")","+","=","-","[","]","\\","/","{","}","|",":","<",">","?",",",".","0","1","2","3","4","5","6","7","8","9"];var isRTL=function(value){for(var i=0;i<value.length;i++){if(/\s/g.test(value[i])){continue;}
if(-1===special.indexOf(value[i])){var firstChar=value[i];break;}}
if(-1<rtlStock.indexOf("^"+firstChar+"^")){return true;}
return false;};return{isRTL:isRTL,};},true);})(window);(function(window){"use strict";window.ls.container.set('sdk',function(window,router){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject(router.params.project||'').setLocale(APP_ENV.LOCALE).setMode('admin');return sdk;},false);})(window);(function(window){"use strict";window.ls.container.set('search',function(window){return{params:{},path:'',pointer:'',selected:'',};},true,true);})(window);(function(window){"use strict";window.ls.container.set('timezone',function(){return{convert:function(unixTime){var timezoneMinutes=new Date().getTimezoneOffset();timezoneMinutes=(timezoneMinutes===0)?0:-timezoneMinutes;return parseInt(unixTime)+(timezoneMinutes*60);}};},true);})(window);window.ls.router.add("/auth/signin",{template:"/auth/signin?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/signup",{template:"/auth/signup?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery",{template:"/auth/recovery?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery/reset",{template:"/auth/recovery/reset?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/confirm",{template:"/auth/confirm?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/join",{template:"/auth/join?version="+APP_ENV.VERSION,scope:"home"}).add("/console",{template:"/console?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account/:tab",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/home",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/home/:tab",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/platforms/:platform",{template:function(window){return window.location.pathname+"?version="+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/notifications",{template:"/console/notifications?version="+APP_ENV.VERSION,scope:"console"}).add("/console/settings",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/settings/:tab",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks/:tab",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys/:tab",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks/:tab",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database",{template:"/console/database?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database/collection",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/collection/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/storage",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/storage/:tab",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/view",{template:"/console/users/view?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/view/:tab",{template:"/console/users/view?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/:tab",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true});window.ls.filter.add("gravatar",function($value,element){if(!$value){return"";}
return false;};return{isRTL:isRTL,};},true);})(window);(function(window){"use strict";window.ls.container.set('sdk',function(window,router){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject(router.params.project||'').setLocale(APP_ENV.LOCALE).setMode('admin');return sdk;},false);})(window);(function(window){"use strict";window.ls.container.set('search',function(window){return{params:{},path:'',pointer:'',selected:'',};},true,true);})(window);(function(window){"use strict";window.ls.container.set('timezone',function(){return{convert:function(unixTime){var timezoneMinutes=new Date().getTimezoneOffset();timezoneMinutes=(timezoneMinutes===0)?0:-timezoneMinutes;return parseInt(unixTime)+(timezoneMinutes*60);}};},true);})(window);window.ls.router.add("/auth/signin",{template:"/auth/signin?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/signup",{template:"/auth/signup?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery",{template:"/auth/recovery?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/recovery/reset",{template:"/auth/recovery/reset?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/confirm",{template:"/auth/confirm?version="+APP_ENV.VERSION,scope:"home"}).add("/auth/join",{template:"/auth/join?version="+APP_ENV.VERSION,scope:"home"}).add("/console",{template:"/console?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/account/:tab",{template:"/console/account?version="+APP_ENV.VERSION,scope:"console"}).add("/console/home",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/home/:tab",{template:"/console/home?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/platforms/:platform",{template:function(window){return window.location.pathname+"?version="+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/notifications",{template:"/console/notifications?version="+APP_ENV.VERSION,scope:"console"}).add("/console/settings",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/settings/:tab",{template:"/console/settings?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/webhooks/:tab",{template:"/console/webhooks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/keys/:tab",{template:"/console/keys?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/tasks/:tab",{template:"/console/tasks?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database",{template:"/console/database?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/database/collection",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/collection/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/database/document/:tab",{template:function(window){return window.location.pathname+window.location.search+'&version='+APP_ENV.VERSION;},scope:"console",project:true}).add("/console/storage",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/storage/:tab",{template:"/console/storage?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/user",{template:"/console/users/user?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/user/:tab",{template:"/console/users/user?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/teams/team",{template:"/console/users/teams/team?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/teams/team/:tab",{template:"/console/users/teams/team?version="+APP_ENV.VERSION,scope:"console",project:true}).add("/console/users/:tab",{template:"/console/users?version="+APP_ENV.VERSION,scope:"console",project:true});window.ls.filter.add("gravatar",function($value,element){if(!$value){return"";}
let MD5=function(s){function L(k,d){return(k<<d)|(k>>>(32-d));}
function K(G,k){let I,d,F,H,x;F=G&2147483648;H=k&2147483648;I=G&1073741824;d=k&1073741824;x=(G&1073741823)+(k&1073741823);if(I&d){return x^2147483648^F^H;}
if(I|d){if(x&1073741824){return x^3221225472^F^H;}else{return x^1073741824^F^H;}}else{return x^F^H;}}
@ -283,7 +283,8 @@ $value=abbreviate($value,0,false,false);return $value==="0"?"N/A":$value;}).add(
return result.length;}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return $value;}).add("platformsLimit",function($value){return $value;}).add("limit",function($value){let postfix=($value.length>=50)?'...':'';return $value.substring(0,50)+postfix;;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
return $value;}).add("platformsLimit",function($value){return $value;}).add("limit",function($value){let postfix=($value.length>=50)?'...':'';return $value.substring(0,50)+postfix;;}).add("arraySentence",function($value){if(!Array.isArray($value)){return'';}
return $value.join(", ").replace(/,\s([^,]+)$/,' and $1');});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
function annotate(number,maxPlaces,forcePlaces,abbr){let rounded=0;switch(abbr){case"T":rounded=number/1e12;break;case"B":rounded=number/1e9;break;case"M":rounded=number/1e6;break;case"K":rounded=number/1e3;break;case"":rounded=number;break;}

View file

@ -286,28 +286,6 @@
}
}(window.document);
let iframe = function(method, url, params) {
let form = document.createElement('form');
form.setAttribute('method', method);
form.setAttribute('action', config.endpoint + url);
for(let key in params) {
if(params.hasOwnProperty(key)) {
let hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
return form.submit();
};
let account = {
/**
@ -334,10 +312,10 @@
*
* 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).
*
* @param {string} email
* @param {string} password
@ -580,7 +558,7 @@
* 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.
*
* @param {string} email
@ -621,7 +599,7 @@
* 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)
@ -768,21 +746,13 @@
* @param {string} success
* @param {string} failure
* @throws {Error}
* @return {string}
* @return {Promise}
*/
createOAuth2Session: function(provider, success, failure) {
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"');
}
if(success === undefined) {
throw new Error('Missing required parameter: "success"');
}
if(failure === undefined) {
throw new Error('Missing required parameter: "failure"');
}
let path = '/account/sessions/oauth2/{provider}'.replace(new RegExp('{provider}', 'g'), provider);
let payload = {};
@ -800,8 +770,8 @@
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
window.location = config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -840,7 +810,7 @@
* 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)
@ -926,7 +896,7 @@
* @param {number} height
* @param {number} quality
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getBrowser: function(code, width = 100, height = 100, quality = 100) {
if(code === undefined) {
@ -949,10 +919,13 @@
payload['quality'] = quality;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -968,7 +941,7 @@
* @param {number} height
* @param {number} quality
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getCreditCard: function(code, width = 100, height = 100, quality = 100) {
if(code === undefined) {
@ -991,10 +964,13 @@
payload['quality'] = quality;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -1005,7 +981,7 @@
*
* @param {string} url
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getFavicon: function(url) {
if(url === undefined) {
@ -1020,10 +996,13 @@
payload['url'] = url;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -1038,7 +1017,7 @@
* @param {number} height
* @param {number} quality
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getFlag: function(code, width = 100, height = 100, quality = 100) {
if(code === undefined) {
@ -1061,10 +1040,13 @@
payload['quality'] = quality;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -1079,7 +1061,7 @@
* @param {number} width
* @param {number} height
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getImage: function(url, width = 400, height = 400) {
if(url === undefined) {
@ -1102,10 +1084,13 @@
payload['height'] = height;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
/**
@ -1119,7 +1104,7 @@
* @param {number} margin
* @param {number} download
* @throws {Error}
* @return {Promise}
* @return {string}
*/
getQR: function(text, size = 400, margin = 1, download = 0) {
if(text === undefined) {
@ -1146,10 +1131,13 @@
payload['download'] = download;
}
return http
.get(path, {
'content-type': 'application/json',
}, payload);
payload['project'] = config.project;
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
}
};
@ -1203,9 +1191,9 @@
* Create a new Collection.
*
* @param {string} name
* @param {array} read
* @param {array} write
* @param {array} rules
* @param {string[]} read
* @param {string[]} write
* @param {string[]} rules
* @throws {Error}
* @return {Promise}
*/
@ -1284,9 +1272,9 @@
*
* @param {string} collectionId
* @param {string} name
* @param {array} read
* @param {array} write
* @param {array} rules
* @param {string[]} read
* @param {string[]} write
* @param {string[]} rules
* @throws {Error}
* @return {Promise}
*/
@ -1367,7 +1355,7 @@
* modes](/docs/admin).
*
* @param {string} collectionId
* @param {array} filters
* @param {string[]} filters
* @param {number} offset
* @param {number} limit
* @param {string} orderField
@ -1433,12 +1421,15 @@
/**
* 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.
*
* @param {string} collectionId
* @param {object} data
* @param {array} read
* @param {array} write
* @param {string[]} read
* @param {string[]} write
* @param {string} parentDocument
* @param {string} parentProperty
* @param {string} parentPropertyType
@ -1533,8 +1524,8 @@
* @param {string} collectionId
* @param {string} documentId
* @param {object} data
* @param {array} read
* @param {array} write
* @param {string[]} read
* @param {string[]} write
* @throws {Error}
* @return {Promise}
*/
@ -1610,6 +1601,272 @@
.delete(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Collection Logs
*
*
* @param {string} collectionId
* @throws {Error}
* @return {Promise}
*/
getCollectionLogs: function(collectionId) {
if(collectionId === undefined) {
throw new Error('Missing required parameter: "collectionId"');
}
let path = '/database/collections/{collectionId}/logs'.replace(new RegExp('{collectionId}', 'g'), collectionId);
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
}
};
let health = {
/**
* Get HTTP
*
* Check the Appwrite HTTP server is up and responsive.
*
* @throws {Error}
* @return {Promise}
*/
get: function() {
let path = '/health';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Anti virus
*
* Check the Appwrite Anti Virus server is up and connection is successful.
*
* @throws {Error}
* @return {Promise}
*/
getAntiVirus: function() {
let path = '/health/anti-virus';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Cache
*
* Check the Appwrite in-memory cache server is up and connection is
* successful.
*
* @throws {Error}
* @return {Promise}
*/
getCache: function() {
let path = '/health/cache';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get DB
*
* Check the Appwrite database server is up and connection is successful.
*
* @throws {Error}
* @return {Promise}
*/
getDB: function() {
let path = '/health/db';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Certificate Queue
*
* Get the number of certificates that are waiting to be issued against
* [Letsencrypt](https://letsencrypt.org/) in the Appwrite internal queue
* server.
*
* @throws {Error}
* @return {Promise}
*/
getQueueCertificates: function() {
let path = '/health/queue/certificates';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Functions Queue
*
*
* @throws {Error}
* @return {Promise}
*/
getQueueFunctions: function() {
let path = '/health/queue/functions';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Logs Queue
*
* Get the number of logs that are waiting to be processed in the Appwrite
* internal queue server.
*
* @throws {Error}
* @return {Promise}
*/
getQueueLogs: function() {
let path = '/health/queue/logs';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Tasks Queue
*
* Get the number of tasks that are waiting to be processed in the Appwrite
* internal queue server.
*
* @throws {Error}
* @return {Promise}
*/
getQueueTasks: function() {
let path = '/health/queue/tasks';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Usage Queue
*
* Get the number of usage stats that are waiting to be processed in the
* Appwrite internal queue server.
*
* @throws {Error}
* @return {Promise}
*/
getQueueUsage: function() {
let path = '/health/queue/usage';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Webhooks Queue
*
* Get the number of webhooks that are waiting to be processed in the Appwrite
* internal queue server.
*
* @throws {Error}
* @return {Promise}
*/
getQueueWebhooks: function() {
let path = '/health/queue/webhooks';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Local Storage
*
* Check the Appwrite local storage device is up and connection is successful.
*
* @throws {Error}
* @return {Promise}
*/
getStorageLocal: function() {
let path = '/health/storage/local';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
},
/**
* Get Time
*
* Check the Appwrite server time is synced with Google remote NTP server. We
* use this technology to smoothly handle leap seconds with no disruptive
* events. The [Network Time
* Protocol](https://en.wikipedia.org/wiki/Network_Time_Protocol) (NTP) is
* used by hundreds of millions of computers and devices to synchronize their
* clocks over the Internet. If your computer sets its own clock, it likely
* uses NTP.
*
* @throws {Error}
* @return {Promise}
*/
getTime: function() {
let path = '/health/time';
let payload = {};
return http
.get(path, {
'content-type': 'application/json',
}, payload);
}
};
@ -1640,7 +1897,7 @@
},
/**
* List Countries
* List Continents
*
* List of all continents. You can use the locale header to get the data in a
* supported language.
@ -2142,7 +2399,7 @@
*
* @param {string} projectId
* @param {string} name
* @param {array} scopes
* @param {string[]} scopes
* @throws {Error}
* @return {Promise}
*/
@ -2212,7 +2469,7 @@
* @param {string} projectId
* @param {string} keyId
* @param {string} name
* @param {array} scopes
* @param {string[]} scopes
* @throws {Error}
* @return {Promise}
*/
@ -2542,7 +2799,7 @@
* @param {number} security
* @param {string} httpMethod
* @param {string} httpUrl
* @param {array} httpHeaders
* @param {string[]} httpHeaders
* @param {string} httpUser
* @param {string} httpPass
* @throws {Error}
@ -2663,7 +2920,7 @@
* @param {number} security
* @param {string} httpMethod
* @param {string} httpUrl
* @param {array} httpHeaders
* @param {string[]} httpHeaders
* @param {string} httpUser
* @param {string} httpPass
* @throws {Error}
@ -2781,10 +3038,11 @@
*
*
* @param {string} projectId
* @param {string} range
* @throws {Error}
* @return {Promise}
*/
getUsage: function(projectId, range = 'monthly') {
getUsage: function(projectId, range = 'last30') {
if(projectId === undefined) {
throw new Error('Missing required parameter: "projectId"');
}
@ -2832,7 +3090,7 @@
*
* @param {string} projectId
* @param {string} name
* @param {array} events
* @param {string[]} events
* @param {string} url
* @param {number} security
* @param {string} httpUser
@ -2930,7 +3188,7 @@
* @param {string} projectId
* @param {string} webhookId
* @param {string} name
* @param {array} events
* @param {string[]} events
* @param {string} url
* @param {number} security
* @param {string} httpUser
@ -3077,8 +3335,8 @@
* read and write arguments.
*
* @param {File} file
* @param {array} read
* @param {array} write
* @param {string[]} read
* @param {string[]} write
* @throws {Error}
* @return {Promise}
*/
@ -3149,8 +3407,8 @@
* to update this resource.
*
* @param {string} fileId
* @param {array} read
* @param {array} write
* @param {string[]} read
* @param {string[]} write
* @throws {Error}
* @return {Promise}
*/
@ -3235,7 +3493,7 @@
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
@ -3290,7 +3548,7 @@
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
},
@ -3323,7 +3581,7 @@
payload['key'] = config.key;
let query = Object.keys(payload).map(key => key + '=' + encodeURIComponent(payload[key])).join('&');
return config.endpoint + path + ((query) ? '?' + query : '');
}
};
@ -3380,7 +3638,7 @@
* project.
*
* @param {string} name
* @param {array} roles
* @param {string[]} roles
* @throws {Error}
* @return {Promise}
*/
@ -3498,10 +3756,14 @@
* for this list of resources.
*
* @param {string} teamId
* @param {string} search
* @param {number} limit
* @param {number} offset
* @param {string} orderType
* @throws {Error}
* @return {Promise}
*/
getMemberships: function(teamId) {
getMemberships: function(teamId, search = '', limit = 25, offset = 0, orderType = 'ASC') {
if(teamId === undefined) {
throw new Error('Missing required parameter: "teamId"');
}
@ -3510,6 +3772,22 @@
let payload = {};
if(search) {
payload['search'] = search;
}
if(limit) {
payload['limit'] = limit;
}
if(offset) {
payload['offset'] = offset;
}
if(orderType) {
payload['orderType'] = orderType;
}
return http
.get(path, {
'content-type': 'application/json',
@ -3525,8 +3803,8 @@
*
* 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)
@ -3535,7 +3813,7 @@
*
* @param {string} teamId
* @param {string} email
* @param {array} roles
* @param {string[]} roles
* @param {string} url
* @param {string} name
* @throws {Error}
@ -3922,10 +4200,7 @@
throw new Error('Missing required parameter: "sessionId"');
}
let path = '/users/{userId}/sessions/{sessionId}'
.replace(new RegExp('{userId}', 'g'), userId)
.replace(new RegExp('{sessionId}', 'g'), sessionId)
;
let path = '/users/{userId}/sessions/{sessionId}'.replace(new RegExp('{userId}', 'g'), userId).replace(new RegExp('{sessionId}', 'g'), sessionId);
let payload = {};
@ -3978,6 +4253,7 @@
account: account,
avatars: avatars,
database: database,
health: health,
locale: locale,
projects: projects,
storage: storage,

View file

@ -415,6 +415,13 @@ window.ls.filter
return $value.substring(0, 50) + postfix;
;
})
.add("arraySentence", function($value) {
if(!Array.isArray($value)) {
return '';
}
return $value.join(", ").replace(/,\s([^,]+)$/, ' and $1');
})
;
function abbreviate(number, maxPlaces, forcePlaces, forceLetter) {

View file

@ -144,13 +144,23 @@ window.ls.router
scope: "console",
project: true
})
.add("/console/users/view", {
template: "/console/users/view?version=" + APP_ENV.VERSION,
.add("/console/users/user", {
template: "/console/users/user?version=" + APP_ENV.VERSION,
scope: "console",
project: true
})
.add("/console/users/view/:tab", {
template: "/console/users/view?version=" + APP_ENV.VERSION,
.add("/console/users/user/:tab", {
template: "/console/users/user?version=" + APP_ENV.VERSION,
scope: "console",
project: true
})
.add("/console/users/teams/team", {
template: "/console/users/teams/team?version=" + APP_ENV.VERSION,
scope: "console",
project: true
})
.add("/console/users/teams/team/:tab", {
template: "/console/users/teams/team?version=" + APP_ENV.VERSION,
scope: "console",
project: true
})

View file

@ -22,10 +22,11 @@ trait TeamsBaseClient
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body'][0]['$id']);
$this->assertEquals($this->getUser()['name'], $response['body'][0]['name']);
$this->assertEquals($this->getUser()['email'], $response['body'][0]['email']);
$this->assertEquals('owner', $response['body'][0]['roles'][0]);
$this->assertIsInt($response['body']['sum']);
$this->assertNotEmpty($response['body']['memberships'][0]['$id']);
$this->assertEquals($this->getUser()['name'], $response['body']['memberships'][0]['name']);
$this->assertEquals($this->getUser()['email'], $response['body']['memberships'][0]['email']);
$this->assertEquals('owner', $response['body']['memberships'][0]['roles'][0]);
/**
* Test for FAILURE
@ -231,7 +232,7 @@ trait TeamsBaseClient
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertCount(1, $response['body']);
$this->assertCount(1, $response['body']['memberships']);
return [];
}

View file

@ -22,7 +22,7 @@ trait TeamsBaseServer
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertCount(0, $response['body']);
$this->assertEquals(0, $response['body']['sum']);
/**
* Test for FAILURE