1
0
Fork 0
mirror of synced 2024-06-02 19:04:49 +12:00

Merge branch 'feat-database-indexing' of https://github.com/appwrite/appwrite into feat-database-after-pagination

This commit is contained in:
Torsten Dittmann 2021-08-09 12:03:15 +02:00
commit 8296021b63
73 changed files with 1914 additions and 1147 deletions

View file

@ -1,3 +1,11 @@
# Version 0.10.0
## Features
- Grouped auth related attributes in project collection. Introduced new attribute `auths` and removed all attributes related to auth methods and `usersAuthLimit` as well, all these are grouped under `auths` attribute
- Grouped oAuth related attributes in project collection. Introduced new attribute `providers` and removed all attributes related to OAuth2 providers. All OAuth2 attributes are grouped under `providers`
- Project model changed, `userAuth<AuthMethod>` => `auth<AuthMethod>` example `userAuthEmailPassword` => `authEmailPassword`, also `userOauth2<Provider>...` => `provider<Provider>...` example `userOauth2GithubAppid` => `providerGithubAppid`
# Version 0.9.3
## Bugs

View file

@ -238,7 +238,6 @@ RUN chmod +x /usr/local/bin/doctor && \
chmod +x /usr/local/bin/worker-deletes && \
chmod +x /usr/local/bin/worker-functions && \
chmod +x /usr/local/bin/worker-mails && \
chmod +x /usr/local/bin/worker-usage && \
chmod +x /usr/local/bin/worker-webhooks
# Letsencrypt Permissions

View file

@ -5,35 +5,35 @@
return [
'email-password' => [
'name' => 'Email/Password',
'key' => 'usersAuthEmailPassword',
'key' => 'emailPassword',
'icon' => '/images/users/email.png',
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateSession',
'enabled' => true,
],
'anonymous' => [
'name' => 'Anonymous',
'key' => 'usersAuthAnonymous',
'key' => 'anonymous',
'icon' => '/images/users/anonymous.png',
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateAnonymousSession',
'enabled' => true,
],
'invites' => [
'name' => 'Invites',
'key' => 'usersAuthInvites',
'key' => 'invites',
'icon' => '/images/users/invites.png',
'docs' => 'https://appwrite.io/docs/client/teams?sdk=web#teamsCreateMembership',
'enabled' => true,
],
'jwt' => [
'name' => 'JWT',
'key' => 'usersAuthJWT',
'key' => 'JWT',
'icon' => '/images/users/jwt.png',
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateJWT',
'enabled' => true,
],
'phone' => [
'name' => 'Phone',
'key' => 'usersAuthPhone',
'key' => 'phone',
'icon' => '/images/users/phone.png',
'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreatePhoneSession',
'docs' => '',

View file

@ -78,17 +78,6 @@ $collections = [
'array' => false,
'filters' => [],
],
[
'$id' => 'usersAuthLimit',
'type' => Database::VAR_INTEGER,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'legalName',
'type' => Database::VAR_STRING,
@ -166,6 +155,28 @@ $collections = [
'array' => false,
'filters' => ['json'],
],
[
'$id' => 'auths',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['json'],
],
[
'$id' => 'providers',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['json'],
],
[
'$id' => 'platforms',
'type' => Database::VAR_STRING,
@ -972,6 +983,17 @@ $collections = [
'array' => true,
'filters' => [],
],
[
'$id' => 'name',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'dateCreated',
'type' => Database::VAR_INTEGER,
@ -1006,17 +1028,6 @@ $collections = [
'array' => false,
'filters' => [],
],
[
'$id' => 'name',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 2048,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
],
[
'$id' => 'runtime',
'type' => Database::VAR_STRING,
@ -1394,51 +1405,4 @@ $collections = [
],
];
/*
* Add enabled OAuth2 providers to default data rules
*/
foreach ($providers as $index => $provider) {
if (!$provider['enabled']) {
continue;
}
$collections['projects']['attributes'][] = [
'$id' => 'usersOauth2' . \ucfirst($index) . 'Appid',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
];
$collections['projects']['attributes'][] = [
'$id' => 'usersOauth2' . \ucfirst($index) . 'Secret',
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
];
}
foreach ($auth as $index => $method) {
$collections['projects']['attributes'][] = [
'$id' => $method['key'] ?? '',
'type' => Database::VAR_BOOLEAN,
'format' => '',
'size' => 0,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => [],
];
}
return $collections;

File diff suppressed because one or more lines are too long

View file

@ -3,30 +3,31 @@
use Ahc\Jwt\JWT;
use Appwrite\Auth\Auth;
use Appwrite\Auth\Validator\Password;
use Appwrite\Database\Validator\CustomId;
use Appwrite\Detector\Detector;
use Appwrite\Template\Template;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\URL\URL as URLParser;
use Appwrite\Utopia\Response;
use Appwrite\Network\Validator\Email;
use Appwrite\Network\Validator\Host;
use Appwrite\Network\Validator\URL;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Template\Template;
use Appwrite\URL\URL as URLParser;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Exception;
use Utopia\Config\Config;
use Utopia\Validator\Assoc;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
use Utopia\Validator\ArrayList;
use Utopia\Audit\Audit;
use Utopia\Config\Config;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\UID;
use Utopia\Exception;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Assoc;
use Utopia\Validator\Text;
use Utopia\Validator\WhiteList;
$oauthDefaultSuccess = App::getEnv('_APP_HOME').'/auth/oauth2/success';
$oauthDefaultFailure = App::getEnv('_APP_HOME').'/auth/oauth2/failure';
$oauthDefaultSuccess = App::getEnv('_APP_HOME') . '/auth/oauth2/success';
$oauthDefaultFailure = App::getEnv('_APP_HOME') . '/auth/oauth2/failure';
App::post('/v1/account')
->desc('Create Account')
@ -42,6 +43,7 @@ App::post('/v1/account')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->label('abuse-limit', 10)
->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('email', '', new Email(), 'User email.')
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
@ -50,7 +52,7 @@ App::post('/v1/account')
->inject('project')
->inject('dbForInternal')
->inject('audits')
->action(function ($email, $password, $name, $request, $response, $project, $dbForInternal, $audits) {
->action(function ($userId, $email, $password, $name, $request, $response, $project, $dbForInternal, $audits) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
@ -71,12 +73,12 @@ App::post('/v1/account')
}
}
$limit = $project->getAttribute('usersAuthLimit', 0);
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [], APP_LIMIT_USERS);
if($sum >= $limit) {
if ($sum >= $limit) {
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
}
}
@ -84,11 +86,11 @@ App::post('/v1/account')
Authorization::disable();
try {
$userId = $dbForInternal->getId();
$userId = $userId == 'unique()' ? $dbForInternal->getId() : $userId;
$user = $dbForInternal->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:'.$userId],
'$write' => ['user:' . $userId],
'email' => $email,
'emailVerification' => false,
'status' => true,
@ -108,14 +110,14 @@ App::post('/v1/account')
Authorization::reset();
Authorization::unsetRole('role:'.Auth::USER_ROLE_GUEST);
Authorization::setRole('user:'.$user->getId());
Authorization::setRole('role:'.Auth::USER_ROLE_MEMBER);
Authorization::unsetRole('role:' . Auth::USER_ROLE_GUEST);
Authorization::setRole('user:' . $user->getId());
Authorization::setRole('role:' . Auth::USER_ROLE_MEMBER);
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.create')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -155,13 +157,13 @@ App::post('/v1/account/sessions')
$email = \strtolower($email);
$protocol = $request->getProtocol();
$profile = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if (!$profile || !Auth::passwordVerify($password, $profile->getAttribute('password'))) {
$audits
//->setParam('userId', $profile->getId())
->setParam('event', 'account.sesssions.failed')
->setParam('event', 'account.sessions.failed')
->setParam('resource', 'users/'.($profile ? $profile->getId() : ''))
;
@ -190,11 +192,11 @@ App::post('/v1/account/sessions')
], $detector->getOS(), $detector->getClient(), $detector->getDevice()
));
Authorization::setRole('user:'.$profile->getId());
Authorization::setRole('user:' . $profile->getId());
$session = $dbForInternal->createDocument('sessions', $session
->setAttribute('$read', ['user:'.$profile->getId()])
->setAttribute('$write', ['user:'.$profile->getId()])
->setAttribute('$read', ['user:' . $profile->getId()])
->setAttribute('$write', ['user:' . $profile->getId()])
);
$profile->setAttribute('sessions', $session, Document::SET_TYPE_APPEND);
@ -203,7 +205,7 @@ App::post('/v1/account/sessions')
$audits
->setParam('userId', $profile->getId())
->setParam('event', 'account.sessions.create')
->setParam('resource', 'users/'.$profile->getId())
->setParam('resource', 'users/' . $profile->getId())
;
if (!Config::getParam('domainVerification')) {
@ -211,9 +213,9 @@ App::post('/v1/account/sessions')
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($profile->getId(), $secret)]))
;
}
$response
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
->setStatusCode(Response::STATUS_CODE_CREATED)
;
@ -224,14 +226,14 @@ App::post('/v1/account/sessions')
->setAttribute('current', true)
->setAttribute('countryName', $countryName)
;
$response->dynamic($session, Response::MODEL_SESSION);
});
App::get('/v1/account/sessions/oauth2/:provider')
->desc('Create Account Session with OAuth2')
->groups(['api', 'account'])
->label('error', __DIR__.'/../../views/general/error.phtml')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('scope', 'public')
->label('sdk.auth', [])
->label('sdk.namespace', 'account')
@ -242,9 +244,9 @@ App::get('/v1/account/sessions/oauth2/:provider')
->label('sdk.methodType', 'webAuth')
->label('abuse-limit', 50)
->label('abuse-key', 'ip:{ip}')
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('providers'), function($node) {return (!$node['mock']);}))).'.')
->param('success', $oauthDefaultSuccess, function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('failure', $oauthDefaultFailure, function ($clients) { return new Host($clients); }, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 Provider. Currently, supported providers are: ' . \implode(', ', \array_keys(\array_filter(Config::getParam('providers'), function ($node) {return (!$node['mock']);}))) . '.')
->param('success', $oauthDefaultSuccess, function ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('failure', $oauthDefaultFailure, function ($clients) {return new Host($clients);}, 'URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients'])
->param('scopes', [], new ArrayList(new Text(128)), 'A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes.', true)
->inject('request')
->inject('response')
@ -256,25 +258,25 @@ App::get('/v1/account/sessions/oauth2/:provider')
$protocol = $request->getProtocol();
$callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId();
$appId = $project->getAttribute('usersOauth2'.\ucfirst($provider).'Appid', '');
$appSecret = $project->getAttribute('usersOauth2'.\ucfirst($provider).'Secret', '{}');
$appId = $project->getAttribute('providers', [])[$provider.'Appid'] ?? '';
$appSecret = $project->getAttribute('providers', [])[$provider.'Secret'] ?? '{}';
if (!empty($appSecret) && isset($appSecret['version'])) {
$key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']);
$key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']);
$appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag']));
}
if (empty($appId) || empty($appSecret)) {
throw new Exception('This provider is disabled. Please configure the provider app ID and app secret key from your '.APP_NAME.' console to continue.', 412);
throw new Exception('This provider is disabled. Please configure the provider app ID and app secret key from your ' . APP_NAME . ' console to continue.', 412);
}
$classname = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider);
$className = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider);
if (!\class_exists($classname)) {
if (!\class_exists($className)) {
throw new Exception('Provider is not supported', 501);
}
$oauth2 = new $classname($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure], $scopes);
$oauth2 = new $className($appId, $appSecret, $callback, ['success' => $success, 'failure' => $failure], $scopes);
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
@ -285,7 +287,7 @@ App::get('/v1/account/sessions/oauth2/:provider')
App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 Callback')
->groups(['api', 'account'])
->label('error', __DIR__.'/../../views/general/error.phtml')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('scope', 'public')
->label('docs', false)
->param('projectId', '', new Text(1024), 'Project unique ID.')
@ -300,18 +302,18 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
$domain = $request->getHostname();
$protocol = $request->getProtocol();
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.\http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?'
. \http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
});
App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 Callback')
->groups(['api', 'account'])
->label('error', __DIR__.'/../../views/general/error.phtml')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('scope', 'public')
->label('origin', '*')
->label('docs', false)
@ -327,18 +329,18 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
$domain = $request->getHostname();
$protocol = $request->getProtocol();
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->redirect($protocol.'://'.$domain.'/v1/account/sessions/oauth2/'.$provider.'/redirect?'
.\http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?'
. \http_build_query(['project' => $projectId, 'code' => $code, 'state' => $state]));
});
App::get('/v1/account/sessions/oauth2/:provider/redirect')
->desc('OAuth2 Redirect')
->groups(['api', 'account'])
->label('error', __DIR__.'/../../views/general/error.phtml')
->label('error', __DIR__ . '/../../views/general/error.phtml')
->label('event', 'account.sessions.create')
->label('scope', 'public')
->label('abuse-limit', 50)
@ -363,32 +365,31 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
/** @var Utopia\Database\Database $dbForInternal */
/** @var MaxMind\Db\Reader $geodb */
/** @var Appwrite\Event\Event $audits */
$protocol = $request->getProtocol();
$callback = $protocol.'://'.$request->getHostname().'/v1/account/sessions/oauth2/callback/'.$provider.'/'.$project->getId();
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
$validateURL = new URL();
$appId = $project->getAttribute('usersOauth2'.\ucfirst($provider).'Appid', '');
$appSecret = $project->getAttribute('usersOauth2'.\ucfirst($provider).'Secret', '{}');
$appId = $project->getAttribute('providers', [])[$provider.'Appid'] ?? '';
$appSecret = $project->getAttribute('providers', [])[$provider.'Secret'] ?? '{}';
if (!empty($appSecret) && isset($appSecret['version'])) {
$key = App::getEnv('_APP_OPENSSL_KEY_V'.$appSecret['version']);
$key = App::getEnv('_APP_OPENSSL_KEY_V' . $appSecret['version']);
$appSecret = OpenSSL::decrypt($appSecret['data'], $appSecret['method'], $key, 0, \hex2bin($appSecret['iv']), \hex2bin($appSecret['tag']));
}
$classname = 'Appwrite\\Auth\\OAuth2\\'.\ucfirst($provider);
$className = 'Appwrite\\Auth\\OAuth2\\' . \ucfirst($provider);
if (!\class_exists($classname)) {
if (!\class_exists($className)) {
throw new Exception('Provider is not supported', 501);
}
$oauth2 = new $classname($appId, $appSecret, $callback);
$oauth2 = new $className($appId, $appSecret, $callback);
if (!empty($state)) {
try {
$state = \array_merge($defaultState, $oauth2->parseState($state));
} catch (\Exception $exception) {
} catch (\Exception$exception) {
throw new Exception('Failed to parse login state params as passed from OAuth2 provider');
}
} else {
@ -402,7 +403,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
if (!empty($state['failure']) && !$validateURL->isValid($state['failure'])) {
throw new Exception('Invalid redirect URL for failure login', 400);
}
$state['failure'] = null;
$accessToken = $oauth2->getAccessToken($code);
@ -415,7 +416,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
}
$oauth2ID = $oauth2->getUserID($accessToken);
if (empty($oauth2ID)) {
if (!empty($state['failure'])) {
$response->redirect($state['failure'], 301, 0);
@ -427,11 +428,11 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$sessions = $user->getAttribute('sessions', []);
$current = Auth::sessionVerify($sessions, Auth::$secret);
if($current) { // Delete current session of new one.
foreach ($sessions as $key => $session) { /** @var Document $session */
if ($current) { // Delete current session of new one.
foreach ($sessions as $key => $session) {/** @var Document $session */
if ($current === $session['$id']) {
unset($sessions[$key]);
$dbForInternal->deleteDocument('sessions', $session->getId());
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', $sessions));
}
@ -450,16 +451,16 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$user = $dbForInternal->findOne('users', [new Query('email', Query::TYPE_EQUAL, [$email])]); // Get user by email address
if ($user === false || $user->isEmpty()) { // Last option -> create the user, generate random password
$limit = $project->getAttribute('usersAuthLimit', 0);
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [], APP_LIMIT_COUNT);
if($sum >= $limit) {
if ($sum >= $limit) {
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
}
}
Authorization::disable();
try {
@ -467,7 +468,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$user = $dbForInternal->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:'.$userId],
'$write' => ['user:' . $userId],
'email' => $email,
'emailVerification' => true,
'status' => true, // Email should already be authenticated by OAuth2 provider
@ -526,11 +527,11 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->setAttribute('sessions', $session, Document::SET_TYPE_APPEND)
;
Authorization::setRole('user:'.$user->getId());
Authorization::setRole('user:' . $user->getId());
$session = $dbForInternal->createDocument('sessions', $session
->setAttribute('$read', ['user:'.$user->getId()])
->setAttribute('$write', ['user:'.$user->getId()])
->setAttribute('$read', ['user:' . $user->getId()])
->setAttribute('$write', ['user:' . $user->getId()])
);
$user = $dbForInternal->updateDocument('users', $user->getId(), $user);
@ -538,7 +539,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.sessions.create')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
->setParam('data', ['provider' => $provider])
;
@ -549,7 +550,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]))
;
}
// Add keys for non-web platforms - TODO - add verification phase to aviod session sniffing
if (parse_url($state['success'], PHP_URL_PATH) === parse_url($oauthDefaultSuccess, PHP_URL_PATH)) {
$state['success'] = URLParser::parse($state['success']);
@ -565,7 +566,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
$response
->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->addHeader('Pragma', 'no-cache')
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
->redirect($state['success'])
;
@ -614,12 +615,12 @@ App::post('/v1/account/sessions/anonymous')
throw new Exception('Cannot create an anonymous user when logged in.', 401);
}
$limit = $project->getAttribute('usersAuthLimit', 0);
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0) {
$sum = $dbForInternal->count('users', [], APP_LIMIT_COUNT);
if($sum >= $limit) {
if ($sum >= $limit) {
throw new Exception('Project registration is restricted. Contact your administrator for more information.', 501);
}
}
@ -629,8 +630,8 @@ App::post('/v1/account/sessions/anonymous')
$userId = $dbForInternal->getId();
$user = $dbForInternal->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],
'$write' => ['user:'.$userId],
'$read' => ['role:all'],
'$write' => ['user:' . $userId],
'email' => null,
'emailVerification' => false,
'status' => true,
@ -669,11 +670,11 @@ App::post('/v1/account/sessions/anonymous')
$detector->getDevice()
));
Authorization::setRole('user:'.$user->getId());
Authorization::setRole('user:' . $user->getId());
$session = $dbForInternal->createDocument('sessions', $session
->setAttribute('$read', ['user:'.$user->getId()])
->setAttribute('$write', ['user:'.$user->getId()])
->setAttribute('$read', ['user:' . $user->getId()])
->setAttribute('$write', ['user:' . $user->getId()])
);
$user = $dbForInternal->updateDocument('users', $user->getId(),
@ -682,7 +683,7 @@ App::post('/v1/account/sessions/anonymous')
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.sessions.create')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
if (!Config::getParam('domainVerification')) {
@ -692,7 +693,7 @@ App::post('/v1/account/sessions/anonymous')
}
$response
->addCookie(Auth::$cookieName.'_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
->setStatusCode(Response::STATUS_CODE_CREATED)
;
@ -728,11 +729,11 @@ App::post('/v1/account/jwt')
->action(function ($response, $user) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
$sessions = $user->getAttribute('sessions', []);
$current = new Document();
foreach ($sessions as $session) {
foreach ($sessions as $session) {
/** @var Utopia\Database\Document $session */
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
@ -740,10 +741,10 @@ App::post('/v1/account/jwt')
}
}
if($current->isEmpty()) {
if ($current->isEmpty()) {
throw new Exception('No valid session found', 401);
}
$jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -821,7 +822,7 @@ App::get('/v1/account/sessions')
$sessions = $user->getAttribute('sessions', []);
$current = Auth::sessionVerify($sessions, Auth::$secret);
foreach ($sessions as $key => $session) { /** @var Document $session */
foreach ($sessions as $key => $session) {/** @var Document $session */
$countryName = $locale->getText('countries.'.strtolower($session->getAttribute('countryCode')), $locale->getText('locale.country.unknown'));
$session->setAttribute('countryName', $countryName);
@ -930,23 +931,23 @@ App::get('/v1/account/sessions/:sessionId')
/** @var Utopia\Locale\Locale $locale */
/** @var Utopia\Database\Database $dbForInternal */
$sessions = $user->getAttribute('sessions', []);
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
$sessions = $user->getAttribute('sessions', []);
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
foreach ($sessions as $session) { /** @var Document $session */
foreach ($sessions as $session) {/** @var Document $session */
if ($sessionId == $session->getId()) {
$countryName = (isset($countries[strtoupper($session->getAttribute('countryCode'))]))
? $countries[strtoupper($session->getAttribute('countryCode'))]
: $locale->getText('locale.country.unknown');
? $countries[strtoupper($session->getAttribute('countryCode'))]
: $locale->getText('locale.country.unknown');
$session
->setAttribute('current', ($session->getAttribute('secret') == Auth::hash(Auth::$secret)))
->setAttribute('countryName', $countryName)
;
return $response->dynamic($session, Response::MODEL_SESSION);
}
}
@ -982,7 +983,7 @@ App::patch('/v1/account/name')
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.update.name')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->dynamic($user, Response::MODEL_USER);
@ -1018,14 +1019,14 @@ App::patch('/v1/account/password')
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
);
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.update.password')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->dynamic($user, Response::MODEL_USER);
@ -1072,15 +1073,15 @@ App::patch('/v1/account/email')
}
$user = $dbForInternal->updateDocument('users', $user->getId(), $user
->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', ''))
->setAttribute('email', $email)
->setAttribute('emailVerification', false) // After this user needs to confirm mail again
->setAttribute('password', $isAnonymousUser ? Auth::passwordHash($password) : $user->getAttribute('password', ''))
->setAttribute('email', $email)
->setAttribute('emailVerification', false) // After this user needs to confirm mail again
);
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.update.email')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->dynamic($user, Response::MODEL_USER);
@ -1113,7 +1114,7 @@ App::patch('/v1/account/prefs')
$audits
->setParam('event', 'account.update.prefs')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->dynamic($user, Response::MODEL_USER);
@ -1150,15 +1151,15 @@ App::delete('/v1/account')
// TODO delete all tokens or only current session?
// TODO delete all user data according to GDPR. Make sure everything is backed up and backups are deleted later
/*
* Data to delete
* * Tokens
* * Memberships
*/
* Data to delete
* * Tokens
* * Memberships
*/
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.delete')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
->setParam('data', $user->getArrayCopy())
;
@ -1173,7 +1174,7 @@ App::delete('/v1/account')
}
$response
->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
->noContent()
;
@ -1210,12 +1211,12 @@ App::delete('/v1/account/sessions/:sessionId')
$protocol = $request->getProtocol();
$sessionId = ($sessionId === 'current')
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
? Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret)
: $sessionId;
$sessions = $user->getAttribute('sessions', []);
foreach ($sessions as $key => $session) { /** @var Document $session */
foreach ($sessions as $key => $session) {/** @var Document $session */
if ($sessionId == $session->getId()) {
unset($sessions[$key]);
@ -1224,17 +1225,17 @@ App::delete('/v1/account/sessions/:sessionId')
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.sessions.delete')
->setParam('resource', '/user/'.$user->getId())
->setParam('resource', '/user/' . $user->getId())
;
$session->setAttribute('current', false);
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
$session
->setAttribute('current', true)
->setAttribute('countryName', (isset($countries[strtoupper($session->getAttribute('countryCode'))])) ? $countries[strtoupper($session->getAttribute('countryCode'))] : $locale->getText('locale.country.unknown'))
;
if (!Config::getParam('domainVerification')) {
$response
->addHeader('X-Fallback-Cookies', \json_encode([]))
@ -1242,7 +1243,7 @@ App::delete('/v1/account/sessions/:sessionId')
}
$response
->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
;
}
@ -1291,13 +1292,13 @@ App::delete('/v1/account/sessions')
$protocol = $request->getProtocol();
$sessions = $user->getAttribute('sessions', []);
foreach ($sessions as $session) { /** @var Document $session */
foreach ($sessions as $session) {/** @var Document $session */
$dbForInternal->deleteDocument('sessions', $session->getId());
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.sessions.delete')
->setParam('resource', '/user/'.$user->getId())
->setParam('resource', '/user/' . $user->getId())
;
if (!Config::getParam('domainVerification')) {
@ -1314,14 +1315,14 @@ App::delete('/v1/account/sessions')
if ($session->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
$session->setAttribute('current', true);
$response
->addCookie(Auth::$cookieName.'_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName . '_legacy', '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, null)
->addCookie(Auth::$cookieName, '', \time() - 3600, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
;
}
}
$dbForInternal->updateDocument('users', $user->getId(), $user->setAttribute('sessions', []));
$events
->setParam('eventData', $response->output(new Document([
'sessions' => $sessions,
@ -1347,7 +1348,7 @@ App::post('/v1/account/recovery')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', new Email(), 'User email.')
->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery 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.', false, ['clients'])
->param('url', '', function ($clients) {return new Host($clients);}, 'URL to redirect the user back to your app from the recovery 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.', false, ['clients'])
->inject('request')
->inject('response')
->inject('dbForInternal')
@ -1392,8 +1393,8 @@ App::post('/v1/account/recovery')
'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(),
]);
Authorization::setRole('user:'.$profile->getId());
Authorization::setRole('user:' . $profile->getId());
$profile->setAttribute('tokens', $recovery, Document::SET_TYPE_APPEND);
@ -1418,18 +1419,18 @@ App::post('/v1/account/recovery')
$events
->setParam('eventData',
$response->output($recovery->setAttribute('secret', $secret),
Response::MODEL_TOKEN
))
Response::MODEL_TOKEN
))
;
$recovery // Hide secret for clients, sp
$recovery // Hide secret for clients, sp
->setAttribute('secret',
($isPrivilegedUser || $isAppUser) ? $secret : '');
$audits
->setParam('userId', $profile->getId())
->setParam('event', 'account.recovery.create')
->setParam('resource', 'users/'.$profile->getId())
->setParam('resource', 'users/' . $profile->getId())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -1461,7 +1462,7 @@ App::put('/v1/account/recovery')
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Appwrite\Event\Event $audits */
if ($password !== $passwordAgain) {
throw new Exception('Passwords must match', 400);
}
@ -1479,21 +1480,21 @@ App::put('/v1/account/recovery')
throw new Exception('Invalid recovery token', 401);
}
Authorization::setRole('user:'.$profile->getId());
Authorization::setRole('user:' . $profile->getId());
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
->setAttribute('emailVerification', true)
->setAttribute('password', Auth::passwordHash($password))
->setAttribute('passwordUpdate', \time())
->setAttribute('emailVerification', true)
);
/**
* We act like we're updating and validating
* the recovery token but actually we don't need it anymore.
*/
* We act like we're updating and validating
* the recovery token but actually we don't need it anymore.
*/
foreach ($tokens as $key => $token) {
if($recovery === $token->getId()) {
if ($recovery === $token->getId()) {
$recovery = $token;
unset($tokens[$key]);
}
@ -1504,7 +1505,7 @@ App::put('/v1/account/recovery')
$audits
->setParam('userId', $profile->getId())
->setParam('event', 'account.recovery.update')
->setParam('resource', 'users/'.$profile->getId())
->setParam('resource', 'users/' . $profile->getId())
;
$response->dynamic($recovery, Response::MODEL_TOKEN);
@ -1551,7 +1552,7 @@ App::post('/v1/account/verification')
$verificationSecret = Auth::tokenGenerator();
$expire = \time() + Auth::TOKEN_EXPIRATION_CONFIRM;
$verification = new Document([
'$id' => $dbForInternal->getId(),
'userId' => $user->getId(),
@ -1561,8 +1562,8 @@ App::post('/v1/account/verification')
'userAgent' => $request->getUserAgent('UNKNOWN'),
'ip' => $request->getIP(),
]);
Authorization::setRole('user:'.$user->getId());
Authorization::setRole('user:' . $user->getId());
$user->setAttribute('tokens', $verification, Document::SET_TYPE_APPEND);
@ -1587,18 +1588,18 @@ App::post('/v1/account/verification')
$events
->setParam('eventData',
$response->output($verification->setAttribute('secret', $verificationSecret),
Response::MODEL_TOKEN
))
Response::MODEL_TOKEN
))
;
$verification // Hide secret for clients, sp
$verification // Hide secret for clients, sp
->setAttribute('secret',
($isPrivilegedUser || $isAppUser) ? $verificationSecret : '');
$audits
->setParam('userId', $user->getId())
->setParam('event', 'account.verification.create')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->setStatusCode(Response::STATUS_CODE_CREATED);
@ -1644,16 +1645,16 @@ App::put('/v1/account/verification')
throw new Exception('Invalid verification token', 401);
}
Authorization::setRole('user:'.$profile->getId());
Authorization::setRole('user:' . $profile->getId());
$profile = $dbForInternal->updateDocument('users', $profile->getId(), $profile->setAttribute('emailVerification', true));
/**
* We act like we're updating and validating
* the verification token but actually we don't need it anymore.
*/
* We act like we're updating and validating
* the verification token but actually we don't need it anymore.
*/
foreach ($tokens as $key => $token) {
if($token->getId() === $verification) {
if ($token->getId() === $verification) {
$verification = $token;
unset($tokens[$key]);
}
@ -1664,7 +1665,7 @@ App::put('/v1/account/verification')
$audits
->setParam('userId', $profile->getId())
->setParam('event', 'account.verification.update')
->setParam('resource', 'users/'.$user->getId())
->setParam('resource', 'users/' . $user->getId())
;
$response->dynamic($verification, Response::MODEL_TOKEN);

View file

@ -443,6 +443,9 @@ App::get('/v1/avatars/initials')
$name = (!empty($name)) ? $name : $user->getAttribute('name', $user->getAttribute('email', ''));
$words = \explode(' ', \strtoupper($name));
// if there is no space, try to split by `_` underscore
$words = (count($words) == 1 ) ? \explode('_', \strtoupper($name)) : $words;
$initials = null;
$code = 0;
@ -455,7 +458,6 @@ App::get('/v1/avatars/initials')
}
}
$length = \count($words);
$rand = \substr($code, -1);
$background = (!empty($background)) ? '#' . $background : $themes[$rand]['background'];
$color = (!empty($color)) ? '#' . $color : $themes[$rand]['color'];

View file

@ -1,5 +1,6 @@
<?php
use Appwrite\Database\Validator\CustomId;
use Utopia\App;
use Utopia\Exception;
use Utopia\Validator\Boolean;
@ -131,20 +132,21 @@ App::post('/v1/database/collections')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_COLLECTION)
->param('collectionId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('name', '', new Text(128), 'Collection name. Max length: 128 chars.')
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('write', null, new Permissions(), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->inject('response')
->inject('dbForExternal')
->inject('audits')
->action(function ($name, $read, $write, $response, $dbForExternal, $audits) {
->action(function ($collectionId, $name, $read, $write, $response, $dbForExternal, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal*/
/** @var Appwrite\Event\Event $audits */
$id = $dbForExternal->getId();
$collectionId = $collectionId == 'unique()' ? $dbForExternal->getId() : $collectionId;
$collection = $dbForExternal->createCollection($id);
$collection = $dbForExternal->createCollection($collectionId);
// TODO@kodumbeats what should the default permissions be?
$read = (is_null($read)) ? ($collection->getRead() ?? []) : $read; // By default inherit read permissions
@ -154,7 +156,7 @@ App::post('/v1/database/collections')
$collection->setAttribute('$read', $read);
$collection->setAttribute('$write', $write);
$dbForExternal->updateDocument(Database::COLLECTIONS, $id, $collection);
$dbForExternal->updateDocument(Database::COLLECTIONS, $collectionId, $collection);
$audits
->setParam('event', 'database.collections.create')
@ -999,6 +1001,7 @@ App::post('/v1/database/collections/:collectionId/documents')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_DOCUMENT)
->param('documentId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('collectionId', null, new UID(), 'Collection unique ID. You can create a new collection with validation rules using the Database service [server integration](/docs/server/database#createCollection).')
->param('data', [], new JSON(), 'Document data as JSON object.')
->param('read', null, new Permissions(), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
@ -1007,7 +1010,7 @@ App::post('/v1/database/collections/:collectionId/documents')
->inject('dbForExternal')
->inject('user')
->inject('audits')
->action(function ($collectionId, $data, $read, $write, $response, $dbForExternal, $user, $audits) {
->action(function ($documentId, $collectionId, $data, $read, $write, $response, $dbForExternal, $user, $audits) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForExternal */
/** @var Utopia\Database\Document $user */
@ -1030,7 +1033,7 @@ App::post('/v1/database/collections/:collectionId/documents')
}
$data['$collection'] = $collection->getId(); // Adding this param to make API easier for developers
$data['$id'] = $dbForExternal->getId();
$data['$id'] = $documentId == 'unique()' ? $dbForExternal->getId() : $documentId;
$data['$read'] = (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? []; // By default set read permissions for user
$data['$write'] = (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? []; // By default set write permissions for user

View file

@ -2,6 +2,7 @@
use Ahc\Jwt\JWT;
use Appwrite\Auth\Auth;
use Appwrite\Database\Validator\CustomId;
use Utopia\Database\Validator\UID;
use Utopia\Storage\Storage;
use Utopia\Storage\Validator\File;
@ -38,6 +39,7 @@ App::post('/v1/functions')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FUNCTION)
->param('functionId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('name', '', new Text(128), 'Function name. Max length: 128 chars.')
->param('execute', [], new ArrayList(new Text(64)), 'An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
->param('runtime', '', new WhiteList(array_keys(Config::getParam('runtimes')), true), 'Execution runtime.')
@ -47,11 +49,12 @@ App::post('/v1/functions')
->param('timeout', 15, new Range(1, 900), 'Function maximum execution time in seconds.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForInternal) {
->action(function ($functionId, $name, $execute, $runtime, $vars, $events, $schedule, $timeout, $response, $dbForInternal) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
$function = $dbForInternal->createDocument('functions', new Document([
'$id' => $functionId == 'unique()' ? $dbForInternal->getId() : $functionId,
'execute' => $execute,
'dateCreated' => time(),
'dateUpdated' => time(),
@ -479,6 +482,7 @@ App::post('/v1/functions/:functionId/tags')
}
$tag = $dbForInternal->createDocument('tags', new Document([
'$id' => $dbForInternal->getId(),
'$read' => [],
'$write' => [],
'functionId' => $function->getId(),
@ -696,6 +700,7 @@ App::post('/v1/functions/:functionId/executions')
Authorization::disable();
$execution = $dbForInternal->createDocument('executions', new Document([
'$id' => $dbForInternal->getId(),
'$read' => (!$user->isEmpty()) ? ['user:' . $user->getId()] : [],
'$write' => [],
'dateCreated' => time(),

View file

@ -1,6 +1,7 @@
<?php
use Appwrite\Auth\Auth;
use Appwrite\Database\Validator\CustomId;
use Appwrite\Network\Validator\CNAME;
use Appwrite\Network\Validator\Domain as DomainValidator;
use Appwrite\Network\Validator\URL;
@ -31,14 +32,6 @@ App::init(function ($project) {
}
}, ['project'], 'projects');
App::init(function ($project) {
/** @var Utopia\Database\Document $project */
if($project->getId() !== 'console') {
throw new Exception('Access to this API is forbidden.', 401);
}
}, ['project'], 'projects');
App::post('/v1/projects')
->desc('Create Project')
->groups(['api', 'projects'])
@ -49,6 +42,7 @@ App::post('/v1/projects')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_PROJECT)
->param('projectId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('name', null, new Text(128), 'Project name. Max length: 128 chars.')
->param('teamId', '', new UID(), 'Team unique ID.')
->param('description', '', new Text(256), 'Project description. Max length: 256 chars.', true)
@ -65,7 +59,7 @@ App::post('/v1/projects')
->inject('dbForInternal')
->inject('dbForExternal')
->inject('consoleDB')
->action(function ($name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $dbForConsole, $dbForInternal, $dbForExternal, $consoleDB) {
->action(function ($projectId, $name, $teamId, $description, $logo, $url, $legalName, $legalCountry, $legalState, $legalCity, $legalAddress, $legalTaxId, $response, $dbForConsole, $dbForInternal, $dbForExternal, $consoleDB) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForConsole */
/** @var Utopia\Database\Database $dbForInternal */
@ -77,12 +71,20 @@ App::post('/v1/projects')
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$auth = Config::getParam('auth', []);
$auths = ['limit' => 0];
foreach ($auth as $index => $method) {
$auths[$method['key'] ?? ''] = true;
}
$project = $dbForConsole->createDocument('projects', new Document([
'$id' => $projectId == 'unique()' ? $dbForConsole->getId() : $projectId,
'$collection' => 'projects',
'$read' => ['team:' . $teamId],
'$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'],
'teamId' => $team->getId(),
'name' => $name,
'teamId' => $team->getId(),
'description' => $description,
'logo' => $logo,
'url' => $url,
@ -98,11 +100,7 @@ App::post('/v1/projects')
'webhooks' => [],
'keys' => [],
'domains' => [],
'usersAuthEmailPassword' => true,
'usersAuthAnonymous' => true,
'usersAuthInvites' => true,
'usersAuthJWT' => true,
'usersAuthPhone' => true,
'auths' => $auths,
]));
$collections = Config::getParam('collections2', []); /** @var array $collections */
@ -520,10 +518,11 @@ App::patch('/v1/projects/:projectId/oauth2')
throw new Exception('Project not found', 404);
}
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute('usersOauth2' . \ucfirst($provider) . 'Appid', $appId)
->setAttribute('usersOauth2' . \ucfirst($provider) . 'Secret', $secret)
);
$providers = $project->getAttribute('providers', []);
$providers[$provider . 'Appid'] = $appId;
$providers[$provider . 'Secret'] = $secret;
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('providers', $providers));
$response->dynamic($project, Response::MODEL_PROJECT);
});
@ -552,8 +551,11 @@ App::patch('/v1/projects/:projectId/auth/limit')
throw new Exception('Project not found', 404);
}
$auths = $project->getAttribute('auths', []);
$auths['limit'] = $limit;
$dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute('usersAuthLimit', $limit)
->setAttribute('auths', $auths)
);
$response->dynamic($project, Response::MODEL_PROJECT);
@ -587,9 +589,10 @@ App::patch('/v1/projects/:projectId/auth/:method')
throw new Exception('Project not found', 404);
}
$dbForConsole->updateDocument('projects', $project->getId(), $project
->setAttribute($authKey, $status)
);
$auths = $project->getAttribute('auths', []);
$auths[$authKey] = $status;
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('auths', $auths));
$response->dynamic($project, Response::MODEL_PROJECT);
});

View file

@ -10,6 +10,7 @@ use Utopia\Validator\HexColor;
use Utopia\Cache\Cache;
use Utopia\Cache\Adapter\Filesystem;
use Appwrite\ClamAV\Network;
use Appwrite\Database\Validator\CustomId;
use Utopia\Database\Document;
use Utopia\Database\Validator\UID;
use Utopia\Storage\Storage;
@ -37,6 +38,7 @@ App::post('/v1/storage/files')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_FILE)
->param('fileId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('file', [], new File(), 'Binary file.', false)
->param('read', null, new ArrayList(new Text(64)), 'An array of strings with read permissions. By default only the current user is granted with read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
->param('write', null, new ArrayList(new Text(64)), 'An array of strings with write permissions. By default only the current user is granted with write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.', true)
@ -46,7 +48,7 @@ App::post('/v1/storage/files')
->inject('user')
->inject('audits')
->inject('usage')
->action(function ($file, $read, $write, $request, $response, $dbForInternal, $user, $audits, $usage) {
->action(function ($fileId, $file, $read, $write, $request, $response, $dbForInternal, $user, $audits, $usage) {
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
@ -122,6 +124,7 @@ App::post('/v1/storage/files')
$sizeActual = $device->getFileSize($path);
$file = $dbForInternal->createDocument('files', new Document([
'$id' => $fileId == 'unique()' ? $dbForInternal->getId() : $fileId,
'$read' => (is_null($read) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $read ?? [], // By default set read permissions for user
'$write' => (is_null($write) && !$user->isEmpty()) ? ['user:'.$user->getId()] : $write ?? [], // By default set write permissions for user
'dateCreated' => \time(),

View file

@ -1,6 +1,7 @@
<?php
use Appwrite\Auth\Auth;
use Appwrite\Database\Validator\CustomId;
use Appwrite\Detector\Detector;
use Appwrite\Template\Template;
use Appwrite\Utopia\Response;
@ -32,12 +33,13 @@ App::post('/v1/teams')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TEAM)
->param('teamId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('name', null, new Text(128), 'Team name. Max length: 128 chars.')
->param('roles', ['owner'], new ArrayList(new Key()), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.', true)
->inject('response')
->inject('user')
->inject('dbForInternal')
->action(function ($name, $roles, $response, $user, $dbForInternal) {
->action(function ($teamId, $name, $roles, $response, $user, $dbForInternal) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Database\Database $dbForInternal */
@ -47,7 +49,7 @@ App::post('/v1/teams')
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
$isAppUser = Auth::isAppUser(Authorization::$roles);
$teamId = $dbForInternal->getId();
$teamId = $teamId == 'unique()' ? $dbForInternal->getId() : $teamId;
$team = $dbForInternal->createDocument('teams', new Document([
'$id' => $teamId ,
'$read' => ['team:'.$teamId],
@ -286,7 +288,7 @@ App::post('/v1/teams/:teamId/memberships')
if (empty($invitee)) { // Create new user if no user with same email found
$limit = $project->getAttribute('usersAuthLimit', 0);
$limit = $project->getAttribute('auths', [])['limit'] ?? 0;
if ($limit !== 0 && $project->getId() !== 'console') { // check users limit, console invites are allways allowed.
$sum = $dbForInternal->count('users', [], APP_LIMIT_USERS);
@ -464,6 +466,42 @@ App::get('/v1/teams/:teamId/memberships')
]), Response::MODEL_MEMBERSHIP_LIST);
});
App::get('/v1/teams/:teamId/memberships/:membershipId')
->desc('Get Team Membership')
->groups(['api', 'teams'])
->label('scope', 'teams.read')
->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT])
->label('sdk.namespace', 'teams')
->label('sdk.method', 'getMembership')
->label('sdk.description', '/docs/references/teams/get-team-member.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_MEMBERSHIP_LIST)
->param('teamId', '', new UID(), 'Team unique ID.')
->param('membershipId', '', new UID(), 'membership unique ID.')
->inject('response')
->inject('dbForInternal')
->action(function ($teamId, $membershipId, $response, $dbForInternal) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
$team = $dbForInternal->getDocument('teams', $teamId);
if ($team->isEmpty()) {
throw new Exception('Team not found', 404);
}
$membership = $dbForInternal->getDocument('memberships', $membershipId);
if($membership->isEmpty() || empty($membership->getAttribute('userId', null))) {
throw new Exception('Membership not found', 404);
}
$temp = $dbForInternal->getDocument('users', $membership->getAttribute('userId', null))->getArrayCopy(['email', 'name']);
$response->dynamic(new Document(\array_merge($temp, $membership->getArrayCopy())), Response::MODEL_MEMBERSHIP );
});
App::patch('/v1/teams/:teamId/memberships/:membershipId')
->desc('Update Membership Roles')
->groups(['api', 'teams'])

View file

@ -16,6 +16,7 @@ use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Validator\UID;
use DeviceDetector\DeviceDetector;
use Appwrite\Database\Validator\CustomId;
App::post('/v1/users')
->desc('Create User')
@ -29,19 +30,20 @@ App::post('/v1/users')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_USER)
->param('userId', '', new CustomId(), 'Unique Id. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, and underscore. Can\'t start with a leading underscore. Max length is 36 chars.')
->param('email', '', new Email(), 'User email.')
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
->inject('response')
->inject('dbForInternal')
->action(function ($email, $password, $name, $response, $dbForInternal) {
->action(function ($userId, $email, $password, $name, $response, $dbForInternal) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
$email = \strtolower($email);
try {
$userId = $dbForInternal->getId();
$userId = $userId == 'unique()' ? $dbForInternal->getId() : $userId;
$user = $dbForInternal->createDocument('users', new Document([
'$id' => $userId,
'$read' => ['role:all'],

View file

@ -53,7 +53,6 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons
'domain' => $domain->get(),
]);
$certificate = $dbForConsole->createDocument('certificates', $certificate);
Authorization::enable();
Console::info('Issuing a TLS certificate for the master domain (' . $domain->get() . ') in a few seconds...');
@ -63,10 +62,11 @@ App::init(function ($utopia, $request, $response, $console, $project, $dbForCons
'validateTarget' => false,
'validateCNAME' => false,
]);
} else {
Authorization::enable(); // ensure authorization is reenabled
}
$domains[$domain->get()] = true;
Authorization::reset(); // ensure authorization is re-enabled
}
Config::setParam('domains', $domains);
}

View file

@ -523,7 +523,7 @@ App::shutdown(function($utopia, $response, $request) {
$tests = \array_merge($tests, $result);
if (!\file_put_contents($path, \json_encode($tests), LOCK_EX)) {
throw new Exception('Failed to save resutls', 500);
throw new Exception('Failed to save results', 500);
}
$response->dynamic(new Document(['result' => $route->getMethod() . ':' . $route->getURL() . ':passed']), Response::MODEL_MOCK);

View file

@ -18,7 +18,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
/** @var Utopia\Registry\Registry $register */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Stats\Stats $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $database */
/** @var Appwrite\Event\Event $functions */
@ -115,18 +115,10 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
;
}, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes', 'database', 'dbForInternal'], 'api');
App::init(function ($utopia, $request, $response, $project, $user) {
App::init(function ($utopia, $request, $project) {
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Utopia\Database\Document $user */
/** @var Utopia\Registry\Registry $register */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $functions */
$route = $utopia->match($request);
@ -137,27 +129,28 @@ App::init(function ($utopia, $request, $response, $project, $user) {
return;
}
$auths = $project->getAttribute('auths', []);
switch ($route->getLabel('auth.type', '')) {
case 'emailPassword':
if($project->getAttribute('usersAuthEmailPassword', true) === false) {
if(($auths['emailPassword'] ?? true) === false) {
throw new Exception('Email / Password authentication is disabled for this project', 501);
}
break;
case 'anonymous':
if($project->getAttribute('usersAuthAnonymous', true) === false) {
if(($auths['anonymous'] ?? true) === false) {
throw new Exception('Anonymous authentication is disabled for this project', 501);
}
break;
case 'invites':
if($project->getAttribute('usersAuthInvites', true) === false) {
if(($auths['invites'] ?? true) === false) {
throw new Exception('Invites authentication is disabled for this project', 501);
}
break;
case 'jwt':
if($project->getAttribute('usersAuthJWT', true) === false) {
if(($auths['JWT'] ?? true) === false) {
throw new Exception('JWT authentication is disabled for this project', 501);
}
break;
@ -167,16 +160,16 @@ App::init(function ($utopia, $request, $response, $project, $user) {
break;
}
}, ['utopia', 'request', 'response', 'project', 'user'], 'auth');
}, ['utopia', 'request', 'project'], 'auth');
App::shutdown(function ($utopia, $request, $response, $project, $events, $audits, $usage, $deletes, $database, $mode) {
App::shutdown(function ($utopia, $request, $response, $project, $register, $events, $audits, $usage, $deletes, $database, $mode) {
/** @var Utopia\App $utopia */
/** @var Utopia\Swoole\Request $request */
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Document $project */
/** @var Appwrite\Event\Event $events */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Event\Event $usage */
/** @var Appwrite\Stats\Stats $usage */
/** @var Appwrite\Event\Event $deletes */
/** @var Appwrite\Event\Event $database */
/** @var Appwrite\Event\Event $functions */
@ -222,8 +215,8 @@ App::shutdown(function ($utopia, $request, $response, $project, $events, $audits
$usage
->setParam('networkRequestSize', $request->getSize() + $usage->getParam('storage'))
->setParam('networkResponseSize', $response->getSize())
->trigger()
->submit()
;
}
}, ['utopia', 'request', 'response', 'project', 'events', 'audits', 'usage', 'deletes', 'database', 'mode'], 'api');
}, ['utopia', 'request', 'response', 'project', 'register', 'events', 'audits', 'usage', 'deletes', 'database', 'mode'], 'api');

View file

@ -47,7 +47,11 @@ App::init(function ($utopia, $request, $response, $layout) {
;
$route = $utopia->match($request);
$route->label('error', __DIR__.'/../../views/general/error.phtml');
$scope = $route->getLabel('scope', '');
$layout
->setParam('version', App::getEnv('_APP_VERSION', 'UNKNOWN'))
->setParam('isDev', App::isDevelopment())

View file

@ -4,7 +4,7 @@ use Utopia\App;
use Utopia\View;
use Utopia\Config\Config;
use Utopia\Domains\Domain;
use Appwrite\Database\Database;
use Utopia\Database\Database;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Database\Validator\UID;
use Utopia\Storage\Storage;
@ -212,17 +212,17 @@ App::get('/console/database/collection')
->param('id', '', new UID(), 'Collection unique ID.')
->inject('response')
->inject('layout')
->inject('projectDB')
->action(function ($id, $response, $layout, $projectDB) {
->inject('dbForExternal')
->action(function ($id, $response, $layout, $dbForExternal) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\View $layout */
/** @var Appwrite\Database\Database $projectDB */
/** @var Utopia\Database\Database $dbForExternal */
Authorization::disable();
$collection = $projectDB->getDocument($id, false);
$collection = $dbForExternal->getCollection($id);
Authorization::reset();
if ($collection->isEmpty() || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404);
}
@ -250,16 +250,16 @@ App::get('/console/database/document')
->label('scope', 'console')
->param('collection', '', new UID(), 'Collection unique ID.')
->inject('layout')
->inject('projectDB')
->action(function ($collection, $layout, $projectDB) {
->inject('dbForExternal')
->action(function ($collection, $layout, $dbForExternal) {
/** @var Utopia\View $layout */
/** @var Appwrite\Database\Database $projectDB */
/** @var Utopia\Database\Database $dbForExternal */
Authorization::disable();
$collection = $projectDB->getDocument($collection, false);
$collection = $dbForExternal->getCollection($collection);
Authorization::reset();
if ($collection->isEmpty() || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
if ($collection->isEmpty()) {
throw new Exception('Collection not found', 404);
}
@ -268,7 +268,7 @@ App::get('/console/database/document')
$searchDocuments = new View(__DIR__.'/../../views/console/database/search/documents.phtml');
$page
->setParam('db', $projectDB)
->setParam('db', $dbForExternal)
->setParam('collection', $collection)
->setParam('searchFiles', $searchFiles)
->setParam('searchDocuments', $searchDocuments)

View file

@ -29,6 +29,7 @@ use Appwrite\Network\Validator\Email;
use Appwrite\Network\Validator\IP;
use Appwrite\Network\Validator\URL;
use Appwrite\OpenSSL\OpenSSL;
use Appwrite\Stats\Stats;
use Utopia\App;
use Utopia\View;
use Utopia\Config\Config;
@ -291,6 +292,7 @@ $register->set('statsd', function () { // Register DB connection
return $statsd;
});
$register->set('smtp', function () {
$mail = new PHPMailer(true);
@ -421,7 +423,7 @@ App::setResource('audits', function($register) {
}, ['register']);
App::setResource('usage', function($register) {
return new Event(Event::USAGE_QUEUE_NAME, Event::USAGE_CLASS_NAME);
return new Stats($register->get('statsd'));
}, ['register']);
App::setResource('mails', function($register) {
@ -580,8 +582,8 @@ App::setResource('project', function($dbForConsole, $request, $console) {
App::setResource('console', function() {
return new Document2([
'$id' => 'console',
'$collection' => 'projects',
'name' => 'Appwrite',
'$collection' => 'projects',
'description' => 'Appwrite core engine',
'logo' => '',
'teamId' => -1,
@ -613,9 +615,11 @@ App::setResource('console', function() {
'legalCity' => '',
'legalAddress' => '',
'legalTaxId' => '',
'auths' => [
'limit' => (App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user
],
'authWhitelistEmails' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null)) : [],
'authWhitelistIPs' => (!empty(App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null))) ? \explode(',', App::getEnv('_APP_CONSOLE_WHITELIST_IPS', null)) : [],
'usersAuthLimit' => (App::getEnv('_APP_CONSOLE_WHITELIST_ROOT', 'enabled') === 'enabled') ? 1 : 0, // limit signup to 1 user
]);
}, []);

View file

@ -202,6 +202,17 @@
data-analytics-label="Create Project">
<p>Appwrite projects are containers for your resources and apps across different platforms.</p>
<label>Project ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="projects.get"
required
maxlength="36"
class=""
name="projectId" />
<label>Name</label>
<input type="text" class="full-width margin-bottom-xl" name="name" required autocomplete="off" maxlength="128" />

View file

@ -22,8 +22,8 @@ $maxCells = 10;
</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>
<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">
@ -80,52 +80,52 @@ $maxCells = 10;
<div data-ls-if="({{project-documents.sum}})">
<div class="margin-bottom-small margin-end-small text-align-end text-size-small"><span data-ls-bind="{{project-documents.sum}}"></span> documents found</div>
<div class="box margin-bottom y-scroll">
<table class="vertical">
<thead>
<tr>
<?php foreach($rules as $i => $rule):
if($i > $maxCells) {
break;
}
$label = (isset($rule['label'])) ? $rule['label'] : '';
?>
<th width="120"><?php echo $this->escape($label); ?></th>
<?php endforeach; ?>
<?php foreach ($rules as $i => $rule):
if ($i > $maxCells) {
break;
}
$label = (isset($rule['label'])) ? $rule['label'] : '';
?>
<th width="120"><?php echo $this->escape($label); ?></th>
<?php endforeach;?>
</tr>
</thead>
<tbody data-ls-loop="project-documents.documents" data-ls-as="node">
<tr>
<?php foreach($rules as $i => $rule):
if($i > $maxCells) {
break;
}
$label = $rule['label'] ?? '';
$key = $rule['key'] ?? '';
$type = $rule['type'] ?? '';
$array = $rule['array'] ?? '';
?>
<td data-title="<?php echo $this->escape($label); ?>: " class="text-size-small text-height-small">
<a data-ls-attrs="href=/console/database/document?id={{node.$id}}&collection={{router.params.id}}&project={{router.params.project}}&buster={{project-collection.dateUpdated}}">
<?php if(!$array): ?>
<?php switch($type):
case 'fileId': ?>
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<?php break; ?>
<?php case 'document': ?>
{...}
<?php break; ?>
<?php default: ?>
<span data-ls-bind="{{node.<?php echo $this->escape($key); ?>}}" data-ls-attrs="title={{node.<?php echo $this->escape($key); ?>}}"></span>
<?php break; ?>
<?php endswitch; ?>
<?php else: ?>
<?php foreach ($rules as $i => $rule):
if ($i > $maxCells) {
break;
}
$label = $rule['label'] ?? '';
$key = $rule['key'] ?? '';
$type = $rule['type'] ?? '';
$array = $rule['array'] ?? '';
?>
<td data-title="<?php echo $this->escape($label); ?>: " class="text-size-small text-height-small">
<a data-ls-attrs="href=/console/database/document?id={{node.$id}}&collection={{router.params.id}}&project={{router.params.project}}&buster={{project-collection.dateUpdated}}">
<?php if (!$array): ?>
<?php switch ($type):
case 'fileId': ?>
<img data-ls-if="{{node.<?php echo $this->escape($key); ?>}} != ''" src="" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{node.<?php echo $this->escape($key); ?>}}/preview?width=65&height=65&project={{router.params.project}}&mode=admin" class="avatar" width="30" height="30" loading="lazy" />
<?php break;?>
<?php case 'document': ?>
{...}
<?php break;?>
<?php default: ?>
<span data-ls-bind="{{node.<?php echo $this->escape($key); ?>}}" data-ls-attrs="title={{node.<?php echo $this->escape($key); ?>}}"></span>
<?php break;?>
<?php endswitch;?>
<?php else: ?>
[...]
<?php endif; ?>
<?php endif;?>
</a>
</td>
<?php endforeach; ?>
<?php endforeach;?>
</tr>
</tbody>
</table>
@ -197,7 +197,7 @@ $maxCells = 10;
<div class="box">
<label for="collection-name">Name</label>
<input name="name" id="collection-name" type="text" autocomplete="off" data-ls-bind="{{project-collection.name}}" data-forms-text-direction required placeholder="Collection Name" maxlength="128" />
<h3 class="margin-bottom-small">Rules</h3>
<div data-ls-if="(!{{project-collection.rules.length}})">
@ -215,7 +215,7 @@ $maxCells = 10;
<div class="toggle list sorts" data-ls-ui-open>
<i class="icon-up-open pull-end margin-top-tiny"></i>
<i class="icon-down-open pull-end margin-top-tiny"></i>
<h4 class="margin-bottom">
<div class="pull-start margin-end-large margin-bottom-small">
<button type="button" disabled class="margin-bottom strip round" data-move-down><i class="icon-down-dir"></i></button>
@ -248,7 +248,7 @@ $maxCells = 10;
<fieldset data-ls-attrs="name=rules" data-cast-to="array">
<input name="$id" type="hidden" data-ls-bind="{{rule.$id}}" />
<input name="$collection" type="hidden" data-ls-bind="{{rule.$collection}}" />
<div class="row thin">
<div class="col span-6">
<label data-ls-attrs="for=rule-label-{{rule.$id}}">Label
@ -287,11 +287,11 @@ $maxCells = 10;
<option value="document">Document (Embeded)</option>
</optgroup>
</select>
<div class="margin-bottom">
<input name="required" type="hidden" data-forms-switch data-ls-bind="{{rule.required}}" data-cast-to="boolean" /> &nbsp; Required <span class="tooltip" data-tooltip="Mark whether this is a required attribute"><i class="icon-info-circled"></i></span>
</div>
<div class="margin-bottom">
<input name="array" type="hidden" data-forms-switch data-ls-bind="{{rule.array}}" data-cast-to="boolean" /> &nbsp; Array <span class="tooltip" data-tooltip="Mark whether this attribute should act as an array"><i class="icon-info-circled"></i></span>
</div>
@ -314,16 +314,16 @@ $maxCells = 10;
<div class="toggle margin-bottom margin-top" data-ls-ui-open data-button-aria="Open Permissions">
<i class="icon-plus pull-end margin-top-tiny"></i>
<i class="icon-minus pull-end margin-top-tiny"></i>
<h3 class="margin-bottom-large">Permissions</h3>
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-collection.$permissions.write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</div>
<button>Update</button>
@ -402,9 +402,9 @@ $maxCells = 10;
<input type="hidden" name="path" value="project-collection.rules" />
<input type="hidden" name="type" value="append" />
<fieldset name="value" data-cast-to="object">
<input name="$id" type="hidden" value="" />
<input name="$id" type="hidden" value="" />
<input name="$collection" type="hidden" value="rules" />
<div class="row thin">
@ -445,11 +445,11 @@ $maxCells = 10;
<option value="document">Document (Embeded)</option>
</optgroup>
</select>
<input name="default" type="hidden" value="" />
<input name="required" type="hidden" value="false" data-cast-to="boolean" />
<input name="array" type="hidden" value="false" data-cast-to="boolean" />
</fieldset>
<hr class="margin-top-no" />

View file

@ -1,8 +1,8 @@
<?php
use Appwrite\Database\Database;
use Utopia\View;
use Appwrite\Database\Validator\Authorization;
use Utopia\View;
$collection = $this->getParam('collection', null);
$searchFiles = $this->getParam('searchFiles', null);
@ -16,18 +16,18 @@ $collections = [];
<?php echo $searchFiles->render(); ?>
<?php foreach($rules as $rule): // Form to append child document
<?php foreach ($rules as $rule): // Form to append child document
$key = $rule['key'] ?? '';
$label = $rule['label'] ?? '';
$type = $rule['type'] ?? '';
$list = $rule['list'] ?? [];
?>
<?php foreach($list as $item):
if($item === $collection->getId()) {
?>
<?php foreach ($list as $item):
if ($item === $collection->getId()) {
continue; // Do not allow rec recrusion
}
if(!isset($collections[$item])) {
if (!isset($collections[$item])) {
Authorization::disable(); //TODO Try and avoid calling the DB from the template
$collections[$item] = $db->getDocument($item, false);
Authorization::reset();
@ -35,7 +35,7 @@ $collections = [];
$childCollection = $collections[$item];
if(!$childCollection->getId() || $childCollection->getCollection() !== Database::SYSTEM_COLLECTION_COLLECTIONS) {
if (!$childCollection->getId() || $childCollection->getCollection() !== Database::SYSTEM_COLLECTION_COLLECTIONS) {
continue;
}
@ -43,114 +43,114 @@ $collections = [];
->setParam('collection', $childCollection)
;
echo $searchDocuments->render(); ?>
<?php endforeach; ?>
<?php endforeach; ?>
echo $searchDocuments->render();?>
<?php endforeach;?>
<?php endforeach;?>
<?php foreach($rules as $rule): // Form to append child document
<?php foreach ($rules as $rule): // Form to append child document
$key = $rule['key'] ?? '';
$label = $rule['label'] ?? '';
$type = $rule['type'] ?? '';
$list = $rule['list'] ?? [];
$array = $rule['array'] ?? false;
?>
<?php if($type !== 'document' && $array): ?>
<form class="margin-bottom-no"
data-service="container.path"
data-event="collection-child-<?php echo $this->escape($namespace.'.'.$key); ?>"
data-scope="window.ls"
data-success="reset">
<input type="hidden" name="path" value="<?php echo $this->escape($namespace.'.'.$key); ?>" />
<input type="hidden" name="type" value="append" />
<input type="hidden" name="value" value="" />
</form>
<?php endif; ?>
<?php if($type !== 'document'): ?>
<?php continue; ?>
<?php endif; ?>
<?php foreach($list as $item):
if($item === $collection->getId()) {
continue; // Do not allow rec recrusion
}
if(!isset($collections[$item])) {
Authorization::disable(); //TODO Try and avoid calling the DB from the template
$collections[$item] = $db->getDocument($item, false);
Authorization::reset();
}
$childCollection = $collections[$item];
if(!$childCollection->getId() || $childCollection->getCollection() !== Database::SYSTEM_COLLECTION_COLLECTIONS) {
continue;
}
?>
<form class="margin-bottom-no"
data-service="container.path"
data-event="collection-child-<?php echo $this->escape($namespace.'.'.$key); ?>-<?php echo $this->escape($childCollection->getId()); ?>"
data-scope="window.ls"
data-success="reset">
<input type="hidden" name="path" value="<?php echo $this->escape($namespace.'.'.$key); ?>" />
<input type="hidden" name="type" value="append" />
<fieldset name="value" data-cast-to="object">
<input name="$id" type="hidden" value="" />
<input name="$collection" type="hidden" value="<?php echo $this->escape($childCollection->getId()); ?>" />
</fieldset>
</form>
<?php if ($type !== 'document' && $array): ?>
<script type="text/html" id="collection-<?php echo ($array) ? 'array-' : ''; ?><?php echo $this->escape($childCollection->getId()); ?>">
<?php
<form class="margin-bottom-no"
data-service="container.path"
data-event="collection-child-<?php echo $this->escape($namespace . '.' . $key); ?>"
data-scope="window.ls"
data-success="reset">
$comp = new View(__DIR__.'/form.phtml');
$comp
->setParam('collection', $childCollection)
->setParam('namespace', ($array) ? 'node' : $namespace.'.'.$key)
->setParam('key', $key)
->setParam('array', $array)
->setParam('parent', 0)
;
<input type="hidden" name="path" value="<?php echo $this->escape($namespace . '.' . $key); ?>" />
<input type="hidden" name="type" value="append" />
<input type="hidden" name="value" value="" />
</form>
echo $comp->render();
?>
</script>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endif;?>
<?php foreach($rules as $rule): // Form to remove array $index key
<?php if ($type !== 'document'): ?>
<?php continue;?>
<?php endif;?>
<?php foreach ($list as $item):
if ($item === $collection->getId()) {
continue; // Do not allow rec recrusion
}
if (!isset($collections[$item])) {
Authorization::disable(); //TODO Try and avoid calling the DB from the template
$collections[$item] = $db->getDocument($item, false);
Authorization::reset();
}
$childCollection = $collections[$item];
if (!$childCollection->getId() || $childCollection->getCollection() !== Database::SYSTEM_COLLECTION_COLLECTIONS) {
continue;
}
?>
<form class="margin-bottom-no"
data-service="container.path"
data-event="collection-child-<?php echo $this->escape($namespace . '.' . $key); ?>-<?php echo $this->escape($childCollection->getId()); ?>"
data-scope="window.ls"
data-success="reset">
<input type="hidden" name="path" value="<?php echo $this->escape($namespace . '.' . $key); ?>" />
<input type="hidden" name="type" value="append" />
<fieldset name="value" data-cast-to="object">
<input name="$id" type="hidden" value="" />
<input name="$collection" type="hidden" value="<?php echo $this->escape($childCollection->getId()); ?>" />
</fieldset>
</form>
<script type="text/html" id="collection-<?php echo ($array) ? 'array-' : ''; ?><?php echo $this->escape($childCollection->getId()); ?>">
<?php
$comp = new View(__DIR__ . '/form.phtml');
$comp
->setParam('collection', $childCollection)
->setParam('namespace', ($array) ? 'node' : $namespace . '.' . $key)
->setParam('key', $key)
->setParam('array', $array)
->setParam('parent', 0)
;
echo $comp->render();
?>
</script>
<?php endforeach;?>
<?php endforeach;?>
<?php foreach ($rules as $rule): // Form to remove array $index key
$key = $rule['key'] ?? '';
$label = $rule['label'] ?? '';
$type = $rule['type'] ?? '';
$list = $rule['list'] ?? false;
$array = $rule['array'] ?? false;
if(!$array) {
if (!$array) {
continue;
}
?>
<ul data-ls-loop="<?php echo $this->escape($namespace.'.'.$key); ?>" data-ls-as="xxx">
<li>
<form
data-service="container.path"
data-event="splice-<?php echo $this->escape($namespace.'.'.$key); ?>-{{$index}}"
data-scope="window.ls"
data-success="reset">
?>
<ul data-ls-loop="<?php echo $this->escape($namespace . '.' . $key); ?>" data-ls-as="xxx">
<li>
<form
data-service="container.path"
data-event="splice-<?php echo $this->escape($namespace . '.' . $key); ?>-{{$index}}"
data-scope="window.ls"
data-success="reset">
<input type="hidden" name="path" value="<?php echo $this->escape($namespace.'.'.$key); ?>" />
<input type="hidden" name="type" value="splice" />
<input type="hidden" name="value" data-ls-bind="{{$index}}" />
</form>
</li>
</ul>
<?php endforeach; ?>
<input type="hidden" name="path" value="<?php echo $this->escape($namespace . '.' . $key); ?>" />
<input type="hidden" name="type" value="splice" />
<input type="hidden" name="value" data-ls-bind="{{$index}}" />
</form>
</li>
</ul>
<?php endforeach;?>
<div
data-service="database.getDocument"
@ -173,8 +173,8 @@ $collections = [];
</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>
<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">
@ -215,57 +215,57 @@ $collections = [];
<!-- <div class="document-nav" data-forms-nav>
<ul class="text-align-end margin-end-small">
<?php foreach($rules as $rule): // Form to append child document
$key = $rule['key'] ?? '';
$label = $rule['label'] ?? '';
$type = $rule['type'] ?? '';
$list = $rule['list'] ?? [];
?>
<li class="text-size-small">
<span class="link text-fade" data-forms-nav-link="<?php echo $this->escape($key); ?>"><?php echo $this->escape($label); ?></span>
</li>
<?php endforeach; ?>
<?php foreach ($rules as $rule): // Form to append child document
$key = $rule['key'] ?? '';
$label = $rule['label'] ?? '';
$type = $rule['type'] ?? '';
$list = $rule['list'] ?? [];
?>
<li class="text-size-small">
<span class="link text-fade" data-forms-nav-link="<?php echo $this->escape($key); ?>"><?php echo $this->escape($label); ?></span>
</li>
<?php endforeach;?>
</ul>
</div> -->
<?php if(empty($rules)): ?>
<?php if (empty($rules)): ?>
<div class="margin-bottom-xl margin-top-xl margin-end margin-start text-align-center">
<h4 class="text-fade text-size-small">No attribute rules added yet.<br /><br /><a data-ls-attrs="href=/console/database/collection/settings?id={{router.params.collection}}&project={{router.params.project}}">Update Collection</a></h4>
</div>
<?php else: ?>
<?php
$comp = new View(__DIR__.'/form.phtml');
$comp
->setParam('collection', $collection)
->setParam('collections', $collections)
->setParam('namespace', $namespace)
->setParam('key', 'data')
->setParam('parent', 1)
;
$comp = new View(__DIR__ . '/form.phtml');
echo $comp->render();
?>
$comp
->setParam('collection', $collection)
->setParam('collections', $collections)
->setParam('namespace', $namespace)
->setParam('key', 'data')
->setParam('parent', 1)
;
echo $comp->render();
?>
<div class="toggle margin-bottom" data-ls-ui-open data-button-aria="Open Permissions">
<i class="icon-plus pull-end margin-top-tiny"></i>
<i class="icon-minus pull-end margin-top-tiny"></i>
<h3 class="margin-bottom-large">Permissions</h3>
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
<input type="hidden" id="collection-read" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="collection-write" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{project-document.$permissions.write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</div>
<button data-ls-if="({{project-document.$id}})">Update</button>
<button data-ls-if="(!{{project-document.$id}})">Create</button>
<?php endif; ?>
<?php endif;?>
</div>
</form>

View file

@ -29,7 +29,7 @@
<p class="margin-bottom-no">You haven't created any collections for your project yet.</p>
</div>
</div>
<div data-ls-if="0 != {{project-collections.sum}}">
<ul data-ls-loop="project-collections.collections" data-ls-as="collection" data-ls-append="" class="tiles cell-3 margin-bottom-small">
<li class="margin-bottom">
@ -94,13 +94,23 @@
data-failure-param-alert-text="Failed to create collection"
data-failure-param-alert-classname="error">
<label for="user-name">Name</label>
<label for="collection-id">Collection ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="database.getCollection"
required
maxlength="36"
name="collectionId" />
<label for="collection-name">Name</label>
<input type="text" class="full-width" id="collection-name" name="name" required autocomplete="off" maxlength="128" />
<input type="hidden" id="collection-read" name="read" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
<input type="hidden" id="collection-write" name="write" required data-cast-to="json" value="<?php echo htmlentities(json_encode([])); ?>" />
<input type="hidden" id="collection-rules" name="rules" required data-cast-to="json" value="{}" />
<hr />
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>

View file

@ -3,7 +3,7 @@ $fileLimit = $this->getParam('fileLimit', 0);
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
$events = array_keys($this->getParam('events', []));
$timeout = $this->getParam('timeout', 900);
$usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
$usageStatsEnabled = $this->getParam('usageStatsEnabled', true);
?>
<div
data-service="functions.get"
@ -23,8 +23,8 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</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>
<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">
@ -37,9 +37,9 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<div class="zone xl">
<ul class="phases clear" data-ui-phases data-selected="{{router.params.tab}}">
<li data-state="/console/functions/function?id={{router.params.id}}&project={{router.params.project}}">
<h2>Overview</h2>
<div class="row responsive margin-top-negative">
<div class="col span-8 margin-bottom">
<label>&nbsp;</label>
@ -98,7 +98,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<input type="hidden" name="tag" data-ls-bind="{{tag.$id}}">
<button>Activate</button>
</form>
<b data-ls-bind="{{tag.$id}}"></b> &nbsp;
<span class="text-fade" data-ls-bind="{{tag.command}}"></span>
<div class="text-size-small margin-top-small clear">
@ -202,9 +202,9 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</div>
</div>
</li>
<?php if($usageStatsEnabled): ?>
<?php if ($usageStatsEnabled): ?>
<li data-state="/console/functions/function/monitors?id={{router.params.id}}&project={{router.params.project}}">
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
data-service="functions.getUsage"
data-event="submit"
@ -238,8 +238,8 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
<h2>Monitors</h2>
<div
<div
data-service="functions.getUsage"
data-event="load"
data-name="usage"
@ -281,7 +281,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</ul>
</div>
</li>
<?php endif; ?>
<?php endif;?>
<li data-state="/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}">
<div class="text-fade text-size-small pull-end margin-top" data-ls-bind="{{project-function-executions.sum}} executions found"></div>
@ -337,7 +337,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</td>
<td data-title="">
<div data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-title="">
<button class="desktops-only pull-end link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
<button class="desktops-only pull-end link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
@ -452,8 +452,8 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<input name="name" id="function-name" type="text" autocomplete="off" data-ls-bind="{{project-function.name}}" data-forms-text-direction required placeholder="Function Name" maxlength="128" />
<label for="execute">Execute Access <span class="tooltip small" data-tooltip="Choose who can execute this function using the client API."><i class="icon-info-circled"></i></span> <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</span></label>
<input type="hidden" id="execute" name="execute" data-forms-tags data-cast-to="json" data-ls-bind="{{project-function.$permissions.execute}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<input type="hidden" id="execute" name="execute" data-forms-tags data-cast-to="json" data-ls-bind="{{project-function.execute}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="timeout">Timeout (seconds) <span class="tooltip small" data-tooltip="Limit the execution time of your function."><i class="icon-info-circled"></i></span></label>
<input name="timeout" id="function-timeout" type="number" autocomplete="off" data-ls-bind="{{project-function.timeout}}" min="1" max="<?php echo $this->escape($timeout); ?>" data-cast-to="integer" />
@ -463,18 +463,18 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<section class="margin-bottom" data-forms-select-all>
<label for="events" class="margin-bottom">Events <span class="tooltip small" data-tooltip="Choose which events should trigger this function."><i class="icon-info-circled"></i></span></label>
<div class="row responsive thin margin-top-small">
<?php foreach ($events as $i => $event) : ?>
<?php foreach ($events as $i => $event): ?>
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
<input type="checkbox" name="events" data-ls-bind="{{project-function.events}}" id="<?php echo $event; ?>" value="<?php echo $event; ?>" />
&nbsp;
<label class="inline" for="<?php echo $event; ?>"><?php echo $event; ?></label>
</div>
<?php if (($i + 1) % 2 === 0) : ?>
<?php if (($i + 1) % 2 === 0): ?>
</div>
<div class="row responsive thin">
<?php endif; ?>
<?php endif;?>
<?php endforeach; ?>
<?php endforeach;?>
</div>
</section>
@ -631,7 +631,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
data-failure="alert"
data-failure-param-alert-text="Failed to create function tag"
data-failure-param-alert-classname="error">
<input type="hidden" name="functionId" data-ls-bind="{{router.params.id}}" />
<label for="tag-command">Command</label>
@ -649,5 +649,5 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</ul>
</div>

View file

@ -35,7 +35,7 @@ $runtimes = $this->getParam('runtimes', []);
<div data-ls-if="0 != {{project-functions.functions.length}}">
<div class="margin-bottom-small margin-end-small text-align-end text-size-small margin-top-negative"><span data-ls-bind="{{project-functions.sum}}"></span> functions found</div>
<div class="box margin-bottom">
<ul data-ls-loop="project-functions.functions" data-ls-as="function" class="list">
<li class="clear">
@ -105,15 +105,24 @@ $runtimes = $this->getParam('runtimes', []);
data-failure="alert"
data-failure-param-alert-text="Failed to create function"
data-failure-param-alert-classname="error">
<label for="functionId">Function ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="functions.get"
required
maxlength="36"
name="functionId" />
<label for="name">Name</label>
<input type="text" id="name" name="name" required autocomplete="off" class="margin-bottom" maxlength="128" />
<label for="runtime">Runtimes</label>
<select name="runtime" id="runtime" required class="margin-bottom-xl">
<?php foreach($runtimes as $key => $runtime): ?>
<?php foreach ($runtimes as $key => $runtime): ?>
<option value="<?php echo $this->escape($key); ?>"><?php echo $this->escape($runtime['name']); ?> <?php echo $this->escape($runtime['version']); ?></option>
<?php endforeach; ?>
<?php endforeach;?>
</select>
<input id="execute" name="execute" value="" hidden/>

View file

@ -1,6 +1,6 @@
<?php
$graph = $this->getParam('graph', false);
$usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
$usageStatsEnabled = $this->getParam('usageStatsEnabled', true);
?>
<div class="cover margin-bottom-small">
@ -36,6 +36,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
data-analytics-label="Usage 24h"
data-service="projects.getUsage"
data-event="submit"
data-scope="console"
data-name="usage"
data-param-project-id="{{router.params.project}}"
data-param-range="24h">
@ -51,6 +52,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
data-analytics-label="Usage 30d"
data-service="projects.getUsage"
data-event="submit"
data-scope="console"
data-name="usage"
data-param-project-id="{{router.params.project}}">
<button class="tick">30d</button>
@ -65,6 +67,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
data-analytics-label="Usage 90d"
data-service="projects.getUsage"
data-event="submit"
data-scope="console"
data-name="usage"
data-param-project-id="{{router.params.project}}"
data-param-range="90d">
@ -73,7 +76,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<button class="tick margin-start-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
</div>
<?php endif; ?>
<?php endif;?>
</div>
<div
data-service="projects.getUsage"
@ -105,7 +108,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
</div>
</div>
</div>
<?php endif; ?>
<?php endif;?>
<div class="box dashboard">
<div class="row responsive">
@ -176,11 +179,11 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<div>
<div class="pull-start margin-end avatar-container">
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Platform Logo" class="avatar" loading="lazy" width="60" height="60" />
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Logo" class="avatar xs" loading="lazy" width="30" height="30" />
</div>
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Logo" class="avatar xs" loading="lazy" width="30" height="30" />
</div>
@ -276,7 +279,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<label for="hostname">Hostname <span class="tooltip large" data-tooltip="The hostname that your website will use to interact with the <?php echo APP_NAME; ?> APIs in production or development environments. No port number required."><i class="icon-question"></i></span></label>
<input name="hostname" type="text" class="margin-bottom" autocomplete="off" placeholder="localhost" required>
<div class="info margin-top margin-bottom">
<div class="text-bold margin-bottom-small">Next Steps</div>
@ -316,7 +319,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<label for="hostname">Hostname <span class="tooltip large" data-tooltip="The hostname that your website will use to interact with the <?php echo APP_NAME; ?> APIs in production or development environments. No port number required."><i class="icon-question"></i></span></label>
<input name="hostname" type="text" class="margin-bottom" autocomplete="off" placeholder="localhost" data-ls-bind="{{platform.hostname}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
@ -559,7 +562,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<label data-ls-attrs="for=key-{{platform.$id}}">Bundle ID <span class="tooltip large" data-tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."><i class="icon-question"></i></span></label>
<input name="key" type="text" class="margin-bottom" autocomplete="off" placeholder="com.cpmpany.appname" data-ls-bind="{{platform.key}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
@ -590,7 +593,39 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<label data-ls-attrs="for=key-{{platform.$id}}">Package Name <span class="tooltip large" data-tooltip="Your package name is generally the applicationId in your app-level build.gradle file."><i class="icon-question"></i></span></label>
<input name="key" type="text" class="margin-bottom" autocomplete="off" placeholder="com.cpmpany.appname" data-ls-bind="{{platform.key}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
</form>
</script>
<script type="text/html" id="template-desktop-update">
<form
data-analytics
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Project Platform (Flutter / Desktop)"
data-service="projects.updatePlatform"
data-scope="console"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated platform successfully"
data-success-param-trigger-events="projects.updatePlatform"
data-failure="alert"
data-failure-param-alert-text="Failed to update platform"
data-failure-param-alert-classname="error">
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="platformId" data-ls-bind="{{platform.$id}}" />
<label data-ls-attrs="for=name-{{platform.$id}}">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" data-ls-attrs="id=name-{{platform.$id}}" name="name" required autocomplete="off" data-ls-bind="{{platform.name}}" placeholder="My desktop app" maxlength="128" />
<label data-ls-attrs="for=key-{{platform.$id}}">App Name <span class="tooltip large" data-tooltip="Your application name"><i class="icon-question"></i></span></label>
<input name="key" type="text" class="margin-bottom" autocomplete="off" placeholder="appname" data-ls-bind="{{platform.key}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
@ -605,6 +640,14 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled',true);
<div data-ls-template="template-android-update" data-type="script"></div>
</script>
<script type="text/html" id="template-flutter-linux-update">
<div data-ls-template="template-desktop-update" data-type="script"></div>
</script>
<script type="text/html" id="template-flutter-macos-update">
<div data-ls-template="template-macos-update" data-type="script"></div>
<div data-ls-template="template-ios-update" data-type="script"></div>
</script>
<script type="text/html" id="template-flutter-windows-update">
<div data-ls-template="template-desktop-update" data-type="script"></div>
</script>

View file

@ -57,18 +57,18 @@ $scopes = $this->getParam('scopes', []);
<section data-forms-select-all>
<label data-ls-attrs="for=scopes-{{key.$id}}">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
<div class="row responsive thin">
<?php foreach ($scopes as $i => $scope) : ?>
<?php foreach ($scopes as $i => $scope): ?>
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $scope; ?>">
<input data-ls-attrs="id=scope-<?php echo $scope; ?>" type="checkbox" name="scopes" data-ls-bind="{{key.scopes}}" value="<?php echo $scope; ?>" />
&nbsp;
<label class="inline" for="scope-<?php echo $scope; ?>"><?php echo $scope; ?></label>
</div>
<?php if (($i + 1) % 2 === 0) : ?>
<?php if (($i + 1) % 2 === 0): ?>
</div>
<div class="row responsive thin">
<?php endif; ?>
<?php endforeach; ?>
<?php endif;?>
<?php endforeach;?>
</div>
</section>
@ -114,7 +114,7 @@ $scopes = $this->getParam('scopes', []);
<div class="input-copy">
<textarea disabled style="height: 130px; line-height: 26px" data-forms-copy data-ls-bind="{{key.secret}}"></textarea>
</div>
<hr />
<div>
@ -160,18 +160,18 @@ $scopes = $this->getParam('scopes', []);
<section data-forms-select-all>
<label for="scopes">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
<div class="row responsive thin">
<?php foreach ($scopes as $i => $scope) : ?>
<?php foreach ($scopes as $i => $scope): ?>
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $scope; ?>">
<input type="checkbox" name="scopes" id="<?php echo $scope; ?>" value="<?php echo $scope; ?>" />
&nbsp;
<input type="checkbox" name="scopes" id="<?php echo $scope; ?>" value="<?php echo $scope; ?>" />
&nbsp;
<label class="inline" for="<?php echo $scope; ?>"><?php echo $scope; ?></label>
</div>
<?php if (($i + 1) % 2 === 0) : ?>
<?php if (($i + 1) % 2 === 0): ?>
</div>
<div class="row responsive thin">
<?php endif; ?>
<?php endif;?>
<?php endforeach; ?>
<?php endforeach;?>
</div>
</section>

View file

@ -3,7 +3,6 @@ $services = $this->getParam('services', []);
$customDomainsEnabled = $this->getParam('customDomainsEnabled', false);
$customDomainsTarget = $this->getParam('customDomainsTarget', false);
$smtpEnabled = $this->getParam('smtpEnabled', false);
?>
<div class="cover">
<h1 class="zone xl margin-bottom-large">
@ -51,7 +50,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
data-failure-param-alert-classname="error">
<input name="$id" type="hidden" data-ls-bind="{{console-project.$id}}" />
<label for="name">Name</label>
<input name="name" id="name" type="text" autocomplete="off" data-ls-bind="{{console-project.name}}" data-forms-text-direction required maxlength="128" />
@ -260,10 +259,10 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
<div class="box line margin-bottom">
<h3>Enable Custom Domains</h3>
<p>To enable <?php echo APP_NAME; ?>'s custom domain feature, you have to start your server instance with a public accessable domain name.</p>
<p>To enable <?php echo APP_NAME; ?>'s custom domain feature, you have to start your server instance with a public accessible domain name.</p>
<p>Start your <?php echo APP_NAME; ?> server container with the <b>_APP_DOMAIN_TARGET</b> enviornment variable set with a public accessable domain name that resolves to your <?php echo APP_NAME; ?> server setup.</p>
<p class="margin-bottom-no">The <?php echo APP_NAME; ?> server will use your target domain to validate new custom domains and will automatically generate SSL certificates for your new domains using letsencrypt certbot.</p>
<p>Start your <?php echo APP_NAME; ?> server container with the <b>_APP_DOMAIN_TARGET</b> environment variable set with a public accessible domain name that resolves to your <?php echo APP_NAME; ?> server setup.</p>
<p class="margin-bottom-no">The <?php echo APP_NAME; ?> server will use your target domain to validate new custom domains and will automatically generate SSL certificates for your new domains using Let'sencrypt Certbot.</p>
</div>
<?php endif; ?>
@ -293,7 +292,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
<th width="200">Domain Name</th>
<th width="160">TLS</th>
<th></th>
<th width="40"></th>
<th width="80"></th>
</tr>
</thead>
<tbody data-ls-loop="console-domains.domains" data-ls-as="domain">
@ -395,7 +394,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="domainId" data-ls-bind="{{domain.$id}}" />
<button class="danger round reverse small"><i class="icon-trash"></i></button>
<button class="danger small">Delete</button>
</form>
</td>
</tr>
@ -551,7 +550,7 @@ $smtpEnabled = $this->getParam('smtpEnabled', false);
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{console-project.teamId}}">
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}/auth/join?project={{router.params.project}}" />
<label for="email">Email</label>
<input name="email" id="email" type="email" autocomplete="email" required>

View file

@ -107,11 +107,11 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-read-{{file.$id}}" name="read" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$read}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-write-{{file.$id}}" name="write" data-forms-tags data-cast-to="json" data-ls-bind="{{file.$write}}" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
</form>
<form class="strip"
@ -136,7 +136,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
</div>
<div class="col span-4 text-size-small">
<div class="margin-bottom-small">File Preview</div>
<div class="margin-bottom-small">
<img src="" class="file-preview" data-ls-attrs="src={{env.ENDPOINT}}/v1/storage/files/{{file.$id}}/preview?width=350&height=250&project={{router.params.project}}&mode=admin" loading="lazy" width="225" height="160" />
</div>
@ -237,6 +237,17 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
data-failure-param-alert-classname="error">
<input type="hidden" name="folderId" id="files-folderId" data-cast-to="integer" value="1">
<label for="fileId">File ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="storage.getFile"
required
maxlength="36"
name="fileId"
id="fileId" />
<label for="file-read">File</label>
<input type="file" name="file" id="file-file" size="1" required>
@ -244,11 +255,11 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['role:all'])); ?>" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank" rel="noopener">Learn more</a>)</label>
<input type="hidden" id="file-write" name="write" data-forms-tags data-cast-to="json" value="" placeholder="User ID, Team ID or Role" />
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add * for wildcard access</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">Add 'role:all' for wildcard access</div>
<footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>

View file

@ -154,6 +154,17 @@ $auth = $this->getParam('auth', []);
data-failure-param-alert-text="Failed to create user"
data-failure-param-alert-classname="error">
<label for="userId">User ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="users.get"
required
maxlength="36"
id="userId"
name="userId" />
<label for="user-name">Name</label>
<input type="text" class="full-width" id="user-name" name="name" required autocomplete="off" maxlength="128" />
@ -290,9 +301,20 @@ $auth = $this->getParam('auth', []);
data-failure-param-alert-text="Failed to create team"
data-failure-param-alert-classname="error">
<label for="teamId">Team ID</label>
<input
type="hidden"
data-custom-id
data-id-type="auto"
data-validator="teams.get"
required
maxlength="36"
id="teamId"
name="teamId" />
<label for="team-name">Name</label>
<input type="text" class="full-width" id="team-name" name="name" required autocomplete="off" maxlength="128" />
<hr />
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
@ -300,10 +322,10 @@ $auth = $this->getParam('auth', []);
</div>
</div>
</li>
<li data-state="/console/users/providers?project={{router.params.project}}">
<p data-ls-if="{{console-project.usersAuthLimit}} == 0" class="text-fade text-size-small margin-bottom pull-end">Unlimited Users <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Set Limit</a></p>
<p data-ls-if="{{console-project.usersAuthLimit}} != 0" class="text-fade text-size-small margin-bottom pull-end"><span data-ls-bind="{{console-project.usersAuthLimit|statsTotal}}"></span> Users allowed <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Change Limit</a></p>
<p data-ls-if="{{console-project.authLimit}} == 0" class="text-fade text-size-small margin-bottom pull-end">Unlimited Users <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Set Limit</a></p>
<p data-ls-if="{{console-project.authLimit}} != 0" class="text-fade text-size-small margin-bottom pull-end"><span data-ls-bind="{{console-project.authLimit|statsTotal}}"></span> Users allowed <span class="link" data-ls-ui-trigger="project-update-auth-users-limit">Change Limit</a></p>
<h2>Settings</h2>
@ -329,7 +351,7 @@ $auth = $this->getParam('auth', []);
data-failure-param-alert-text="Failed to update project users limit"
data-failure-param-alert-classname="error">
<input name="limit" id="users-limit" type="number" data-ls-bind="{{console-project.usersAuthLimit}}" data-cast-to="numeric" min="0" />
<input name="limit" id="users-limit" type="number" data-ls-bind="{{console-project.authLimit}}" data-cast-to="numeric" min="0" />
<div class="info row thin margin-bottom margin-top">
<div class="col span-1">
@ -373,22 +395,22 @@ $auth = $this->getParam('auth', []);
data-failure-param-alert-classname="error">
<input name="method" id="<?php echo $this->escape($key); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($index); ?>">
<input name="status" type="hidden" data-forms-switch data-ls-bind="{{console-project.<?php echo $this->escape($key); ?>}}" data-cast-to="boolean" class="pull-end" />
<input name="status" type="hidden" data-forms-switch data-ls-bind="{{console-project.auth<?php echo $this->escape(ucfirst($key)); ?>}}" data-cast-to="boolean" class="pull-end" />
</form>
<?php endif; ?>
<img src="<?php echo $this->escape($icon); ?>?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo $this->escape($name); ?> Logo" class="pull-start provider margin-end" />
<span class="text-size-small"><?php echo $this->escape($name); ?><?php if(!$enabled): ?> <span class="text-fade text-size-xs">soon</span><?php endif; ?></span>
<?php if($docs): ?>
<span class="text-size-small"><?php echo $this->escape($name); ?><?php if (!$enabled): ?> <span class="text-fade text-size-xs">soon</span><?php endif;?></span>
<?php if ($docs): ?>
<p class="margin-bottom-no text-one-liner text-size-small">
<a href="<?php echo $this->escape($docs); ?>" target="_blank" rel="noopener">Docs<i class="icon-link-ext"></i></a>
</p>
<?php endif; ?>
<?php endif;?>
</div>
</li>
<?php endforeach; ?>
<?php endforeach;?>
</ul>
<h3>OAuth2 Providers</h3>
@ -401,18 +423,18 @@ $auth = $this->getParam('auth', []);
data-scope="console">
<ul class="tiles cell-3 margin-bottom-small">
<?php foreach ($providers as $provider => $data):
if (isset($data['enabled']) && !$data['enabled']) { continue; }
if (isset($data['mock']) && $data['mock']) { continue; }
$sandbox = $data['sandbox'] ?? false;
$form = $data['form'] ?? false;
$name = $data['name'] ?? 'Unknown';
$beta = $data['beta'] ?? false;
?>
<li class="<?php echo (isset($data['enabled']) && !$data['enabled']) ? 'dev-feature' : ''; ?>">
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="provider-update-<?php echo $provider; ?>">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
if (isset($data['enabled']) && !$data['enabled']) {continue;}
if (isset($data['mock']) && $data['mock']) {continue;}
$sandbox = $data['sandbox'] ?? false;
$form = $data['form'] ?? false;
$name = $data['name'] ?? 'Unknown';
$beta = $data['beta'] ?? false;
?>
<li class="<?php echo (isset($data['enabled']) && !$data['enabled']) ? 'dev-feature' : ''; ?>">
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="provider-update-<?php echo $provider; ?>">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1><?php echo $this->escape($name); ?> <?php if($sandbox): ?>Sandbox<?php endif; ?> OAuth2 Settings</h1>
<h1><?php echo $this->escape($name); ?> <?php if ($sandbox): ?>Sandbox<?php endif;?> OAuth2 Settings</h1>
<form
autocomplete="off"
@ -431,23 +453,22 @@ $auth = $this->getParam('auth', []);
data-failure="alert"
data-failure-param-alert-text="Failed to update project OAuth2 settings"
data-failure-param-alert-classname="error">
<input style="display: none" type="text" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */ ?>
<input style="display: none" type="password" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */ ?>
<input style="display: none" type="text" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */?>
<input style="display: none" type="password" /> <?php /** Disabling Chrone Autofill @see https://stackoverflow.com/a/15917221/2299554 */?>
<input name="provider" id="provider<?php echo $this->escape(ucfirst($provider)); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($provider); ?>">
<?php if(!$form): ?>
<?php if (!$form): ?>
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">App ID</label>
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}}">
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}}">
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret">App Secret</label>
<input name="secret" data-forms-show-secret id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="password" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<input name="secret" data-forms-show-secret id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="password" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<?php else: ?>
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid">Bundle ID <span class="tooltip" data-tooltip="Attribute internal display name"><i class="icon-info-circled"></i></span></label>
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}}" placeholder="com.company.appname" />
<input name="secret" data-forms-oauth-apple id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="hidden" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
<input name="appId" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}}" placeholder="com.company.appname" />
<input name="secret" data-forms-oauth-apple id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="hidden" autocomplete="off" data-ls-bind="{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
<?php endif; ?>
<div class="info row thin margin-bottom margin-top">
@ -469,21 +490,21 @@ $auth = $this->getParam('auth', []);
<div class="box padding-small margin-bottom">
<span data-ls-if="
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} &&
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}} &&
{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<button class="switch on pull-end" data-ls-ui-trigger="provider-update-<?php echo $provider; ?>"></button>
</span>
<span data-ls-if="
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} ||
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
!{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Appid}} ||
!{{console-project.provider<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<button class="switch pull-end" data-ls-ui-trigger="provider-update-<?php echo $this->escape($provider); ?>"></button>
</span>
<img src="/images/users/<?php echo $this->escape(strtolower($provider)); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo $this->escape(ucfirst($provider)); ?> Logo" class="pull-start provider margin-end" />
<span class="text-size-small">
<?php echo $this->escape($name); ?> <?php if($sandbox): ?><span class="text-size-xs text-fade">sandbox</span><?php endif; ?> <?php if($beta): ?><span class="text-size-xs text-fade">beta</span><?php endif; ?>
<?php echo $this->escape($name); ?> <?php if ($sandbox): ?><span class="text-size-xs text-fade">sandbox</span><?php endif;?> <?php if ($beta): ?><span class="text-size-xs text-fade">beta</span><?php endif;?>
</span>
<p class="margin-bottom-no text-one-liner text-size-small">
@ -491,7 +512,7 @@ $auth = $this->getParam('auth', []);
</p>
</div>
</li>
<?php endforeach; ?>
<?php endforeach;?>
</ul>
</div>
</li>

View file

@ -17,8 +17,8 @@
</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>
<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">
@ -32,7 +32,7 @@
<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>Overview</h2>
<div class="row responsive margin-top-negative">
<div class="col span-8 margin-bottom-large">
<label>&nbsp;</label>
@ -146,10 +146,10 @@
<input name="teamId" id="team-teamId" type="hidden" data-ls-bind="{{team.$id}}">
<input name="url" type="hidden" data-ls-bind="{{env.ENDPOINT}}" />
<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" maxlength="128" />
@ -232,7 +232,7 @@
</div>
</div>
</li>
</ul>
</div>
</div>

View file

@ -58,31 +58,31 @@ $events = array_keys($this->getParam('events', []));
<label data-ls-attrs="for=name-{{webhook.$id}}">Name</label>
<input type="text" class="full-width" data-ls-attrs="id=name-{{webhook.$id}}" name="name" required autocomplete="off" data-ls-bind="{{webhook.name}}" maxlength="128" />
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
<input type="url" class="full-width" data-ls-attrs="id=url-{{webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{webhook.url}}" />
<section data-forms-select-all>
<label data-ls-attrs="for=events-{{webhook.$id}}">Events</label>
<div class="row responsive thin">
<?php foreach ($events as $i => $event) : ?>
<?php foreach ($events as $i => $event): ?>
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
<input type="checkbox" name="events" data-ls-bind="{{webhook.events}}" id="update-<?php echo $event; ?>" value="<?php echo $event; ?>" />
&nbsp;
<label class="inline" for="update-<?php echo $event; ?>"><?php echo $event; ?></label>
</div>
<?php if (($i + 1) % 2 === 0) : ?>
<?php if (($i + 1) % 2 === 0): ?>
</div>
<div class="row responsive thin">
<?php endif; ?>
<?php endforeach; ?>
<?php endif;?>
<?php endforeach;?>
</div>
</section>
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
<input type="url" class="full-width" data-ls-attrs="id=url-{{webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{webhook.url}}" />
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
<i class="icon-plus pull-end margin-top-tiny"></i>
<i class="icon-minus pull-end margin-top-tiny"></i>
<h2 class="margin-bottom">
Advanced Options
<small class="text-size-small">(optional)</small>
@ -90,7 +90,7 @@ $events = array_keys($this->getParam('events', []));
<label data-ls-attrs="for=security-{{task.$id}}" class="margin-bottom-small">
<div class="margin-bottom-small text-bold">SSL / TLS (Certificate verification)</div>
<input name="security" type="radio" required data-ls-attrs="id=secure-yes-{{webhook.$id}}" data-ls-bind="{{webhook.security}}" value="true" data-cast-to="boolean" /> &nbsp; <span>Enabled</span> &nbsp;
<input name="security" type="radio" required data-ls-attrs="id=secure-no-{{webhook.$id}}" data-ls-bind="{{webhook.security}}" value="false" data-cast-to="boolean" /> &nbsp; <span>Disabled</span> &nbsp;
</label>
@ -180,31 +180,31 @@ $events = array_keys($this->getParam('events', []));
<label for="name">Name</label>
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" maxlength="128" />
<label for="url">POST URL</label>
<input type="url" class="full-width" id="url" name="url" required autocomplete="off" placeholder="https://example.com/callback" />
<section data-forms-select-all>
<label for="events">Events</label>
<div class="row responsive thin">
<?php foreach ($events as $i => $event) : ?>
<?php foreach ($events as $i => $event): ?>
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
<input type="checkbox" name="events" id="add-<?php echo $event; ?>" value="<?php echo $event; ?>" />
&nbsp;
<label class="inline" for="add-<?php echo $event; ?>"><?php echo $event; ?></label>
</div>
<?php if (($i + 1) % 2 === 0) : ?>
<?php if (($i + 1) % 2 === 0): ?>
</div>
<div class="row responsive thin">
<?php endif; ?>
<?php endif;?>
<?php endforeach; ?>
<?php endforeach;?>
</div>
</section>
<label for="url">POST URL</label>
<input type="url" class="full-width" id="url" name="url" required autocomplete="off" placeholder="https://example.com/callback" />
<div class="margin-bottom toggle" data-ls-ui-open data-button-aria="Advanced Options">
<i class="icon-plus pull-end margin-top-tiny"></i>
<i class="icon-minus pull-end margin-top-tiny"></i>
<h2 class="margin-bottom">
Advanced Options
<small class="text-size-small">(optional)</small>
@ -212,7 +212,7 @@ $events = array_keys($this->getParam('events', []));
<label data-ls-attrs="for=security-{{task.$id}}" class="margin-bottom-small">
<div class="margin-bottom-small text-bold">SSL / TLS (Certificate verification)</div>
<input name="security" type="radio" required data-ls-attrs="id=secure-yes" checked="checked" value="1" /> &nbsp; <span>Enabled</span> &nbsp;
<input name="security" type="radio" required data-ls-attrs="id=secure-no" value="0" /> &nbsp; <span>Disabled</span> &nbsp;
</label>

View file

@ -37,6 +37,7 @@ $root = ($this->getParam('root') !== 'disabled');
<?php if($root): ?>
<p>Please create your root account</p>
<?php endif; ?>
<input name="userId" type="hidden" value="unique()">
<label>Name</label>
<input name="name" type="text" autocomplete="name" placeholder="" required maxlength="128">

View file

@ -3,6 +3,7 @@
use Appwrite\Resque\Worker;
use Utopia\CLI\Console;
use Utopia\Database\Document;
use Utopia\Database\Validator\Authorization;
require_once __DIR__.'/../workers.php';
@ -21,6 +22,8 @@ class DatabaseV1 extends Worker
{
$projectId = $this->args['projectId'] ?? '';
$type = $this->args['type'] ?? '';
Authorization::disable();
switch (strval($type)) {
case CREATE_TYPE_ATTRIBUTE:
@ -49,6 +52,7 @@ class DatabaseV1 extends Worker
break;
}
Authorization::reset();
}
public function shutdown(): void

View file

@ -2,6 +2,7 @@
use Appwrite\Event\Event;
use Appwrite\Resque\Worker;
use Appwrite\Stats\Stats;
use Appwrite\Utopia\Response\Model\Execution;
use Cron\CronExpression;
use Swoole\Runtime;
@ -134,8 +135,6 @@ class FunctionsV1 extends Worker
public function run(): void
{
global $register;
$projectId = $this->args['projectId'] ?? '';
$functionId = $this->args['functionId'] ?? '';
$webhooks = $this->args['webhooks'] ?? [];
@ -279,7 +278,7 @@ class FunctionsV1 extends Worker
*/
public function execute(string $trigger, string $projectId, string $executionId, Database $database, Document $function, string $event = '', string $eventData = '', string $data = '', array $webhooks = [], string $userId = '', string $jwt = ''): void
{
global $list;
global $list, $register;
$runtimes = Config::getParam('runtimes');
@ -477,21 +476,22 @@ class FunctionsV1 extends Worker
->setParam('eventData', $execution->getArrayCopy(array_keys($executionModel->getRules())));
$executionUpdate->trigger();
$usage = new Event('v1-usage', 'UsageV1');
$usage
->setParam('projectId', $projectId)
->setParam('functionId', $function->getId())
->setParam('functionExecution', 1)
->setParam('functionStatus', $functionStatus)
->setParam('functionExecutionTime', $executionTime * 1000) // ms
->setParam('networkRequestSize', 0)
->setParam('networkResponseSize', 0)
;
if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$usage->trigger();
$statsd = $register->get('statsd');
$usage = new Stats($statsd);
$usage
->setParam('projectId', $projectId)
->setParam('functionId', $function->getId())
->setParam('functionExecution', 1)
->setParam('functionStatus', $functionStatus)
->setParam('functionExecutionTime', $executionTime * 1000) // ms
->setParam('networkRequestSize', 0)
->setParam('networkResponseSize', 0)
->submit()
;
}
$this->cleanup();

View file

@ -1,71 +0,0 @@
<?php
use Appwrite\Resque\Worker;
use Utopia\App;
use Utopia\CLI\Console;
require_once __DIR__.'/../workers.php';
Console::title('Usage V1 Worker');
Console::success(APP_NAME.' usage worker v1 has started');
class UsageV1 extends Worker
{
/**
* @var array
*/
public $args = [];
public function init(): void
{
}
public function run(): void
{
global $register;
/** @var \Domnikl\Statsd\Client $statsd */
$statsd = $register->get('statsd', true);
$projectId = $this->args['projectId'] ?? '';
$storage = $this->args['storage'] ?? 0;
$networkRequestSize = $this->args['networkRequestSize'] ?? 0;
$networkResponseSize = $this->args['networkResponseSize'] ?? 0;
$httpMethod = $this->args['httpMethod'] ?? '';
$httpRequest = $this->args['httpRequest'] ?? 0;
$functionId = $this->args['functionId'] ?? '';
$functionExecution = $this->args['functionExecution'] ?? 0;
$functionExecutionTime = $this->args['functionExecutionTime'] ?? 0;
$functionStatus = $this->args['functionStatus'] ?? '';
$tags = ",project={$projectId},version=".App::getEnv('_APP_VERSION', 'UNKNOWN');
// the global namespace is prepended to every key (optional)
$statsd->setNamespace('appwrite.usage');
if($httpRequest >= 1) {
$statsd->increment('requests.all'.$tags.',method='.\strtolower($httpMethod));
}
if($functionExecution >= 1) {
$statsd->increment('executions.all'.$tags.',functionId='.$functionId.',functionStatus='.$functionStatus);
$statsd->count('executions.time'.$tags.',functionId='.$functionId, $functionExecutionTime);
}
$statsd->count('network.inbound'.$tags, $networkRequestSize);
$statsd->count('network.outbound'.$tags, $networkResponseSize);
$statsd->count('network.all'.$tags, $networkRequestSize + $networkResponseSize);
if($storage >= 1) {
$statsd->count('storage.all'.$tags, $storage);
}
}
public function shutdown(): void
{
}
}

View file

@ -1,10 +0,0 @@
#!/bin/sh
if [ -z "$_APP_REDIS_USER" ] && [ -z "$_APP_REDIS_PASS" ]
then
REDIS_BACKEND="${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
else
REDIS_BACKEND="redis://${_APP_REDIS_USER}:${_APP_REDIS_PASS}@${_APP_REDIS_HOST}:${_APP_REDIS_PORT}"
fi
INTERVAL=1 QUEUE='v1-usage' APP_INCLUDE='/usr/src/code/app/workers/usage.php' php /usr/src/code/vendor/bin/resque -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php

2
composer.lock generated
View file

@ -6278,5 +6278,5 @@
"platform-overrides": {
"php": "8.0"
},
"plugin-api-version": "2.0.0"
"plugin-api-version": "2.1.0"
}

View file

@ -121,26 +121,6 @@ services:
- _APP_FUNCTIONS_MEMORY
- _APP_FUNCTIONS_MEMORY_SWAP
- _APP_FUNCTIONS_RUNTIMES
appwrite-worker-usage:
entrypoint: worker-usage
container_name: appwrite-worker-usage
build:
context: .
networks:
- appwrite
volumes:
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
depends_on:
- redis
- telegraf
environment:
- _APP_ENV
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
- _APP_STATSD_HOST
- _APP_STATSD_PORT
@ -308,6 +288,8 @@ services:
- _APP_FUNCTIONS_MEMORY
- _APP_FUNCTIONS_MEMORY_SWAP
- _APP_USAGE_STATS
- _APP_STATSD_HOST
- _APP_STATSD_PORT
- DOCKERHUB_PULL_USERNAME
- DOCKERHUB_PULL_PASSWORD

View file

@ -0,0 +1 @@
Get a team member by the membership unique id. All team members have read access for this resource.

View file

@ -44,6 +44,7 @@ const configApp = {
'public/scripts/views/forms/code.js',
'public/scripts/views/forms/color.js',
'public/scripts/views/forms/copy.js',
'public/scripts/views/forms/custom-id.js',
'public/scripts/views/forms/document.js',
'public/scripts/views/forms/document-preview.js',
'public/scripts/views/forms/filter.js',

20
package-lock.json generated
View file

@ -1,7 +1,7 @@
{
"name": "appwrite-server",
"version": "0.1.0",
"lockfileVersion": 1,
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
@ -8489,6 +8489,15 @@
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@ -8517,15 +8526,6 @@
}
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",

View file

@ -5,9 +5,11 @@ function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e)
function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);}
step((generator=generator.apply(thisArg,_arguments||[])).next());});}
class AppwriteException extends Error{constructor(message,code=0,response=''){super(message);this.name='AppwriteException';this.message=message;this.code=code;this.response=response;}}
class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:2.1.0','X-Appwrite-Response-Format':'0.9.0',};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:2.1.0','X-Appwrite-Response-Format':'0.9.0',};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(userId,email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');}
let path='/account';let payload={};if(typeof email!=='undefined'){payload['email']=email;}
let path='/account';let payload={};if(typeof userId!=='undefined'){payload['userId']=userId;}
if(typeof email!=='undefined'){payload['email']=email;}
if(typeof password!=='undefined'){payload['password']=password;}
if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),delete:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),updateEmail:(email,password)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
@ -90,10 +92,12 @@ return uri;}};this.database={listCollections:(search,limit,offset,orderType)=>__
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createCollection:(name,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createCollection:(collectionId,name,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof read==='undefined'){throw new AppwriteException('Missing required parameter: "read"');}
if(typeof write==='undefined'){throw new AppwriteException('Missing required parameter: "write"');}
let path='/database/collections';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/database/collections';let payload={};if(typeof collectionId!=='undefined'){payload['collectionId']=collectionId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getCollection:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
@ -104,13 +108,59 @@ if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'content-type':'application/json',},payload);}),deleteCollection:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),listAttributes:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createAttribute:(collectionId,id,type,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof id==='undefined'){throw new AppwriteException('Missing required parameter: "id"');}
if(typeof type==='undefined'){throw new AppwriteException('Missing required parameter: "type"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createBooleanAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/boolean'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createEmailAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/email'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createFloatAttribute:(collectionId,attributeId,required,min,max,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/float'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof min!=='undefined'){payload['min']=min;}
if(typeof max!=='undefined'){payload['max']=max;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createIntegerAttribute:(collectionId,attributeId,required,min,max,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/integer'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof min!=='undefined'){payload['min']=min;}
if(typeof max!=='undefined'){payload['max']=max;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createIpAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/ip'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createStringAttribute:(collectionId,attributeId,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof size==='undefined'){throw new AppwriteException('Missing required parameter: "size"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};if(typeof id!=='undefined'){payload['id']=id;}
if(typeof type!=='undefined'){payload['type']=type;}
let path='/database/collections/{collectionId}/attributes/string'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof size!=='undefined'){payload['size']=size;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createUrlAttribute:(collectionId,attributeId,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof size==='undefined'){throw new AppwriteException('Missing required parameter: "size"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/url'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof size!=='undefined'){payload['size']=size;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
@ -125,9 +175,11 @@ if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderAttributes!=='undefined'){payload['orderAttributes']=orderAttributes;}
if(typeof orderTypes!=='undefined'){payload['orderTypes']=orderTypes;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createDocument:(collectionId,data,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createDocument:(collectionId,documentId,data,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof documentId==='undefined'){throw new AppwriteException('Missing required parameter: "documentId"');}
if(typeof data==='undefined'){throw new AppwriteException('Missing required parameter: "data"');}
let path='/database/collections/{collectionId}/documents'.replace('{collectionId}',collectionId);let payload={};if(typeof data!=='undefined'){payload['data']=data;}
let path='/database/collections/{collectionId}/documents'.replace('{collectionId}',collectionId);let payload={};if(typeof documentId!=='undefined'){payload['documentId']=documentId;}
if(typeof data!=='undefined'){payload['data']=data;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getDocument:(collectionId,documentId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
@ -157,10 +209,12 @@ let path='/database/collections/{collectionId}/indexes/{indexId}'.replace('{coll
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,execute,runtime,vars,events,schedule,timeout)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(functionId,name,execute,runtime,vars,events,schedule,timeout)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof execute==='undefined'){throw new AppwriteException('Missing required parameter: "execute"');}
if(typeof runtime==='undefined'){throw new AppwriteException('Missing required parameter: "runtime"');}
let path='/functions';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/functions';let payload={};if(typeof functionId!=='undefined'){payload['functionId']=functionId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof execute!=='undefined'){payload['execute']=execute;}
if(typeof runtime!=='undefined'){payload['runtime']=runtime;}
if(typeof vars!=='undefined'){payload['vars']=vars;}
@ -204,13 +258,15 @@ let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionI
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionId).replace('{tagId}',tagId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),getUsage:(functionId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
let path='/functions/{functionId}/usage'.replace('{functionId}',functionId);let payload={};if(typeof range!=='undefined'){payload['range']=range;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.health={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/health';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getAntiVirus:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/anti-virus';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCache:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/cache';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getDB:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/db';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueCertificates:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/certificates';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueFunctions:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/functions';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueLogs:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/logs';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueTasks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/tasks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueUsage:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/usage';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueWebhooks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/webhooks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getStorageLocal:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/storage/local';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getTime:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/time';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.locale={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getContinents:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/continents';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountries:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesEU:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/eu';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesPhones:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/phones';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCurrencies:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/currencies';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getLanguages:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/languages';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.projects={list:(search,limit,offset,orderType)=>__awaiter(this,void 0,void 0,function*(){let path='/projects';let payload={};if(typeof search!=='undefined'){payload['search']=search;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.health={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/health';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getAntiVirus:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/anti-virus';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCache:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/cache';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getDB:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/db';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueCertificates:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/certificates';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueFunctions:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/functions';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueLogs:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/logs';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueUsage:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/usage';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueWebhooks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/webhooks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getStorageLocal:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/storage/local';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getTime:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/time';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.locale={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getContinents:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/continents';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountries:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesEU:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/eu';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesPhones:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/phones';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCurrencies:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/currencies';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getLanguages:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/languages';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.projects={list:(search,limit,offset,orderType)=>__awaiter(this,void 0,void 0,function*(){let path='/projects';let payload={};if(typeof search!=='undefined'){payload['search']=search;}
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,teamId,description,logo,url,legalName,legalCountry,legalState,legalCity,legalAddress,legalTaxId)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(projectId,name,teamId,description,logo,url,legalName,legalCountry,legalState,legalCity,legalAddress,legalTaxId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
let path='/projects';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/projects';let payload={};if(typeof projectId!=='undefined'){payload['projectId']=projectId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof teamId!=='undefined'){payload['teamId']=teamId;}
if(typeof description!=='undefined'){payload['description']=description;}
if(typeof logo!=='undefined'){payload['logo']=logo;}
@ -297,47 +353,10 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'
if(typeof platformId==='undefined'){throw new AppwriteException('Missing required parameter: "platformId"');}
let path='/projects/{projectId}/platforms/{platformId}'.replace('{projectId}',projectId).replace('{platformId}',platformId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),updateServiceStatus:(projectId,service,status)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof service==='undefined'){throw new AppwriteException('Missing required parameter: "service"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
let path='/projects/{projectId}/service'.replace('{projectId}',projectId);let payload={};if(typeof service!=='undefined'){payload['service']=service;}
if(typeof status!=='undefined'){payload['status']=status;}
const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),listTasks:(projectId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/tasks'.replace('{projectId}',projectId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createTask:(projectId,name,status,schedule,security,httpMethod,httpUrl,httpHeaders,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
if(typeof schedule==='undefined'){throw new AppwriteException('Missing required parameter: "schedule"');}
if(typeof security==='undefined'){throw new AppwriteException('Missing required parameter: "security"');}
if(typeof httpMethod==='undefined'){throw new AppwriteException('Missing required parameter: "httpMethod"');}
if(typeof httpUrl==='undefined'){throw new AppwriteException('Missing required parameter: "httpUrl"');}
let path='/projects/{projectId}/tasks'.replace('{projectId}',projectId);let payload={};if(typeof name!=='undefined'){payload['name']=name;}
if(typeof status!=='undefined'){payload['status']=status;}
if(typeof schedule!=='undefined'){payload['schedule']=schedule;}
if(typeof security!=='undefined'){payload['security']=security;}
if(typeof httpMethod!=='undefined'){payload['httpMethod']=httpMethod;}
if(typeof httpUrl!=='undefined'){payload['httpUrl']=httpUrl;}
if(typeof httpHeaders!=='undefined'){payload['httpHeaders']=httpHeaders;}
if(typeof httpUser!=='undefined'){payload['httpUser']=httpUser;}
if(typeof httpPass!=='undefined'){payload['httpPass']=httpPass;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getTask:(projectId,taskId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateTask:(projectId,taskId,name,status,schedule,security,httpMethod,httpUrl,httpHeaders,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
if(typeof schedule==='undefined'){throw new AppwriteException('Missing required parameter: "schedule"');}
if(typeof security==='undefined'){throw new AppwriteException('Missing required parameter: "security"');}
if(typeof httpMethod==='undefined'){throw new AppwriteException('Missing required parameter: "httpMethod"');}
if(typeof httpUrl==='undefined'){throw new AppwriteException('Missing required parameter: "httpUrl"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};if(typeof name!=='undefined'){payload['name']=name;}
if(typeof status!=='undefined'){payload['status']=status;}
if(typeof schedule!=='undefined'){payload['schedule']=schedule;}
if(typeof security!=='undefined'){payload['security']=security;}
if(typeof httpMethod!=='undefined'){payload['httpMethod']=httpMethod;}
if(typeof httpUrl!=='undefined'){payload['httpUrl']=httpUrl;}
if(typeof httpHeaders!=='undefined'){payload['httpHeaders']=httpHeaders;}
if(typeof httpUser!=='undefined'){payload['httpUser']=httpUser;}
if(typeof httpPass!=='undefined'){payload['httpPass']=httpPass;}
const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'content-type':'application/json',},payload);}),deleteTask:(projectId,taskId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),getUsage:(projectId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),getUsage:(projectId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/usage'.replace('{projectId}',projectId);let payload={};if(typeof range!=='undefined'){payload['range']=range;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),listWebhooks:(projectId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/webhooks'.replace('{projectId}',projectId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createWebhook:(projectId,name,events,url,security,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
@ -371,8 +390,10 @@ let path='/projects/{projectId}/webhooks/{webhookId}'.replace('{projectId}',proj
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createFile:(file,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof file==='undefined'){throw new AppwriteException('Missing required parameter: "file"');}
let path='/storage/files';let payload={};if(typeof file!=='undefined'){payload['file']=file;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createFile:(fileId,file,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
if(typeof file==='undefined'){throw new AppwriteException('Missing required parameter: "file"');}
let path='/storage/files';let payload={};if(typeof fileId!=='undefined'){payload['fileId']=fileId;}
if(typeof file!=='undefined'){payload['file']=file;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}),getFile:(fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
@ -403,8 +424,10 @@ return uri;}};this.teams={list:(search,limit,offset,orderType)=>__awaiter(this,v
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
let path='/teams';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(teamId,name,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
let path='/teams';let payload={};if(typeof teamId!=='undefined'){payload['teamId']=teamId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof roles!=='undefined'){payload['roles']=roles;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),get:(teamId)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace('{teamId}',teamId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),update:(teamId,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
@ -424,7 +447,9 @@ let path='/teams/{teamId}/memberships'.replace('{teamId}',teamId);let payload={}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof roles!=='undefined'){payload['roles']=roles;}
if(typeof url!=='undefined'){payload['url']=url;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),updateMembershipRoles:(teamId,membershipId,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getMembership:(teamId,membershipId)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof membershipId==='undefined'){throw new AppwriteException('Missing required parameter: "membershipId"');}
let path='/teams/{teamId}/memberships/{membershipId}'.replace('{teamId}',teamId).replace('{membershipId}',membershipId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateMembershipRoles:(teamId,membershipId,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof membershipId==='undefined'){throw new AppwriteException('Missing required parameter: "membershipId"');}
if(typeof roles==='undefined'){throw new AppwriteException('Missing required parameter: "roles"');}
let path='/teams/{teamId}/memberships/{membershipId}'.replace('{teamId}',teamId).replace('{membershipId}',membershipId);let payload={};if(typeof roles!=='undefined'){payload['roles']=roles;}
@ -440,9 +465,11 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(userId,email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');}
let path='/users';let payload={};if(typeof email!=='undefined'){payload['email']=email;}
let path='/users';let payload={};if(typeof userId!=='undefined'){payload['userId']=userId;}
if(typeof email!=='undefined'){payload['email']=email;}
if(typeof password!=='undefined'){payload['password']=password;}
if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),get:(userId)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
@ -2345,7 +2372,21 @@ code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addE
function syncA(){element.value=picker.value;update();}
function syncB(){picker.value=element.value;}
element.parentNode.insertBefore(preview,element);update();syncB();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-copy",controller:function(element,alerts,document,window){var button=window.document.createElement("i");button.type="button";button.className="icon-docs note copy";button.style.cursor="pointer";element.parentNode.insertBefore(button,element.nextSibling);var copy=function(event){let disabled=element.disabled;element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
element.disabled=disabled;element.blur();alerts.add({text:"Copied to clipboard",class:""},3000);};button.addEventListener("click",copy);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document",controller:function(element,container,search){var formsDocument=(element.dataset["formsDocument"]||'');var searchButton=(element.dataset["search"]||0);let path=container.scope(searchButton);element.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent(formsDocument,{bubbles:false,cancelable:true}));});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document-preview",controller:function(element,container,search){element.addEventListener('change',function(){console.log(element.value);});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-filter",controller:function(document,container,expression,element,form,di){let name=element.dataset["formsFilter"]||"";let events=element.dataset["event"]||"";let serialize=function(obj,prefix){let str=[],p;for(p in obj){if(obj.hasOwnProperty(p)){let k=prefix?prefix+"["+p+"]":p,v=obj[p];if(v===""){continue;}
element.disabled=disabled;element.blur();alerts.add({text:"Copied to clipboard",class:""},3000);};button.addEventListener("click",copy);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-custom-id",controller:function(element,sdk,console,window){let prevData="";let idType=element.getAttribute('data-id-type');let disableSwitch=element.getAttribute('data-disable-switch');const div=window.document.createElement("div");if(disableSwitch!=="true"){div.className="input-copy";}
const button=window.document.createElement("i");button.type="button";button.style.cursor="pointer";const writer=window.document.createElement("input");writer.type="text";writer.setAttribute("maxlength",element.getAttribute("maxlength"));const placeholder=element.getAttribute("placeholder");if(placeholder){writer.setAttribute("placeholder",placeholder);}
const info=window.document.createElement("div");info.className="text-fade text-size-xs margin-top-negative-small margin-bottom";div.appendChild(writer);if(disableSwitch!=="true"){div.appendChild(button);}
element.parentNode.insertBefore(div,element);element.parentNode.insertBefore(info,div.nextSibling);const switchType=function(event){if(idType=="custom"){idType="auto";setIdType(idType);}else{idType="custom";setIdType(idType);}}
const validate=function(event){const[service,method]=element.dataset["validator"].split('.');const value=event.target.value;if(value.length<1){event.target.setCustomValidity("ID is required");}else{switch(service){case'projects':setValidity(console[service][method](value),event.target);break;default:setValidity(sdk[service][method](value),event.target);}}}
const setValidity=async function(promise,target){try{await promise;target.setCustomValidity("ID already exists");}catch(e){target.setCustomValidity("");}}
const setIdType=function(idType){if(idType=="custom"){element.setAttribute("data-id-type",idType);info.innerHTML="Allowed Characters A-Z, a-z, 0-9, and non-leading underscore";if(prevData==='auto-generated'){prevData=""}
writer.setAttribute("value",prevData);writer.value=prevData;element.value=prevData;writer.removeAttribute("disabled");writer.focus();writer.addEventListener('blur',validate);}else{idType='auto'
element.setAttribute("data-id-type",idType);info.innerHTML="Appwrite will generate a unique ID";prevData=writer.value;writer.setAttribute("disabled",true);writer.setAttribute("value","auto-generated");writer.value="auto-generated";element.value='unique()';}
button.className=idType=="custom"?"icon-shuffle copy":"icon-edit copy";}
const syncEditorWithID=function(event){if(element.value!=='unique()'||idType!='auto'){writer.value=element.value;}
if(idType=='auto'){element.value='unique()';}}
const keypress=function(e){const key=e.which||e.keyCode;const ZERO=48;const NINE=57;const SMALL_A=97;const SMALL_Z=122;const CAPITAL_A=65;const CAPITAL_Z=90;const UNDERSCORE=95;const isNotValidDigit=key<ZERO||key>NINE;const isNotValidSmallAlphabet=key<SMALL_A||key>SMALL_Z;const isNotValidCapitalAlphabet=key<CAPITAL_A||key>CAPITAL_Z;if(key==UNDERSCORE&&e.target.value.length==0){e.preventDefault();}
if(key!=UNDERSCORE&&isNotValidDigit&&isNotValidSmallAlphabet&&isNotValidCapitalAlphabet){e.preventDefault();}}
syncEditorWithID();setIdType(idType);writer.addEventListener("change",function(event){element.value=writer.value;});writer.form.addEventListener('reset',function(event){const resetEvent=new Event('reset');element.dispatchEvent(resetEvent);});element.addEventListener('reset',function(event){idType=element.getAttribute('data-id-type');setIdType(idType);});writer.addEventListener('keypress',keypress);button.addEventListener("click",switchType);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document",controller:function(element,container,search){var formsDocument=(element.dataset["formsDocument"]||'');var searchButton=(element.dataset["search"]||0);let path=container.scope(searchButton);element.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent(formsDocument,{bubbles:false,cancelable:true}));});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document-preview",controller:function(element,container,search){element.addEventListener('change',function(){console.log(element.value);});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-filter",controller:function(document,container,expression,element,form,di){let name=element.dataset["formsFilter"]||"";let events=element.dataset["event"]||"";let serialize=function(obj,prefix){let str=[],p;for(p in obj){if(obj.hasOwnProperty(p)){let k=prefix?prefix+"["+p+"]":p,v=obj[p];if(v===""){continue;}
str.push(v!==null&&typeof v==="object"?serialize(v,k):encodeURIComponent(k)+"="+encodeURIComponent(v));}}
return str.join("&");};let parse=function(filter){if(filter===""){return null;}
let operatorsMap=["!=",">=","<=","=",">","<"];let operator=null;for(let key=0;key<operatorsMap.length;key++){if(filter.indexOf(operatorsMap[key])>-1){operator=operatorsMap[key];}}
@ -2386,7 +2427,7 @@ element.classList.add('scroll-to-bottom')}
else{element.classList.remove('scroll-to-bottom')
element.classList.add('scroll-to-top')}
position=direction;let current=Math.ceil(direction/window.innerHeight);element.setAttribute('data-views-total',Math.ceil(element.scrollHeight/window.innerHeight));element.setAttribute('data-views-current',current);if(element.scrollHeight<=(direction+element.offsetHeight+300)&&direction>0){element.classList.add('scroll-end')}
else{element.classList.remove('scroll-end')}};window.addEventListener('scroll',check,false);window.addEventListener('resize',check,false);check();}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-setup",controller:function(element,console,form,alerts,router){element.addEventListener("submit",function(event){event.preventDefault();let loaderId=alerts.add({text:'Creating new project...',class:""},0);let formData=form.toJson(element);formData["name"]=formData["name"]||(element.dataset["defaultName"]||"");console.teams.create(formData["name"]||"").then(function(data){let team=data["$id"];formData=JSON.parse(JSON.stringify(formData).replace(new RegExp("{{teamId}}","g"),team));console.projects.create(formData["name"],team).then(function(project){alerts.remove(loaderId);window.location.href="/console/home?project="+project["$id"];},function(){throw new Error("Failed to setup project");});},function(){throw new Error("Setup failed creating project team");});});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-switch",controller:function(element,router,document){let check=function(c){if(!element.value){return;}
else{element.classList.remove('scroll-end')}};window.addEventListener('scroll',check,false);window.addEventListener('resize',check,false);check();}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-setup",controller:function(element,console,form,alerts,router){element.addEventListener("submit",function(event){event.preventDefault();let loaderId=alerts.add({text:'Creating new project...',class:""},0);let formData=form.toJson(element);formData["name"]=formData["name"]||(element.dataset["defaultName"]||"");console.teams.create('unique()',formData["name"]||"").then(function(data){let team=data["$id"];formData=JSON.parse(JSON.stringify(formData).replace(new RegExp("{{teamId}}","g"),team));console.projects.create(formData["projectId"],formData["name"],team).then(function(project){alerts.remove(loaderId);window.location.href="/console/home?project="+project["$id"];},function(){throw new Error("Failed to setup project");});},function(){throw new Error("Setup failed creating project team");});});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-switch",controller:function(element,router,document){let check=function(c){if(!element.value){return;}
if(element.value===router.params.project){return;}
return router.change("/console/home?project="+element.value);};element.addEventListener("change",function(){check();});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-general-theme",controller:function(element,router,document){let toggle=function(c){if(document.body.classList.contains('theme-light')){document.body.classList.remove('theme-light');document.body.classList.add('theme-dark');window.localStorage.setItem('user-theme','theme-dark')}
else{document.body.classList.remove('theme-dark');document.body.classList.add('theme-light');window.localStorage.setItem('user-theme','theme-light')}};element.addEventListener("click",function(){toggle();});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-version",controller:function(alerts,env,cookie){let cookieName="version-update-"+env.VERSION.replace(/\./g,"_");if(!cookie.get(cookieName)){var xhr=new XMLHttpRequest();xhr.open('GET','/console/version',true);xhr.onload=function(){if(this.readyState==4&&this.status==200){let data=JSON.parse(this.responseText);let text='Appwrite version '+data.version+' is avaliable, check the';if(isNewerVersion(env.VERSION,data.version)){alerts.add({text:text,class:"success",link:"https://github.com/appwrite/appwrite/releases",label:'release notes',callback:function(){cookie.set(cookieName,"true",365*10);}},0);}}};xhr.send(null);function isNewerVersion(oldVer,newVer){const oldParts=oldVer.split('.')
@ -2403,7 +2444,7 @@ if(selected&&list[selected].dataset["selected"]){let parent=element.querySelecto
if(!buttonAlias){buttonElements.forEach(button=>{button.innerText=buttonText;button.className=buttonClass;button.type=buttonElement;if(buttonIcon){let iconElement=document.createElement("i");iconElement.className=buttonIcon;button.insertBefore(iconElement,button.firstChild);}});}
if(buttonEvent){buttonElements.forEach(button=>{button.addEventListener("click",function(){document.dispatchEvent(new CustomEvent(buttonEvent,{bubbles:false,cancelable:true}));});});}
element.classList.add("modal");if(!buttonAlias&&!buttonHide){buttonElements.forEach(button=>{element.parentNode.insertBefore(button,element);});}
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'&&!element.disabled){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
if(openEvent){document.addEventListener(openEvent,open);}
buttonElements.forEach(button=>{button.addEventListener("click",open);});document.addEventListener("keydown",function(event){if(event.which===27){close();}});element.addEventListener("blur",close);let closeButtons=element.querySelectorAll("[data-ui-modal-close]");for(let i=0;i<closeButtons.length;i++){closeButtons[i].addEventListener("click",close);}
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonAria=element.dataset["buttonAria"]||"Open";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}

View file

@ -5,9 +5,11 @@ function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e)
function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);}
step((generator=generator.apply(thisArg,_arguments||[])).next());});}
class AppwriteException extends Error{constructor(message,code=0,response=''){super(message);this.name='AppwriteException';this.message=message;this.code=code;this.response=response;}}
class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:2.1.0','X-Appwrite-Response-Format':'0.9.0',};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
class Appwrite{constructor(){this.config={endpoint:'https://appwrite.io/v1',project:'',key:'',jwt:'',locale:'',mode:'',};this.headers={'x-sdk-version':'appwrite:web:2.1.0','X-Appwrite-Response-Format':'0.9.0',};this.account={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(userId,email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');}
let path='/account';let payload={};if(typeof email!=='undefined'){payload['email']=email;}
let path='/account';let payload={};if(typeof userId!=='undefined'){payload['userId']=userId;}
if(typeof email!=='undefined'){payload['email']=email;}
if(typeof password!=='undefined'){payload['password']=password;}
if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),delete:()=>__awaiter(this,void 0,void 0,function*(){let path='/account';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),updateEmail:(email,password)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
@ -90,10 +92,12 @@ return uri;}};this.database={listCollections:(search,limit,offset,orderType)=>__
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createCollection:(name,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createCollection:(collectionId,name,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof read==='undefined'){throw new AppwriteException('Missing required parameter: "read"');}
if(typeof write==='undefined'){throw new AppwriteException('Missing required parameter: "write"');}
let path='/database/collections';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/database/collections';let payload={};if(typeof collectionId!=='undefined'){payload['collectionId']=collectionId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getCollection:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
@ -104,13 +108,59 @@ if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'content-type':'application/json',},payload);}),deleteCollection:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),listAttributes:(collectionId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createAttribute:(collectionId,id,type,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof id==='undefined'){throw new AppwriteException('Missing required parameter: "id"');}
if(typeof type==='undefined'){throw new AppwriteException('Missing required parameter: "type"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createBooleanAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/boolean'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createEmailAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/email'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createFloatAttribute:(collectionId,attributeId,required,min,max,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/float'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof min!=='undefined'){payload['min']=min;}
if(typeof max!=='undefined'){payload['max']=max;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createIntegerAttribute:(collectionId,attributeId,required,min,max,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/integer'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof min!=='undefined'){payload['min']=min;}
if(typeof max!=='undefined'){payload['max']=max;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createIpAttribute:(collectionId,attributeId,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/ip'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createStringAttribute:(collectionId,attributeId,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof size==='undefined'){throw new AppwriteException('Missing required parameter: "size"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes'.replace('{collectionId}',collectionId);let payload={};if(typeof id!=='undefined'){payload['id']=id;}
if(typeof type!=='undefined'){payload['type']=type;}
let path='/database/collections/{collectionId}/attributes/string'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof size!=='undefined'){payload['size']=size;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
if(typeof array!=='undefined'){payload['array']=array;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),createUrlAttribute:(collectionId,attributeId,size,required,xdefault,array)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof attributeId==='undefined'){throw new AppwriteException('Missing required parameter: "attributeId"');}
if(typeof size==='undefined'){throw new AppwriteException('Missing required parameter: "size"');}
if(typeof required==='undefined'){throw new AppwriteException('Missing required parameter: "required"');}
let path='/database/collections/{collectionId}/attributes/url'.replace('{collectionId}',collectionId);let payload={};if(typeof attributeId!=='undefined'){payload['attributeId']=attributeId;}
if(typeof size!=='undefined'){payload['size']=size;}
if(typeof required!=='undefined'){payload['required']=required;}
if(typeof xdefault!=='undefined'){payload['xdefault']=xdefault;}
@ -125,9 +175,11 @@ if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderAttributes!=='undefined'){payload['orderAttributes']=orderAttributes;}
if(typeof orderTypes!=='undefined'){payload['orderTypes']=orderTypes;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createDocument:(collectionId,data,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createDocument:(collectionId,documentId,data,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
if(typeof documentId==='undefined'){throw new AppwriteException('Missing required parameter: "documentId"');}
if(typeof data==='undefined'){throw new AppwriteException('Missing required parameter: "data"');}
let path='/database/collections/{collectionId}/documents'.replace('{collectionId}',collectionId);let payload={};if(typeof data!=='undefined'){payload['data']=data;}
let path='/database/collections/{collectionId}/documents'.replace('{collectionId}',collectionId);let payload={};if(typeof documentId!=='undefined'){payload['documentId']=documentId;}
if(typeof data!=='undefined'){payload['data']=data;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getDocument:(collectionId,documentId)=>__awaiter(this,void 0,void 0,function*(){if(typeof collectionId==='undefined'){throw new AppwriteException('Missing required parameter: "collectionId"');}
@ -157,10 +209,12 @@ let path='/database/collections/{collectionId}/indexes/{indexId}'.replace('{coll
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,execute,runtime,vars,events,schedule,timeout)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(functionId,name,execute,runtime,vars,events,schedule,timeout)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof execute==='undefined'){throw new AppwriteException('Missing required parameter: "execute"');}
if(typeof runtime==='undefined'){throw new AppwriteException('Missing required parameter: "runtime"');}
let path='/functions';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/functions';let payload={};if(typeof functionId!=='undefined'){payload['functionId']=functionId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof execute!=='undefined'){payload['execute']=execute;}
if(typeof runtime!=='undefined'){payload['runtime']=runtime;}
if(typeof vars!=='undefined'){payload['vars']=vars;}
@ -204,13 +258,15 @@ let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionI
if(typeof tagId==='undefined'){throw new AppwriteException('Missing required parameter: "tagId"');}
let path='/functions/{functionId}/tags/{tagId}'.replace('{functionId}',functionId).replace('{tagId}',tagId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),getUsage:(functionId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof functionId==='undefined'){throw new AppwriteException('Missing required parameter: "functionId"');}
let path='/functions/{functionId}/usage'.replace('{functionId}',functionId);let payload={};if(typeof range!=='undefined'){payload['range']=range;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.health={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/health';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getAntiVirus:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/anti-virus';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCache:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/cache';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getDB:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/db';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueCertificates:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/certificates';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueFunctions:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/functions';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueLogs:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/logs';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueTasks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/tasks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueUsage:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/usage';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueWebhooks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/webhooks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getStorageLocal:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/storage/local';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getTime:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/time';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.locale={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getContinents:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/continents';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountries:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesEU:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/eu';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesPhones:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/phones';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCurrencies:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/currencies';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getLanguages:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/languages';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.projects={list:(search,limit,offset,orderType)=>__awaiter(this,void 0,void 0,function*(){let path='/projects';let payload={};if(typeof search!=='undefined'){payload['search']=search;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.health={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/health';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getAntiVirus:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/anti-virus';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCache:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/cache';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getDB:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/db';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueCertificates:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/certificates';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueFunctions:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/functions';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueLogs:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/logs';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueUsage:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/usage';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getQueueWebhooks:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/queue/webhooks';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getStorageLocal:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/storage/local';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getTime:()=>__awaiter(this,void 0,void 0,function*(){let path='/health/time';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.locale={get:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getContinents:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/continents';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountries:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesEU:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/eu';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCountriesPhones:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/countries/phones';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getCurrencies:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/currencies';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),getLanguages:()=>__awaiter(this,void 0,void 0,function*(){let path='/locale/languages';let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);})};this.projects={list:(search,limit,offset,orderType)=>__awaiter(this,void 0,void 0,function*(){let path='/projects';let payload={};if(typeof search!=='undefined'){payload['search']=search;}
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,teamId,description,logo,url,legalName,legalCountry,legalState,legalCity,legalAddress,legalTaxId)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(projectId,name,teamId,description,logo,url,legalName,legalCountry,legalState,legalCity,legalAddress,legalTaxId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
let path='/projects';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
let path='/projects';let payload={};if(typeof projectId!=='undefined'){payload['projectId']=projectId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof teamId!=='undefined'){payload['teamId']=teamId;}
if(typeof description!=='undefined'){payload['description']=description;}
if(typeof logo!=='undefined'){payload['logo']=logo;}
@ -297,47 +353,10 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'
if(typeof platformId==='undefined'){throw new AppwriteException('Missing required parameter: "platformId"');}
let path='/projects/{projectId}/platforms/{platformId}'.replace('{projectId}',projectId).replace('{platformId}',platformId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),updateServiceStatus:(projectId,service,status)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof service==='undefined'){throw new AppwriteException('Missing required parameter: "service"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
let path='/projects/{projectId}/service'.replace('{projectId}',projectId);let payload={};if(typeof service!=='undefined'){payload['service']=service;}
if(typeof status!=='undefined'){payload['status']=status;}
const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),listTasks:(projectId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/tasks'.replace('{projectId}',projectId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createTask:(projectId,name,status,schedule,security,httpMethod,httpUrl,httpHeaders,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
if(typeof schedule==='undefined'){throw new AppwriteException('Missing required parameter: "schedule"');}
if(typeof security==='undefined'){throw new AppwriteException('Missing required parameter: "security"');}
if(typeof httpMethod==='undefined'){throw new AppwriteException('Missing required parameter: "httpMethod"');}
if(typeof httpUrl==='undefined'){throw new AppwriteException('Missing required parameter: "httpUrl"');}
let path='/projects/{projectId}/tasks'.replace('{projectId}',projectId);let payload={};if(typeof name!=='undefined'){payload['name']=name;}
if(typeof status!=='undefined'){payload['status']=status;}
if(typeof schedule!=='undefined'){payload['schedule']=schedule;}
if(typeof security!=='undefined'){payload['security']=security;}
if(typeof httpMethod!=='undefined'){payload['httpMethod']=httpMethod;}
if(typeof httpUrl!=='undefined'){payload['httpUrl']=httpUrl;}
if(typeof httpHeaders!=='undefined'){payload['httpHeaders']=httpHeaders;}
if(typeof httpUser!=='undefined'){payload['httpUser']=httpUser;}
if(typeof httpPass!=='undefined'){payload['httpPass']=httpPass;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getTask:(projectId,taskId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateTask:(projectId,taskId,name,status,schedule,security,httpMethod,httpUrl,httpHeaders,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
if(typeof status==='undefined'){throw new AppwriteException('Missing required parameter: "status"');}
if(typeof schedule==='undefined'){throw new AppwriteException('Missing required parameter: "schedule"');}
if(typeof security==='undefined'){throw new AppwriteException('Missing required parameter: "security"');}
if(typeof httpMethod==='undefined'){throw new AppwriteException('Missing required parameter: "httpMethod"');}
if(typeof httpUrl==='undefined'){throw new AppwriteException('Missing required parameter: "httpUrl"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};if(typeof name!=='undefined'){payload['name']=name;}
if(typeof status!=='undefined'){payload['status']=status;}
if(typeof schedule!=='undefined'){payload['schedule']=schedule;}
if(typeof security!=='undefined'){payload['security']=security;}
if(typeof httpMethod!=='undefined'){payload['httpMethod']=httpMethod;}
if(typeof httpUrl!=='undefined'){payload['httpUrl']=httpUrl;}
if(typeof httpHeaders!=='undefined'){payload['httpHeaders']=httpHeaders;}
if(typeof httpUser!=='undefined'){payload['httpUser']=httpUser;}
if(typeof httpPass!=='undefined'){payload['httpPass']=httpPass;}
const uri=new URL(this.config.endpoint+path);return yield this.call('put',uri,{'content-type':'application/json',},payload);}),deleteTask:(projectId,taskId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
if(typeof taskId==='undefined'){throw new AppwriteException('Missing required parameter: "taskId"');}
let path='/projects/{projectId}/tasks/{taskId}'.replace('{projectId}',projectId).replace('{taskId}',taskId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('delete',uri,{'content-type':'application/json',},payload);}),getUsage:(projectId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,{'content-type':'application/json',},payload);}),getUsage:(projectId,range)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/usage'.replace('{projectId}',projectId);let payload={};if(typeof range!=='undefined'){payload['range']=range;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),listWebhooks:(projectId)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
let path='/projects/{projectId}/webhooks'.replace('{projectId}',projectId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createWebhook:(projectId,name,events,url,security,httpUser,httpPass)=>__awaiter(this,void 0,void 0,function*(){if(typeof projectId==='undefined'){throw new AppwriteException('Missing required parameter: "projectId"');}
@ -371,8 +390,10 @@ let path='/projects/{projectId}/webhooks/{webhookId}'.replace('{projectId}',proj
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createFile:(file,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof file==='undefined'){throw new AppwriteException('Missing required parameter: "file"');}
let path='/storage/files';let payload={};if(typeof file!=='undefined'){payload['file']=file;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),createFile:(fileId,file,read,write)=>__awaiter(this,void 0,void 0,function*(){if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
if(typeof file==='undefined'){throw new AppwriteException('Missing required parameter: "file"');}
let path='/storage/files';let payload={};if(typeof fileId!=='undefined'){payload['fileId']=fileId;}
if(typeof file!=='undefined'){payload['file']=file;}
if(typeof read!=='undefined'){payload['read']=read;}
if(typeof write!=='undefined'){payload['write']=write;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'multipart/form-data',},payload);}),getFile:(fileId)=>__awaiter(this,void 0,void 0,function*(){if(typeof fileId==='undefined'){throw new AppwriteException('Missing required parameter: "fileId"');}
@ -403,8 +424,10 @@ return uri;}};this.teams={list:(search,limit,offset,orderType)=>__awaiter(this,v
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(name,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
let path='/teams';let payload={};if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(teamId,name,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof name==='undefined'){throw new AppwriteException('Missing required parameter: "name"');}
let path='/teams';let payload={};if(typeof teamId!=='undefined'){payload['teamId']=teamId;}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof roles!=='undefined'){payload['roles']=roles;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),get:(teamId)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
let path='/teams/{teamId}'.replace('{teamId}',teamId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),update:(teamId,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
@ -424,7 +447,9 @@ let path='/teams/{teamId}/memberships'.replace('{teamId}',teamId);let payload={}
if(typeof name!=='undefined'){payload['name']=name;}
if(typeof roles!=='undefined'){payload['roles']=roles;}
if(typeof url!=='undefined'){payload['url']=url;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),updateMembershipRoles:(teamId,membershipId,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),getMembership:(teamId,membershipId)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof membershipId==='undefined'){throw new AppwriteException('Missing required parameter: "membershipId"');}
let path='/teams/{teamId}/memberships/{membershipId}'.replace('{teamId}',teamId).replace('{membershipId}',membershipId);let payload={};const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),updateMembershipRoles:(teamId,membershipId,roles)=>__awaiter(this,void 0,void 0,function*(){if(typeof teamId==='undefined'){throw new AppwriteException('Missing required parameter: "teamId"');}
if(typeof membershipId==='undefined'){throw new AppwriteException('Missing required parameter: "membershipId"');}
if(typeof roles==='undefined'){throw new AppwriteException('Missing required parameter: "roles"');}
let path='/teams/{teamId}/memberships/{membershipId}'.replace('{teamId}',teamId).replace('{membershipId}',membershipId);let payload={};if(typeof roles!=='undefined'){payload['roles']=roles;}
@ -440,9 +465,11 @@ const uri=new URL(this.config.endpoint+path);return yield this.call('patch',uri,
if(typeof limit!=='undefined'){payload['limit']=limit;}
if(typeof offset!=='undefined'){payload['offset']=offset;}
if(typeof orderType!=='undefined'){payload['orderType']=orderType;}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
const uri=new URL(this.config.endpoint+path);return yield this.call('get',uri,{'content-type':'application/json',},payload);}),create:(userId,email,password,name)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}
if(typeof email==='undefined'){throw new AppwriteException('Missing required parameter: "email"');}
if(typeof password==='undefined'){throw new AppwriteException('Missing required parameter: "password"');}
let path='/users';let payload={};if(typeof email!=='undefined'){payload['email']=email;}
let path='/users';let payload={};if(typeof userId!=='undefined'){payload['userId']=userId;}
if(typeof email!=='undefined'){payload['email']=email;}
if(typeof password!=='undefined'){payload['password']=password;}
if(typeof name!=='undefined'){payload['name']=name;}
const uri=new URL(this.config.endpoint+path);return yield this.call('post',uri,{'content-type':'application/json',},payload);}),get:(userId)=>__awaiter(this,void 0,void 0,function*(){if(typeof userId==='undefined'){throw new AppwriteException('Missing required parameter: "userId"');}

View file

@ -356,7 +356,21 @@ code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addE
function syncA(){element.value=picker.value;update();}
function syncB(){picker.value=element.value;}
element.parentNode.insertBefore(preview,element);update();syncB();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-copy",controller:function(element,alerts,document,window){var button=window.document.createElement("i");button.type="button";button.className="icon-docs note copy";button.style.cursor="pointer";element.parentNode.insertBefore(button,element.nextSibling);var copy=function(event){let disabled=element.disabled;element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
element.disabled=disabled;element.blur();alerts.add({text:"Copied to clipboard",class:""},3000);};button.addEventListener("click",copy);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document",controller:function(element,container,search){var formsDocument=(element.dataset["formsDocument"]||'');var searchButton=(element.dataset["search"]||0);let path=container.scope(searchButton);element.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent(formsDocument,{bubbles:false,cancelable:true}));});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document-preview",controller:function(element,container,search){element.addEventListener('change',function(){console.log(element.value);});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-filter",controller:function(document,container,expression,element,form,di){let name=element.dataset["formsFilter"]||"";let events=element.dataset["event"]||"";let serialize=function(obj,prefix){let str=[],p;for(p in obj){if(obj.hasOwnProperty(p)){let k=prefix?prefix+"["+p+"]":p,v=obj[p];if(v===""){continue;}
element.disabled=disabled;element.blur();alerts.add({text:"Copied to clipboard",class:""},3000);};button.addEventListener("click",copy);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-custom-id",controller:function(element,sdk,console,window){let prevData="";let idType=element.getAttribute('data-id-type');let disableSwitch=element.getAttribute('data-disable-switch');const div=window.document.createElement("div");if(disableSwitch!=="true"){div.className="input-copy";}
const button=window.document.createElement("i");button.type="button";button.style.cursor="pointer";const writer=window.document.createElement("input");writer.type="text";writer.setAttribute("maxlength",element.getAttribute("maxlength"));const placeholder=element.getAttribute("placeholder");if(placeholder){writer.setAttribute("placeholder",placeholder);}
const info=window.document.createElement("div");info.className="text-fade text-size-xs margin-top-negative-small margin-bottom";div.appendChild(writer);if(disableSwitch!=="true"){div.appendChild(button);}
element.parentNode.insertBefore(div,element);element.parentNode.insertBefore(info,div.nextSibling);const switchType=function(event){if(idType=="custom"){idType="auto";setIdType(idType);}else{idType="custom";setIdType(idType);}}
const validate=function(event){const[service,method]=element.dataset["validator"].split('.');const value=event.target.value;if(value.length<1){event.target.setCustomValidity("ID is required");}else{switch(service){case'projects':setValidity(console[service][method](value),event.target);break;default:setValidity(sdk[service][method](value),event.target);}}}
const setValidity=async function(promise,target){try{await promise;target.setCustomValidity("ID already exists");}catch(e){target.setCustomValidity("");}}
const setIdType=function(idType){if(idType=="custom"){element.setAttribute("data-id-type",idType);info.innerHTML="Allowed Characters A-Z, a-z, 0-9, and non-leading underscore";if(prevData==='auto-generated'){prevData=""}
writer.setAttribute("value",prevData);writer.value=prevData;element.value=prevData;writer.removeAttribute("disabled");writer.focus();writer.addEventListener('blur',validate);}else{idType='auto'
element.setAttribute("data-id-type",idType);info.innerHTML="Appwrite will generate a unique ID";prevData=writer.value;writer.setAttribute("disabled",true);writer.setAttribute("value","auto-generated");writer.value="auto-generated";element.value='unique()';}
button.className=idType=="custom"?"icon-shuffle copy":"icon-edit copy";}
const syncEditorWithID=function(event){if(element.value!=='unique()'||idType!='auto'){writer.value=element.value;}
if(idType=='auto'){element.value='unique()';}}
const keypress=function(e){const key=e.which||e.keyCode;const ZERO=48;const NINE=57;const SMALL_A=97;const SMALL_Z=122;const CAPITAL_A=65;const CAPITAL_Z=90;const UNDERSCORE=95;const isNotValidDigit=key<ZERO||key>NINE;const isNotValidSmallAlphabet=key<SMALL_A||key>SMALL_Z;const isNotValidCapitalAlphabet=key<CAPITAL_A||key>CAPITAL_Z;if(key==UNDERSCORE&&e.target.value.length==0){e.preventDefault();}
if(key!=UNDERSCORE&&isNotValidDigit&&isNotValidSmallAlphabet&&isNotValidCapitalAlphabet){e.preventDefault();}}
syncEditorWithID();setIdType(idType);writer.addEventListener("change",function(event){element.value=writer.value;});writer.form.addEventListener('reset',function(event){const resetEvent=new Event('reset');element.dispatchEvent(resetEvent);});element.addEventListener('reset',function(event){idType=element.getAttribute('data-id-type');setIdType(idType);});writer.addEventListener('keypress',keypress);button.addEventListener("click",switchType);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document",controller:function(element,container,search){var formsDocument=(element.dataset["formsDocument"]||'');var searchButton=(element.dataset["search"]||0);let path=container.scope(searchButton);element.addEventListener('click',function(){search.selected=element.value;search.path=path;document.dispatchEvent(new CustomEvent(formsDocument,{bubbles:false,cancelable:true}));});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-document-preview",controller:function(element,container,search){element.addEventListener('change',function(){console.log(element.value);});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-forms-filter",controller:function(document,container,expression,element,form,di){let name=element.dataset["formsFilter"]||"";let events=element.dataset["event"]||"";let serialize=function(obj,prefix){let str=[],p;for(p in obj){if(obj.hasOwnProperty(p)){let k=prefix?prefix+"["+p+"]":p,v=obj[p];if(v===""){continue;}
str.push(v!==null&&typeof v==="object"?serialize(v,k):encodeURIComponent(k)+"="+encodeURIComponent(v));}}
return str.join("&");};let parse=function(filter){if(filter===""){return null;}
let operatorsMap=["!=",">=","<=","=",">","<"];let operator=null;for(let key=0;key<operatorsMap.length;key++){if(filter.indexOf(operatorsMap[key])>-1){operator=operatorsMap[key];}}
@ -397,7 +411,7 @@ element.classList.add('scroll-to-bottom')}
else{element.classList.remove('scroll-to-bottom')
element.classList.add('scroll-to-top')}
position=direction;let current=Math.ceil(direction/window.innerHeight);element.setAttribute('data-views-total',Math.ceil(element.scrollHeight/window.innerHeight));element.setAttribute('data-views-current',current);if(element.scrollHeight<=(direction+element.offsetHeight+300)&&direction>0){element.classList.add('scroll-end')}
else{element.classList.remove('scroll-end')}};window.addEventListener('scroll',check,false);window.addEventListener('resize',check,false);check();}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-setup",controller:function(element,console,form,alerts,router){element.addEventListener("submit",function(event){event.preventDefault();let loaderId=alerts.add({text:'Creating new project...',class:""},0);let formData=form.toJson(element);formData["name"]=formData["name"]||(element.dataset["defaultName"]||"");console.teams.create(formData["name"]||"").then(function(data){let team=data["$id"];formData=JSON.parse(JSON.stringify(formData).replace(new RegExp("{{teamId}}","g"),team));console.projects.create(formData["name"],team).then(function(project){alerts.remove(loaderId);window.location.href="/console/home?project="+project["$id"];},function(){throw new Error("Failed to setup project");});},function(){throw new Error("Setup failed creating project team");});});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-switch",controller:function(element,router,document){let check=function(c){if(!element.value){return;}
else{element.classList.remove('scroll-end')}};window.addEventListener('scroll',check,false);window.addEventListener('resize',check,false);check();}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-setup",controller:function(element,console,form,alerts,router){element.addEventListener("submit",function(event){event.preventDefault();let loaderId=alerts.add({text:'Creating new project...',class:""},0);let formData=form.toJson(element);formData["name"]=formData["name"]||(element.dataset["defaultName"]||"");console.teams.create('unique()',formData["name"]||"").then(function(data){let team=data["$id"];formData=JSON.parse(JSON.stringify(formData).replace(new RegExp("{{teamId}}","g"),team));console.projects.create(formData["projectId"],formData["name"],team).then(function(project){alerts.remove(loaderId);window.location.href="/console/home?project="+project["$id"];},function(){throw new Error("Failed to setup project");});},function(){throw new Error("Setup failed creating project team");});});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-switch",controller:function(element,router,document){let check=function(c){if(!element.value){return;}
if(element.value===router.params.project){return;}
return router.change("/console/home?project="+element.value);};element.addEventListener("change",function(){check();});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-general-theme",controller:function(element,router,document){let toggle=function(c){if(document.body.classList.contains('theme-light')){document.body.classList.remove('theme-light');document.body.classList.add('theme-dark');window.localStorage.setItem('user-theme','theme-dark')}
else{document.body.classList.remove('theme-dark');document.body.classList.add('theme-light');window.localStorage.setItem('user-theme','theme-light')}};element.addEventListener("click",function(){toggle();});}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-version",controller:function(alerts,env,cookie){let cookieName="version-update-"+env.VERSION.replace(/\./g,"_");if(!cookie.get(cookieName)){var xhr=new XMLHttpRequest();xhr.open('GET','/console/version',true);xhr.onload=function(){if(this.readyState==4&&this.status==200){let data=JSON.parse(this.responseText);let text='Appwrite version '+data.version+' is avaliable, check the';if(isNewerVersion(env.VERSION,data.version)){alerts.add({text:text,class:"success",link:"https://github.com/appwrite/appwrite/releases",label:'release notes',callback:function(){cookie.set(cookieName,"true",365*10);}},0);}}};xhr.send(null);function isNewerVersion(oldVer,newVer){const oldParts=oldVer.split('.')
@ -414,7 +428,7 @@ if(selected&&list[selected].dataset["selected"]){let parent=element.querySelecto
if(!buttonAlias){buttonElements.forEach(button=>{button.innerText=buttonText;button.className=buttonClass;button.type=buttonElement;if(buttonIcon){let iconElement=document.createElement("i");iconElement.className=buttonIcon;button.insertBefore(iconElement,button.firstChild);}});}
if(buttonEvent){buttonElements.forEach(button=>{button.addEventListener("click",function(){document.dispatchEvent(new CustomEvent(buttonEvent,{bubbles:false,cancelable:true}));});});}
element.classList.add("modal");if(!buttonAlias&&!buttonHide){buttonElements.forEach(button=>{element.parentNode.insertBefore(button,element);});}
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
let open=function(){document.documentElement.classList.add("modal-open");document.dispatchEvent(new CustomEvent("modal-open",{bubbles:false,cancelable:true}));element.classList.add("open");element.classList.remove("close");let form=element.querySelector('form');let elements=(form&&form.elements)?[...form.elements]:[];for(let index=0;index<elements.length;index++){let element=elements[index];if(element.type!=='hidden'&&element.type!=='button'&&element.type!=='submit'&&!element.disabled){element.focus();break;}}};let close=function(event){document.documentElement.classList.remove("modal-open");element.classList.add("close");element.classList.remove("open");};if(name){document.querySelectorAll("[data-ui-modal-ref='"+name+"']").forEach(function(elem){elem.addEventListener("click",open);});}
if(openEvent){document.addEventListener(openEvent,open);}
buttonElements.forEach(button=>{button.addEventListener("click",open);});document.addEventListener("keydown",function(event){if(event.which===27){close();}});element.addEventListener("blur",close);let closeButtons=element.querySelectorAll("[data-ui-modal-close]");for(let i=0;i<closeButtons.length;i++){closeButtons[i].addEventListener("click",close);}
document.addEventListener("modal-close",close);element.addEventListener(closeEvent,close);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-open",controller:function(element,window){let def=element.classList.contains("open")?"open":"close";let buttonClass=element.dataset["buttonClass"]||"ls-ui-open";let buttonText=element.dataset["buttonText"]||"";let buttonIcon=element.dataset["buttonIcon"]||"";let buttonAria=element.dataset["buttonAria"]||"Open";let buttonSelector=element.dataset["buttonSelector"]||"";let hover=element.hasAttribute("data-hover");let blur=element.hasAttribute("data-blur");let button=window.document.createElement("button");let isTouch=function(){return("ontouchstart"in window||navigator.maxTouchPoints);};button.innerText=buttonText;button.className=buttonClass;button.type="button";if(buttonIcon){let icon=window.document.createElement("i");icon.className=buttonIcon;button.insertBefore(icon,button.firstChild);}

View file

@ -76,13 +76,17 @@
* login to their new account, you need to create a new [account
* session](/docs/client/account#accountCreateSession).
*
* @param {string} userId
* @param {string} email
* @param {string} password
* @param {string} name
* @throws {AppwriteException}
* @returns {Promise}
*/
create: (email, password, name) => __awaiter(this, void 0, void 0, function* () {
create: (userId, email, password, name) => __awaiter(this, void 0, void 0, function* () {
if (typeof userId === 'undefined') {
throw new AppwriteException('Missing required parameter: "userId"');
}
if (typeof email === 'undefined') {
throw new AppwriteException('Missing required parameter: "email"');
}
@ -91,6 +95,9 @@
}
let path = '/account';
let payload = {};
if (typeof userId !== 'undefined') {
payload['userId'] = userId;
}
if (typeof email !== 'undefined') {
payload['email'] = email;
}
@ -928,13 +935,17 @@
*
* Create a new Collection.
*
* @param {string} collectionId
* @param {string} name
* @param {string} read
* @param {string} write
* @throws {AppwriteException}
* @returns {Promise}
*/
createCollection: (name, read, write) => __awaiter(this, void 0, void 0, function* () {
createCollection: (collectionId, name, read, write) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
@ -946,6 +957,9 @@
}
let path = '/database/collections';
let payload = {};
if (typeof collectionId !== 'undefined') {
payload['collectionId'] = collectionId;
}
if (typeof name !== 'undefined') {
payload['name'] = name;
}
@ -1057,12 +1071,232 @@
}, payload);
}),
/**
* Create Attribute
* Create Boolean Attribute
*
*
* @param {string} collectionId
* @param {string} id
* @param {string} type
* @param {string} attributeId
* @param {boolean} required
* @param {boolean} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createBooleanAttribute: (collectionId, attributeId, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/boolean'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create Email Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {boolean} required
* @param {string} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createEmailAttribute: (collectionId, attributeId, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/email'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create Float Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {boolean} required
* @param {string} min
* @param {string} max
* @param {string} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createFloatAttribute: (collectionId, attributeId, required, min, max, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/float'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof min !== 'undefined') {
payload['min'] = min;
}
if (typeof max !== 'undefined') {
payload['max'] = max;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create Integer Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {boolean} required
* @param {number} min
* @param {number} max
* @param {number} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createIntegerAttribute: (collectionId, attributeId, required, min, max, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/integer'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof min !== 'undefined') {
payload['min'] = min;
}
if (typeof max !== 'undefined') {
payload['max'] = max;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create IP Address Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {boolean} required
* @param {string} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createIpAttribute: (collectionId, attributeId, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/ip'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create String Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {number} size
* @param {boolean} required
* @param {string} xdefault
@ -1070,15 +1304,12 @@
* @throws {AppwriteException}
* @returns {Promise}
*/
createAttribute: (collectionId, id, type, size, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
createStringAttribute: (collectionId, attributeId, size, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof id === 'undefined') {
throw new AppwriteException('Missing required parameter: "id"');
}
if (typeof type === 'undefined') {
throw new AppwriteException('Missing required parameter: "type"');
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof size === 'undefined') {
throw new AppwriteException('Missing required parameter: "size"');
@ -1086,13 +1317,58 @@
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes'.replace('{collectionId}', collectionId);
let path = '/database/collections/{collectionId}/attributes/string'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof id !== 'undefined') {
payload['id'] = id;
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof type !== 'undefined') {
payload['type'] = type;
if (typeof size !== 'undefined') {
payload['size'] = size;
}
if (typeof required !== 'undefined') {
payload['required'] = required;
}
if (typeof xdefault !== 'undefined') {
payload['xdefault'] = xdefault;
}
if (typeof array !== 'undefined') {
payload['array'] = array;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create IP Address Attribute
*
*
* @param {string} collectionId
* @param {string} attributeId
* @param {number} size
* @param {boolean} required
* @param {string} xdefault
* @param {boolean} array
* @throws {AppwriteException}
* @returns {Promise}
*/
createUrlAttribute: (collectionId, attributeId, size, required, xdefault, array) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof attributeId === 'undefined') {
throw new AppwriteException('Missing required parameter: "attributeId"');
}
if (typeof size === 'undefined') {
throw new AppwriteException('Missing required parameter: "size"');
}
if (typeof required === 'undefined') {
throw new AppwriteException('Missing required parameter: "required"');
}
let path = '/database/collections/{collectionId}/attributes/url'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof attributeId !== 'undefined') {
payload['attributeId'] = attributeId;
}
if (typeof size !== 'undefined') {
payload['size'] = size;
@ -1209,21 +1485,28 @@
* directly from your database console.
*
* @param {string} collectionId
* @param {string} documentId
* @param {object} data
* @param {string} read
* @param {string} write
* @throws {AppwriteException}
* @returns {Promise}
*/
createDocument: (collectionId, data, read, write) => __awaiter(this, void 0, void 0, function* () {
createDocument: (collectionId, documentId, data, read, write) => __awaiter(this, void 0, void 0, function* () {
if (typeof collectionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "collectionId"');
}
if (typeof documentId === 'undefined') {
throw new AppwriteException('Missing required parameter: "documentId"');
}
if (typeof data === 'undefined') {
throw new AppwriteException('Missing required parameter: "data"');
}
let path = '/database/collections/{collectionId}/documents'.replace('{collectionId}', collectionId);
let payload = {};
if (typeof documentId !== 'undefined') {
payload['documentId'] = documentId;
}
if (typeof data !== 'undefined') {
payload['data'] = data;
}
@ -1480,6 +1763,7 @@
* [permissions](/docs/permissions) to allow different project users or team
* with access to execute the function using the client API.
*
* @param {string} functionId
* @param {string} name
* @param {string[]} execute
* @param {string} runtime
@ -1490,7 +1774,10 @@
* @throws {AppwriteException}
* @returns {Promise}
*/
create: (name, execute, runtime, vars, events, schedule, timeout) => __awaiter(this, void 0, void 0, function* () {
create: (functionId, name, execute, runtime, vars, events, schedule, timeout) => __awaiter(this, void 0, void 0, function* () {
if (typeof functionId === 'undefined') {
throw new AppwriteException('Missing required parameter: "functionId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
@ -1502,6 +1789,9 @@
}
let path = '/functions';
let payload = {};
if (typeof functionId !== 'undefined') {
payload['functionId'] = functionId;
}
if (typeof name !== 'undefined') {
payload['name'] = name;
}
@ -1997,23 +2287,6 @@
'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 {AppwriteException}
* @returns {Promise}
*/
getQueueTasks: () => __awaiter(this, void 0, void 0, function* () {
let path = '/health/queue/tasks';
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('get', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Get Usage Queue
*
@ -2249,6 +2522,7 @@
* Create Project
*
*
* @param {string} projectId
* @param {string} name
* @param {string} teamId
* @param {string} description
@ -2263,7 +2537,10 @@
* @throws {AppwriteException}
* @returns {Promise}
*/
create: (name, teamId, description, logo, url, legalName, legalCountry, legalState, legalCity, legalAddress, legalTaxId) => __awaiter(this, void 0, void 0, function* () {
create: (projectId, name, teamId, description, logo, url, legalName, legalCountry, legalState, legalCity, legalAddress, legalTaxId) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
@ -2272,6 +2549,9 @@
}
let path = '/projects';
let payload = {};
if (typeof projectId !== 'undefined') {
payload['projectId'] = projectId;
}
if (typeof name !== 'undefined') {
payload['name'] = name;
}
@ -2925,6 +3205,9 @@
if (typeof service === 'undefined') {
throw new AppwriteException('Missing required parameter: "service"');
}
if (typeof status === 'undefined') {
throw new AppwriteException('Missing required parameter: "status"');
}
let path = '/projects/{projectId}/service'.replace('{projectId}', projectId);
let payload = {};
if (typeof service !== 'undefined') {
@ -2938,221 +3221,6 @@
'content-type': 'application/json',
}, payload);
}),
/**
* List Tasks
*
*
* @param {string} projectId
* @throws {AppwriteException}
* @returns {Promise}
*/
listTasks: (projectId) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
let path = '/projects/{projectId}/tasks'.replace('{projectId}', projectId);
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('get', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Create Task
*
*
* @param {string} projectId
* @param {string} name
* @param {string} status
* @param {string} schedule
* @param {boolean} security
* @param {string} httpMethod
* @param {string} httpUrl
* @param {string[]} httpHeaders
* @param {string} httpUser
* @param {string} httpPass
* @throws {AppwriteException}
* @returns {Promise}
*/
createTask: (projectId, name, status, schedule, security, httpMethod, httpUrl, httpHeaders, httpUser, httpPass) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
if (typeof status === 'undefined') {
throw new AppwriteException('Missing required parameter: "status"');
}
if (typeof schedule === 'undefined') {
throw new AppwriteException('Missing required parameter: "schedule"');
}
if (typeof security === 'undefined') {
throw new AppwriteException('Missing required parameter: "security"');
}
if (typeof httpMethod === 'undefined') {
throw new AppwriteException('Missing required parameter: "httpMethod"');
}
if (typeof httpUrl === 'undefined') {
throw new AppwriteException('Missing required parameter: "httpUrl"');
}
let path = '/projects/{projectId}/tasks'.replace('{projectId}', projectId);
let payload = {};
if (typeof name !== 'undefined') {
payload['name'] = name;
}
if (typeof status !== 'undefined') {
payload['status'] = status;
}
if (typeof schedule !== 'undefined') {
payload['schedule'] = schedule;
}
if (typeof security !== 'undefined') {
payload['security'] = security;
}
if (typeof httpMethod !== 'undefined') {
payload['httpMethod'] = httpMethod;
}
if (typeof httpUrl !== 'undefined') {
payload['httpUrl'] = httpUrl;
}
if (typeof httpHeaders !== 'undefined') {
payload['httpHeaders'] = httpHeaders;
}
if (typeof httpUser !== 'undefined') {
payload['httpUser'] = httpUser;
}
if (typeof httpPass !== 'undefined') {
payload['httpPass'] = httpPass;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('post', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Get Task
*
*
* @param {string} projectId
* @param {string} taskId
* @throws {AppwriteException}
* @returns {Promise}
*/
getTask: (projectId, taskId) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
if (typeof taskId === 'undefined') {
throw new AppwriteException('Missing required parameter: "taskId"');
}
let path = '/projects/{projectId}/tasks/{taskId}'.replace('{projectId}', projectId).replace('{taskId}', taskId);
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('get', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Update Task
*
*
* @param {string} projectId
* @param {string} taskId
* @param {string} name
* @param {string} status
* @param {string} schedule
* @param {boolean} security
* @param {string} httpMethod
* @param {string} httpUrl
* @param {string[]} httpHeaders
* @param {string} httpUser
* @param {string} httpPass
* @throws {AppwriteException}
* @returns {Promise}
*/
updateTask: (projectId, taskId, name, status, schedule, security, httpMethod, httpUrl, httpHeaders, httpUser, httpPass) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
if (typeof taskId === 'undefined') {
throw new AppwriteException('Missing required parameter: "taskId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
if (typeof status === 'undefined') {
throw new AppwriteException('Missing required parameter: "status"');
}
if (typeof schedule === 'undefined') {
throw new AppwriteException('Missing required parameter: "schedule"');
}
if (typeof security === 'undefined') {
throw new AppwriteException('Missing required parameter: "security"');
}
if (typeof httpMethod === 'undefined') {
throw new AppwriteException('Missing required parameter: "httpMethod"');
}
if (typeof httpUrl === 'undefined') {
throw new AppwriteException('Missing required parameter: "httpUrl"');
}
let path = '/projects/{projectId}/tasks/{taskId}'.replace('{projectId}', projectId).replace('{taskId}', taskId);
let payload = {};
if (typeof name !== 'undefined') {
payload['name'] = name;
}
if (typeof status !== 'undefined') {
payload['status'] = status;
}
if (typeof schedule !== 'undefined') {
payload['schedule'] = schedule;
}
if (typeof security !== 'undefined') {
payload['security'] = security;
}
if (typeof httpMethod !== 'undefined') {
payload['httpMethod'] = httpMethod;
}
if (typeof httpUrl !== 'undefined') {
payload['httpUrl'] = httpUrl;
}
if (typeof httpHeaders !== 'undefined') {
payload['httpHeaders'] = httpHeaders;
}
if (typeof httpUser !== 'undefined') {
payload['httpUser'] = httpUser;
}
if (typeof httpPass !== 'undefined') {
payload['httpPass'] = httpPass;
}
const uri = new URL(this.config.endpoint + path);
return yield this.call('put', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Delete Task
*
*
* @param {string} projectId
* @param {string} taskId
* @throws {AppwriteException}
* @returns {Promise}
*/
deleteTask: (projectId, taskId) => __awaiter(this, void 0, void 0, function* () {
if (typeof projectId === 'undefined') {
throw new AppwriteException('Missing required parameter: "projectId"');
}
if (typeof taskId === 'undefined') {
throw new AppwriteException('Missing required parameter: "taskId"');
}
let path = '/projects/{projectId}/tasks/{taskId}'.replace('{projectId}', projectId).replace('{taskId}', taskId);
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('delete', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Get Project
*
@ -3398,18 +3466,25 @@
* assigned to read and write access unless he has passed custom values for
* read and write arguments.
*
* @param {string} fileId
* @param {File} file
* @param {string[]} read
* @param {string[]} write
* @throws {AppwriteException}
* @returns {Promise}
*/
createFile: (file, read, write) => __awaiter(this, void 0, void 0, function* () {
createFile: (fileId, file, read, write) => __awaiter(this, void 0, void 0, function* () {
if (typeof fileId === 'undefined') {
throw new AppwriteException('Missing required parameter: "fileId"');
}
if (typeof file === 'undefined') {
throw new AppwriteException('Missing required parameter: "file"');
}
let path = '/storage/files';
let payload = {};
if (typeof fileId !== 'undefined') {
payload['fileId'] = fileId;
}
if (typeof file !== 'undefined') {
payload['file'] = file;
}
@ -3663,17 +3738,24 @@
* who will be able add new owners and update or delete the team from your
* project.
*
* @param {string} teamId
* @param {string} name
* @param {string[]} roles
* @throws {AppwriteException}
* @returns {Promise}
*/
create: (name, roles) => __awaiter(this, void 0, void 0, function* () {
create: (teamId, name, roles) => __awaiter(this, void 0, void 0, function* () {
if (typeof teamId === 'undefined') {
throw new AppwriteException('Missing required parameter: "teamId"');
}
if (typeof name === 'undefined') {
throw new AppwriteException('Missing required parameter: "name"');
}
let path = '/teams';
let payload = {};
if (typeof teamId !== 'undefined') {
payload['teamId'] = teamId;
}
if (typeof name !== 'undefined') {
payload['name'] = name;
}
@ -3852,6 +3934,31 @@
'content-type': 'application/json',
}, payload);
}),
/**
* Get Team Membership
*
* Get a team member by the membership unique id. All team members have read
* access for this resource.
*
* @param {string} teamId
* @param {string} membershipId
* @throws {AppwriteException}
* @returns {Promise}
*/
getMembership: (teamId, membershipId) => __awaiter(this, void 0, void 0, function* () {
if (typeof teamId === 'undefined') {
throw new AppwriteException('Missing required parameter: "teamId"');
}
if (typeof membershipId === 'undefined') {
throw new AppwriteException('Missing required parameter: "membershipId"');
}
let path = '/teams/{teamId}/memberships/{membershipId}'.replace('{teamId}', teamId).replace('{membershipId}', membershipId);
let payload = {};
const uri = new URL(this.config.endpoint + path);
return yield this.call('get', uri, {
'content-type': 'application/json',
}, payload);
}),
/**
* Update Membership Roles
*
@ -3988,13 +4095,17 @@
*
* Create a new user.
*
* @param {string} userId
* @param {string} email
* @param {string} password
* @param {string} name
* @throws {AppwriteException}
* @returns {Promise}
*/
create: (email, password, name) => __awaiter(this, void 0, void 0, function* () {
create: (userId, email, password, name) => __awaiter(this, void 0, void 0, function* () {
if (typeof userId === 'undefined') {
throw new AppwriteException('Missing required parameter: "userId"');
}
if (typeof email === 'undefined') {
throw new AppwriteException('Missing required parameter: "email"');
}
@ -4003,6 +4114,9 @@
}
let path = '/users';
let payload = {};
if (typeof userId !== 'undefined') {
payload['userId'] = userId;
}
if (typeof email !== 'undefined') {
payload['email'] = email;
}

View file

@ -0,0 +1,149 @@
(function (window) {
"use strict";
window.ls.container.get("view").add({
selector: "data-custom-id",
controller: function (element, sdk, console, window) {
let prevData = "";
let idType = element.getAttribute('data-id-type');
let disableSwitch = element.getAttribute('data-disable-switch');
const div = window.document.createElement("div");
if(disableSwitch !== "true") {
div.className = "input-copy";
}
const button = window.document.createElement("i");
button.type = "button";
button.style.cursor = "pointer";
const writer = window.document.createElement("input");
writer.type = "text";
writer.setAttribute("maxlength", element.getAttribute("maxlength"));
const placeholder = element.getAttribute("placeholder");
if (placeholder) {
writer.setAttribute("placeholder", placeholder);
}
const info = window.document.createElement("div");
info.className = "text-fade text-size-xs margin-top-negative-small margin-bottom";
div.appendChild(writer);
if(disableSwitch !== "true") {
div.appendChild(button);
}
element.parentNode.insertBefore(div, element);
element.parentNode.insertBefore(info, div.nextSibling);
const switchType = function (event) {
if (idType == "custom") {
idType = "auto";
setIdType(idType);
} else {
idType = "custom";
setIdType(idType);
}
}
const validate = function (event) {
const [service, method] = element.dataset["validator"].split('.');
const value = event.target.value;
if (value.length < 1) {
event.target.setCustomValidity("ID is required");
} else {
switch (service) {
case 'projects':
setValidity(console[service][method](value), event.target);
break;
default:
setValidity(sdk[service][method](value), event.target);
}
}
}
const setValidity = async function (promise, target) {
try {
await promise;
target.setCustomValidity("ID already exists");
} catch (e) {
target.setCustomValidity("");
}
}
const setIdType = function (idType) {
if (idType == "custom") {
element.setAttribute("data-id-type", idType);
info.innerHTML = "Allowed Characters A-Z, a-z, 0-9, and non-leading underscore";
if (prevData === 'auto-generated') {
prevData = ""
}
writer.setAttribute("value", prevData);
writer.value = prevData;
element.value = prevData;
writer.removeAttribute("disabled");
writer.focus();
writer.addEventListener('blur', validate);
} else {
idType = 'auto'
element.setAttribute("data-id-type", idType);
info.innerHTML = "Appwrite will generate a unique ID";
prevData = writer.value;
writer.setAttribute("disabled", true);
writer.setAttribute("value", "auto-generated");
writer.value = "auto-generated";
element.value = 'unique()';
}
button.className = idType == "custom" ? "icon-shuffle copy" : "icon-edit copy";
}
const syncEditorWithID = function (event) {
if (element.value !== 'unique()' || idType != 'auto') {
writer.value = element.value;
}
if (idType == 'auto') {
element.value = 'unique()';
}
}
const keypress = function (e) {
// which key is pressed, keyPressed = e.which || e.keyCode;
const key = e.which || e.keyCode;
const ZERO = 48;
const NINE = 57;
const SMALL_A = 97;
const SMALL_Z = 122;
const CAPITAL_A = 65;
const CAPITAL_Z = 90;
const UNDERSCORE = 95;
const isNotValidDigit = key < ZERO || key > NINE;
const isNotValidSmallAlphabet = key < SMALL_A || key > SMALL_Z;
const isNotValidCapitalAlphabet = key < CAPITAL_A || key > CAPITAL_Z;
//Leading underscore is prevented
if (key == UNDERSCORE && e.target.value.length == 0) {
e.preventDefault();
}
if (key != UNDERSCORE && isNotValidDigit && isNotValidSmallAlphabet && isNotValidCapitalAlphabet) {
e.preventDefault();
}
}
syncEditorWithID();
setIdType(idType);
writer.addEventListener("change", function (event) {
element.value = writer.value;
});
writer.form.addEventListener('reset', function (event) {
const resetEvent = new Event('reset');
element.dispatchEvent(resetEvent);
});
element.addEventListener('reset', function (event) {
idType = element.getAttribute('data-id-type');
setIdType(idType);
});
writer.addEventListener('keypress', keypress);
button.addEventListener("click", switchType);
}
});
})(window);

View file

@ -12,7 +12,7 @@
formData["name"] =
formData["name"] || (element.dataset["defaultName"] || "");
console.teams.create(formData["name"] || "").then(
console.teams.create('unique()', formData["name"] || "").then(
function(data) {
let team = data["$id"];
@ -23,7 +23,7 @@
)
); //convert to JSON string
console.projects.create(formData["name"], team).then(
console.projects.create(formData["projectId"], formData["name"], team).then(
function(project) {
alerts.remove(loaderId);
//router.change("/console/home?project=" + project["$id"]);

View file

@ -93,6 +93,7 @@
if(element.type !== 'hidden'
&& element.type !== 'button'
&& element.type !== 'submit'
&& !element.disabled
) {
element.focus();
break;

View file

@ -0,0 +1,21 @@
<?php
namespace Appwrite\Database\Validator;
use Utopia\Database\Validator\Key;
class CustomId extends Key {
/**
* Is valid.
*
* Returns true if valid or false if not.
*
* @param $value
*
* @return bool
*/
public function isValid($value)
{
return $value == 'unique()' || parent::isValid($value);
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace Appwrite\Stats;
use Utopia\App;
class Stats
{
/**
* @var array
*/
protected $params = [];
/**
* @var mixed
*/
protected $statsd;
/**
* @var string
*/
protected $namespace = 'appwrite.usage';
/**
* Event constructor.
*
* @param mixed $statsd
*/
public function __construct($statsd)
{
$this->statsd = $statsd;
}
/**
* @param string $key
* @param mixed $value
*
* @return $this
*/
public function setParam(string $key, $value): self
{
$this->params[$key] = $value;
return $this;
}
/**
* @param string $key
*
* @return mixed|null
*/
public function getParam(string $key)
{
return (isset($this->params[$key])) ? $this->params[$key] : null;
}
/**
* @param string $namespace
*
* @return $this
*/
public function setNamespace(string $namespace): self
{
$this->namespace = $namespace;
return $this;
}
/**
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Submit data to StatsD.
*/
public function submit(): void
{
$projectId = $this->params['projectId'] ?? '';
$storage = $this->params['storage'] ?? 0;
$networkRequestSize = $this->params['networkRequestSize'] ?? 0;
$networkResponseSize = $this->params['networkResponseSize'] ?? 0;
$httpMethod = $this->params['httpMethod'] ?? '';
$httpRequest = $this->params['httpRequest'] ?? 0;
$functionId = $this->params['functionId'] ?? '';
$functionExecution = $this->params['functionExecution'] ?? 0;
$functionExecutionTime = $this->params['functionExecutionTime'] ?? 0;
$functionStatus = $this->params['functionStatus'] ?? '';
$tags = ",project={$projectId},version=" . App::getEnv('_APP_VERSION', 'UNKNOWN');
// the global namespace is prepended to every key (optional)
$this->statsd->setNamespace($this->namespace);
if ($httpRequest >= 1) {
$this->statsd->increment('requests.all' . $tags . ',method=' . \strtolower($httpMethod));
}
if ($functionExecution >= 1) {
$this->statsd->increment('executions.all' . $tags . ',functionId=' . $functionId . ',functionStatus=' . $functionStatus);
$this->statsd->count('executions.time' . $tags . ',functionId=' . $functionId, $functionExecutionTime);
}
$this->statsd->count('network.inbound' . $tags, $networkRequestSize);
$this->statsd->count('network.outbound' . $tags, $networkResponseSize);
$this->statsd->count('network.all' . $tags, $networkRequestSize + $networkResponseSize);
if ($storage >= 1) {
$this->statsd->count('storage.all' . $tags, $storage);
}
$this->reset();
}
public function reset(): self
{
$this->params = [];
$this->namespace = 'appwrite.usage';
return $this;
}
}

View file

@ -16,12 +16,12 @@ class Func extends Model
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('$permissions', [
'type' => Response::MODEL_PERMISSIONS,
'description' => 'Function permissions.',
'default' => new \stdClass,
'example' => new \stdClass,
'array' => false,
->addRule('execute', [
'type' => self::TYPE_STRING,
'description' => 'Document execute permissions.',
'default' => '',
'example' => 'role:all',
'array' => true,
])
->addRule('name', [
'type' => self::TYPE_STRING,

View file

@ -90,7 +90,7 @@ class Project extends Model
'default' => '',
'example' => '131102020',
])
->addRule('usersAuthLimit', [
->addRule('authLimit', [
'type' => self::TYPE_INTEGER,
'description' => 'Max users allowed. 0 is unlimited.',
'default' => 0,
@ -138,13 +138,13 @@ class Project extends Model
$name = (isset($provider['name'])) ? $provider['name'] : 'Unknown';
$this
->addRule('usersOauth2'.\ucfirst($index).'Appid', [
->addRule('provider'.\ucfirst($index).'Appid', [
'type' => self::TYPE_STRING,
'description' => $name.' OAuth app ID.',
'example' => '123247283472834787438',
'default' => '',
])
->addRule('usersOauth2'.\ucfirst($index).'Secret', [
->addRule('provider'.\ucfirst($index).'Secret', [
'type' => self::TYPE_STRING,
'description' => $name.' OAuth secret ID.',
'example' => 'djsgudsdsewe43434343dd34...',
@ -158,7 +158,7 @@ class Project extends Model
$key = $method['key'] ?? '';
$this
->addRule($key, [
->addRule('auth' . ucfirst($key), [
'type' => self::TYPE_BOOLEAN,
'description' => $name.' auth method status',
'example' => true,
@ -225,6 +225,28 @@ class Project extends Model
$document->setAttribute('serviceStatusFor'.ucfirst($key), $value);
}
$authValues = $document->getAttribute('auths',[]);
$auth = Config::getParam('auth', []);
$document->setAttribute('authLimit', $authValues['limit'] ?? 0);
foreach ($auth as $index => $method) {
$key = $method['key'];
$value = $authValues[$key] ?? true;
$document->setAttribute('auth' . ucfirst($key), $value);
}
$providers = Config::getParam('providers', []);
$providerValues = $document->getAttribute('providers', []);
foreach ($providers as $key => $provider) {
if (!$provider['enabled']) {
continue;
}
$appId = $providerValues[$key . 'Appid'] ?? '';
$secret = $providerValues[$key . 'Secret'] ?? '';
$document->setAttribute('provider' . ucfirst($key) . 'Appid', $appId)->setAttribute('provider' . ucfirst($key) . 'Secret', $secret);
}
return $document;
}
}

View file

@ -26,9 +26,9 @@ trait ProjectCustom
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
'x-appwrite-project' => 'console',
], [
'teamId' => 'unique()',
'name' => 'Demo Project Team',
]);
$this->assertEquals(201, $team['headers']['status-code']);
$this->assertEquals('Demo Project Team', $team['body']['name']);
$this->assertNotEmpty($team['body']['$id']);
@ -39,6 +39,7 @@ trait ProjectCustom
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
'x-appwrite-project' => 'console',
], [
'projectId' => 'unique()',
'name' => 'Demo Project',
'teamId' => $team['body']['$id'],
'description' => 'Demo Project Description',

View file

@ -87,6 +87,7 @@ abstract class Scope extends TestCase
'content-type' => 'application/json',
'x-appwrite-project' => 'console',
], [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -138,6 +139,7 @@ abstract class Scope extends TestCase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,

View file

@ -20,6 +20,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -42,6 +43,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -54,6 +56,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => '',
'password' => '',
]);
@ -65,6 +68,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => '',
]);
@ -76,6 +80,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => '',
'password' => $password,
]);
@ -601,6 +606,7 @@ trait AccountBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $data['email'],
'password' => $data['password'],
'name' => $data['name'],

View file

@ -68,6 +68,7 @@ class AccountCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -147,6 +148,7 @@ class AccountCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -325,6 +327,7 @@ class AccountCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password
]);

View file

@ -26,6 +26,7 @@ class AccountCustomServerTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,

View file

@ -16,6 +16,7 @@ trait DatabaseBase
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => 'unique()',
'name' => 'Movies',
'read' => ['role:all'],
'write' => ['role:all'],
@ -157,6 +158,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Captain America',
'releaseYear' => 1944,
@ -173,6 +175,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Spider-Man: Far From Home',
'releaseYear' => 2019,
@ -190,6 +193,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Spider-Man: Homecoming',
'releaseYear' => 2017,
@ -206,6 +210,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'releaseYear' => 2020, // Missing title, expect an 400 error
],
@ -527,6 +532,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Thor: Ragnaroc',
'releaseYear' => 2017,
@ -582,6 +588,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Thor: Ragnarok',
'releaseYear' => 2017,
@ -627,6 +634,7 @@ trait DatabaseBase
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => 'unique()',
'name' => 'invalidDocumentStructure',
'read' => ['role:all'],
'write' => ['role:all'],
@ -765,6 +773,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'email' => 'user@example.com',
],
@ -776,6 +785,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'ip' => '1.1.1.1',
],
@ -787,6 +797,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'url' => 'http://www.example.com',
],
@ -798,6 +809,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'range' => 3,
],
@ -809,6 +821,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'floatRange' => 1.4,
],
@ -820,6 +833,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'upperBound' => 8,
],
@ -831,6 +845,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'lowerBound' => 8,
],
@ -838,8 +853,6 @@ trait DatabaseBase
'write' => ['user:'.$this->getUser()['$id']],
]);
// var_dump($notTooLow);
$this->assertEquals(201, $goodEmail['headers']['status-code']);
$this->assertEquals(201, $goodIp['headers']['status-code']);
$this->assertEquals(201, $goodUrl['headers']['status-code']);
@ -856,6 +869,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'email' => 'user@@example.com',
],
@ -867,6 +881,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'ip' => '1.1.1.1.1',
],
@ -878,6 +893,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'url' => 'example...com',
],
@ -889,6 +905,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'range' => 11,
],
@ -900,6 +917,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'floatRange' => 2.5,
],
@ -911,6 +929,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'upperBound' => 11,
],
@ -922,6 +941,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'lowerBound' => 3,
],
@ -955,6 +975,7 @@ trait DatabaseBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'title' => 'Captain America',
'releaseYear' => 1944,

View file

@ -25,6 +25,7 @@ class DatabaseCustomServerTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => 'unique()',
'name' => 'Actors',
'read' => ['role:all'],
'write' => ['role:all'],
@ -74,6 +75,7 @@ class DatabaseCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'firstName' => 'Tom',
'lastName' => 'Holland',
@ -86,6 +88,7 @@ class DatabaseCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'firstName' => 'Samuel',
'lastName' => 'Jackson',

View file

@ -23,6 +23,7 @@ class FunctionsCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test',
'vars' => [
'funcKey1' => 'funcValue1',
@ -52,6 +53,7 @@ class FunctionsCustomClientTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'functionId' => 'unique()',
'name' => 'Test',
'execute' => ['user:'.$this->getUser()['$id']],
'runtime' => 'php-8.0',
@ -109,8 +111,6 @@ class FunctionsCustomClientTest extends Scope
'async' => 1,
]);
$executionId = $execution['body']['$id'] ?? '';
$this->assertEquals(201, $execution['headers']['status-code']);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([
@ -138,6 +138,7 @@ class FunctionsCustomClientTest extends Scope
'x-appwrite-project' => $projectId,
'x-appwrite-key' => $apikey,
], [
'functionId' => 'unique()',
'name' => 'Test',
'execute' => ['role:all'],
'runtime' => 'php-8.0',

View file

@ -23,6 +23,7 @@ class FunctionsCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test',
'runtime' => 'php-8.0',
'vars' => [
@ -461,6 +462,7 @@ class FunctionsCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test '.$name,
'runtime' => $name,
'vars' => [],
@ -539,6 +541,7 @@ class FunctionsCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test '.$name,
'runtime' => $name,
'vars' => [],

View file

@ -23,6 +23,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Project Test',
]);
@ -34,6 +35,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => 'Project Test',
'teamId' => $team['body']['$id'],
]);
@ -55,6 +57,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => '',
'teamId' => $team['body']['$id'],
]);
@ -65,6 +68,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => 'Project Test',
]);
@ -211,6 +215,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => 'Project Test 2',
]);
@ -231,6 +236,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => '',
]);
@ -275,8 +281,8 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals($id, $response['body']['$id']);
foreach ($providers as $key => $provider) {
$this->assertEquals('AppId-'.ucfirst($key), $response['body']['usersOauth2'.ucfirst($key).'Appid']);
$this->assertEquals('Secret-'.ucfirst($key), $response['body']['usersOauth2'.ucfirst($key).'Secret']);
$this->assertEquals('AppId-'.ucfirst($key), $response['body']['provider'.ucfirst($key).'Appid']);
$this->assertEquals('Secret-'.ucfirst($key), $response['body']['provider'.ucfirst($key).'Secret']);
}
/**
@ -314,6 +320,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $id,
]), [
'userId' => 'unique()',
'email' => $originalEmail,
'password' => $originalPassword,
'name' => $originalName,
@ -351,7 +358,7 @@ class ProjectsConsoleClientTest extends Scope
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertNotEmpty($response['body']['$id']);
$this->assertEquals(false, $response['body'][$method['key']]);
$this->assertEquals(false, $response['body']['auth'. ucfirst($method['key'])]);
}
$email = uniqid().'user@localhost.test';
@ -366,6 +373,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $id,
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -378,6 +386,7 @@ class ProjectsConsoleClientTest extends Scope
'x-appwrite-project' => $id,
'cookie' => 'a_session_'.$id.'='.$session,
]), [
'teamId' => 'unique()',
'name' => 'Arsenal'
]);
@ -471,6 +480,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $id,
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -496,6 +506,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $id,
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -513,6 +524,7 @@ class ProjectsConsoleClientTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
]), [
'teamId' => 'unique()',
'name' => 'Project Test',
]);
$this->assertEquals(201, $team['headers']['status-code']);
@ -523,6 +535,7 @@ class ProjectsConsoleClientTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_console=' . $this->getRoot()['session'],
]), [
'projectId' => 'unique()',
'name' => 'Project Test',
'teamId' => $team['body']['$id'],
]);
@ -655,6 +668,7 @@ class ProjectsConsoleClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $id,
]), [
'teamId' => 'unique()',
'name' => 'Arsenal'
]);

View file

@ -17,6 +17,7 @@ trait StorageBase
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'fileId' => 'unique()',
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
'read' => ['role:all'],
'write' => ['role:all'],

View file

@ -15,6 +15,7 @@ trait TeamsBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Arsenal'
]);
@ -28,15 +29,18 @@ trait TeamsBase
$teamUid = $response1['body']['$id'];
$teamName = $response1['body']['name'];
$teamId = \uniqid();
$response2 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => $teamId,
'name' => 'Manchester United'
]);
$this->assertEquals(201, $response2['headers']['status-code']);
$this->assertNotEmpty($response2['body']['$id']);
$this->assertEquals($teamId, $response2['body']['$id']);
$this->assertEquals('Manchester United', $response2['body']['name']);
$this->assertGreaterThan(-1, $response2['body']['sum']);
$this->assertIsInt($response2['body']['sum']);
@ -46,6 +50,7 @@ trait TeamsBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Newcastle'
]);
@ -183,6 +188,7 @@ trait TeamsBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Demo'
]);
@ -197,6 +203,7 @@ trait TeamsBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Demo New'
]);
@ -230,6 +237,7 @@ trait TeamsBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Demo'
]);

View file

@ -384,8 +384,7 @@ trait TeamsBaseClient
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertCount(1, $response['body']['memberships']);
$this->assertEquals(404, $response['headers']['status-code']);
return [];
}

View file

@ -15,6 +15,7 @@ trait UsersBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'userId' => 'unique()',
'email' => 'users.service@example.com',
'password' => 'password',
'name' => 'Project User',
@ -26,6 +27,26 @@ trait UsersBase
$this->assertEquals($user['body']['status'], true);
$this->assertGreaterThan(0, $user['body']['registration']);
/**
* Test Create with Custom ID for SUCCESS
*/
$res = $this->client->call(Client::METHOD_POST, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'userId' => 'user1',
'email' => 'users.service1@example.com',
'password' => 'password',
'name' => 'Project User',
]);
$this->assertEquals($res['headers']['status-code'], 201);
$this->assertEquals($res['body']['$id'], 'user1');
$this->assertEquals($res['body']['name'], 'Project User');
$this->assertEquals($res['body']['email'], 'users.service1@example.com');
$this->assertEquals(true, $res['body']['status']);
$this->assertGreaterThan(0, $res['body']['registration']);
return ['userId' => $user['body']['$id']];
}
@ -86,9 +107,9 @@ trait UsersBase
$this->assertIsArray($users['body']);
$this->assertIsArray($users['body']['users']);
$this->assertIsInt($users['body']['sum']);
$this->assertEquals(1, $users['body']['sum']);
$this->assertEquals(2, $users['body']['sum']);
$this->assertGreaterThan(0, $users['body']['sum']);
$this->assertCount(1, $users['body']['users']);
$this->assertCount(2, $users['body']['users']);
return $data;
}

View file

@ -17,6 +17,7 @@ trait WebhooksBase
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => 'unique()',
'name' => 'Actors',
'read' => ['role:all'],
'write' => ['role:all'],
@ -106,6 +107,7 @@ trait WebhooksBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'firstName' => 'Chris',
'lastName' => 'Evans',
@ -191,6 +193,7 @@ trait WebhooksBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'firstName' => 'Bradly',
'lastName' => 'Cooper',
@ -240,6 +243,7 @@ trait WebhooksBase
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'fileId' => 'unique()',
'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'),
'read' => ['role:all'],
'write' => ['role:all'],
@ -362,6 +366,7 @@ trait WebhooksBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Arsenal'
]);
@ -439,6 +444,7 @@ trait WebhooksBase
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Chelsea'
]);

View file

@ -27,6 +27,7 @@ class WebhooksCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -77,6 +78,7 @@ class WebhooksCustomClientTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,

View file

@ -122,6 +122,7 @@ class WebhooksCustomServerTest extends Scope
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'collectionId' => 'unique()',
'name' => 'Demo',
'read' => ['role:all'],
'write' => ['role:all'],
@ -171,6 +172,7 @@ class WebhooksCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,
@ -322,6 +324,7 @@ class WebhooksCustomServerTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test',
'execute' => ['role:all'],
'runtime' => 'php-8.0',
@ -474,7 +477,7 @@ class WebhooksCustomServerTest extends Scope
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
], $this->getHeaders()), ['executionId' => 'unique()',]);
$this->assertEquals($execution['headers']['status-code'], 201);
$this->assertNotEmpty($execution['body']['$id']);

View file

@ -23,6 +23,7 @@ class WebhooksTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'teamId' => 'unique()',
'name' => 'Project Test',
]);
@ -34,6 +35,7 @@ class WebhooksTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => 'Project Test',
'teamId' => $team['body']['$id'],
]);
@ -55,6 +57,7 @@ class WebhooksTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'projectId' => 'unique()',
'name' => '',
'teamId' => $team['body']['$id'],
]);
@ -129,6 +132,7 @@ class WebhooksTest extends Scope
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
]), [
'userId' => 'unique()',
'email' => $email,
'password' => $password,
'name' => $name,

View file

@ -0,0 +1,41 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Database\Validator\CustomId;
use PHPUnit\Framework\TestCase;
class CustomIdTest extends TestCase
{
/**
* @var Key
*/
protected $object = null;
public function setUp(): void
{
$this->object = new CustomId();
}
public function tearDown(): void
{
}
public function testValues()
{
$this->assertEquals($this->object->isValid('unique()'), true);
$this->assertEquals($this->object->isValid('unique)'), false);
$this->assertEquals($this->object->isValid('else()'), false);
$this->assertEquals($this->object->isValid('dasda asdasd'), false);
$this->assertEquals($this->object->isValid('dasda_asdasd'), true);
$this->assertEquals($this->object->isValid('asdasdasdas'), true);
$this->assertEquals($this->object->isValid('_asdasdasdas'), false);
$this->assertEquals($this->object->isValid('as$$5dasdasdas'), false);
$this->assertEquals($this->object->isValid(false), false);
$this->assertEquals($this->object->isValid(null), false);
$this->assertEquals($this->object->isValid('socialAccountForYoutubeAndRestSubscribers'), false);
$this->assertEquals($this->object->isValid('socialAccountForYoutubeAndRSubscriber'), false);
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscribe'), true);
$this->assertEquals($this->object->isValid('socialAccountForYoutubeSubscrib'), true);
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Appwrite\Tests;
use Appwrite\Stats\Stats;
use PHPUnit\Framework\TestCase;
use Utopia\App;
class StatsTest extends TestCase
{
/**
* @var Stats
*/
protected $object = null;
public function setUp(): void
{
$host = App::getEnv('_APP_STATSD_HOST', 'telegraf');
$port = App::getEnv('_APP_STATSD_PORT', 8125);
$connection = new \Domnikl\Statsd\Connection\UdpSocket($host, $port);
$statsd = new \Domnikl\Statsd\Client($connection);
$this->object = new Stats($statsd);
}
public function tearDown(): void
{
}
public function testNamespace()
{
$this->object->setNamespace('appwritetest.usage');
$this->assertEquals('appwritetest.usage', $this->object->getNamespace());
}
public function testParams()
{
$this->object
->setParam('projectId', 'appwrite_test')
->setParam('networkRequestSize', 100)
;
$this->assertEquals('appwrite_test', $this->object->getParam('projectId'));
$this->assertEquals(100, $this->object->getParam('networkRequestSize'));
$this->object->submit();
$this->assertEquals(null, $this->object->getParam('projectId'));
$this->assertEquals(null, $this->object->getParam('networkRequestSize'));
}
public function testReset()
{
$this->object
->setParam('projectId', 'appwrite_test')
->setParam('networkRequestSize', 100)
;
$this->assertEquals('appwrite_test', $this->object->getParam('projectId'));
$this->assertEquals(100, $this->object->getParam('networkRequestSize'));
$this->object->reset();
$this->assertEquals(null, $this->object->getParam('projectId'));
$this->assertEquals(null, $this->object->getParam('networkRequestSize'));
$this->assertEquals('appwrite.usage', $this->object->getNamespace());
}
}