Merge branch 'master' of github.com:appwrite/appwrite into preloader

This commit is contained in:
Eldad Fux
2020-06-05 00:54:07 +03:00
92 changed files with 551 additions and 256 deletions
+14 -3
View File
@@ -1,20 +1,31 @@
# Version 0.7.0 (NOT-RELEASED)
## Features
- New route in Locale API to fetch a list of languages
## Bug Fixes
- Fixed output of /v1/health/queue/certificates returning wrong data
# Version 0.6.2 (PRE-RELEASE)
## Features
- New route in Locale API to fetch list of languages
- New OAuth adapter for sign-in with Apple
## Bug Fixes
- Fixed custom domain not setting correct domain
- Fixed wrong SDK method type in avatars browser route
- Fixed bug denied public documents (*) to be accessed by guest users
- Fixed cache control issue not allowing collection UI to update properly
- Fixed cache-control issue not allowing collection UI to update properly
- Fixed a bug where single permission tag in the console was not being saved
- Added missing webhooks events in the console
- Added missing option to delete project
- Fixed a bug where the session was not set properly when the API used an IP with non-standard port as hostname
- Fixed a bug where the session was not set properly when the API used an IP with a non-standard port as hostname
- Fixed bug where requests number on the dashboard was hidden when the number got too long
- Permission fields are not required for file creation or update
## Security
+3 -3
View File
@@ -51,7 +51,7 @@ The easiest way to start running your Appwrite server is by running our docker-c
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/install/appwrite:rw \
-e version=0.6.1 \
-e version=0.6.2 \
appwrite/install
```
@@ -63,7 +63,7 @@ docker run -it --rm \
docker run -it --rm ^
--volume //var/run/docker.sock:/var/run/docker.sock ^
--volume "%cd%"/appwrite:/install/appwrite:rw ^
-e version=0.6.1 ^
-e version=0.6.2 ^
appwrite/install
```
@@ -73,7 +73,7 @@ docker run -it --rm ^
docker run -it --rm ,
--volume /var/run/docker.sock:/var/run/docker.sock ,
--volume ${pwd}/appwrite:/install/appwrite:rw ,
-e version=0.6.1 ,
-e version=0.6.2 ,
appwrite/install
```
+1
View File
@@ -104,6 +104,7 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
if(!$originValidator->isValid($origin)
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& $route->getLabel('origin', false) !== '*'
&& empty($request->getHeader('X-Appwrite-Key', ''))) {
throw new Exception($originValidator->getDescription(), 403);
}
+1 -1
View File
@@ -184,7 +184,7 @@ return [
[
'key' => 'ruby',
'name' => 'Ruby',
'version' => '1.0.10',
'version' => '1.0.11',
'url' => 'https://github.com/appwrite/sdk-for-ruby',
'enabled' => true,
'beta' => true,
+52 -6
View File
@@ -5,138 +5,182 @@ return [
'developers' => 'https://developer.atlassian.com/bitbucket',
'icon' => 'icon-bitbucket',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'facebook' => [
'developers' => 'https://developers.facebook.com/',
'icon' => 'icon-facebook',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'github' => [
'developers' => 'https://developer.github.com/',
'icon' => 'icon-github-circled',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'gitlab' => [
'developers' => 'https://docs.gitlab.com/ee/api/',
'icon' => 'icon-gitlab',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'google' => [
'developers' => 'https://developers.google.com/',
'icon' => 'icon-google',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
// 'instagram' => [
// 'developers' => 'https://www.instagram.com/developer/',
// 'icon' => 'icon-instagram',
// 'enabled' => false,
// 'beta' => false,
// 'mock' => false,
// ],
'microsoft' => [
'developers' => 'https://developer.microsoft.com/en-us/',
'icon' => 'icon-windows',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
// 'twitter' => [
// 'developers' => 'https://developer.twitter.com/',
// 'icon' => 'icon-twitter',
// 'enabled' => false,
// 'beta' => false,
// 'mock' => false,
// ],
'linkedin' => [
'developers' => 'https://developer.linkedin.com/',
'icon' => 'icon-linkedin',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'slack' => [
'developers' => 'https://api.slack.com/',
'icon' => 'icon-slack',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'dropbox' => [
'developers' => 'https://www.dropbox.com/developers/documentation',
'icon' => 'icon-dropbox',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'salesforce' => [
'developers' => 'https://developer.salesforce.com/docs/',
'icon' => 'icon-salesforce',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'apple' => [
'developers' => 'https://developer.apple.com/',
'icon' => 'icon-apple',
'enabled' => true,
'form' => 'apple.phtml', // Perperation for adding ability to customized OAuth UI forms, currently handled hardcoded.
'beta' => true,
'mock' => false,
],
// 'apple' => [
// 'developers' => 'https://developer.apple.com/',
// 'icon' => 'icon-apple',
// 'enabled' => false,
// 'mock' => false,
// ],
'amazon' => [
'developers' => 'https://developer.amazon.com/apps-and-games/services-and-apis',
'icon' => 'icon-amazon',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'vk' => [
'developers' => 'https://vk.com/dev',
'icon' => 'icon-vk',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'discord' => [
'developers' => 'https://discordapp.com/developers/docs/topics/oauth2',
'icon' => 'icon-discord',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'twitch' => [
'developers' => 'https://dev.twitch.tv/docs/authentication',
'icon' => 'icon-twitch',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'spotify' => [
'developers' => 'https://developer.spotify.com/documentation/general/guides/authorization-guide/',
'icon' => 'icon-spotify',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'yahoo' => [
'developers' => 'https://developer.yahoo.com/oauth2/guide/flows_authcode/',
'icon' => 'icon-yahoo',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'yandex' => [
'developers' => 'https://tech.yandex.com/oauth/',
'icon' => 'icon-yandex',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false,
],
'twitter' => [
'developers' => 'https://developer.twitter.com/',
'icon' => 'icon-twitter',
'enabled' => false,
'form' => false,
'beta' => false,
'mock' => false
],
'paypal' => [
'developers' => 'https://developer.paypal.com/docs/api/overview/',
'icon' => 'icon-paypal',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false
],
'bitly' => [
'developers' => 'https://dev.bitly.com/v4_documentation.html',
'icon' => 'icon-bitly',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => false
],
// Keep Last
@@ -144,6 +188,8 @@ return [
'developers' => 'https://appwrite.io',
'icon' => 'icon-appwrite',
'enabled' => true,
'form' => false,
'beta' => false,
'mock' => true,
]
];
+31 -7
View File
@@ -57,7 +57,7 @@ $utopia->post('/v1/account')
->label('sdk.description', '/docs/references/account/create.md')
->label('abuse-limit', 10)
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->param('name', '', function () { return new Text(100); }, 'User name.', true)
->action(
function ($email, $password, $name) use ($register, $request, $response, $audit, $projectDB, $project, $webhook, $oauth2Keys) {
@@ -158,7 +158,7 @@ $utopia->post('/v1/account/sessions')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},email:{param-email}')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->action(
function ($email, $password) use ($response, $request, $projectDB, $audit, $webhook) {
$protocol = Config::getParam('protocol');
@@ -308,6 +308,29 @@ $utopia->get('/v1/account/sessions/oauth2/callback/:provider/:projectId')
}
);
$utopia->post('/v1/account/sessions/oauth2/callback/:provider/:projectId')
->desc('OAuth2 Callback')
->label('error', __DIR__.'/../../views/general/error.phtml')
->label('scope', 'public')
->label('origin', '*')
->label('docs', false)
->param('projectId', '', function () { return new Text(1024); }, 'Project unique ID.')
->param('provider', '', function () { return new WhiteList(array_keys(Config::getParam('providers'))); }, 'OAuth2 provider.')
->param('code', '', function () { return new Text(1024); }, 'OAuth2 code.')
->param('state', '', function () { return new Text(2048); }, 'Login state params.', true)
->action(
function ($projectId, $provider, $code, $state) use ($response) {
$domain = Config::getParam('domain');
$protocol = Config::getParam('protocol');
$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]));
}
);
$utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
->desc('OAuth2 Redirect')
->label('error', __DIR__.'/../../views/general/error.phtml')
@@ -361,6 +384,7 @@ $utopia->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);
@@ -721,8 +745,8 @@ $utopia->patch('/v1/account/password')
->label('sdk.namespace', 'account')
->label('sdk.method', 'updatePassword')
->label('sdk.description', '/docs/references/account/update-password.md')
->param('password', '', function () { return new Password(); }, 'New user password.')
->param('oldPassword', '', function () { return new Password(); }, 'Old user password.')
->param('password', '', function () { return new Password(); }, 'New user password. Must be between 6 to 32 chars.')
->param('oldPassword', '', function () { return new Password(); }, 'Old user password. Must be between 6 to 32 chars.')
->action(
function ($password, $oldPassword) use ($response, $user, $projectDB, $audit, $oauth2Keys) {
if (!Auth::passwordVerify($oldPassword, $user->getAttribute('password'))) { // Double check user password
@@ -764,7 +788,7 @@ $utopia->patch('/v1/account/email')
->label('sdk.method', 'updateEmail')
->label('sdk.description', '/docs/references/account/update-email.md')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->action(
function ($email, $password) use ($response, $user, $projectDB, $audit, $oauth2Keys) {
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
@@ -1120,8 +1144,8 @@ $utopia->put('/v1/account/recovery')
->label('abuse-key', 'url:{url},userId:{param-userId}')
->param('userId', '', function () { return new UID(); }, 'User account UID address.')
->param('secret', '', function () { return new Text(256); }, 'Valid reset token.')
->param('password', '', function () { return new Password(); }, 'New password.')
->param('passwordAgain', '', function () {return new Password(); }, 'New password again.')
->param('password', '', function () { return new Password(); }, 'New password. Must be between 6 to 32 chars.')
->param('passwordAgain', '', function () {return new Password(); }, 'New password again. Must be between 6 to 32 chars.')
->action(
function ($userId, $secret, $password, $passwordAgain) use ($response, $projectDB, $audit) {
if ($password !== $passwordAgain) {
+1 -1
View File
@@ -158,7 +158,7 @@ $utopia->get('/v1/health/queue/certificates')
->label('sdk.description', '/docs/references/health/get-queue-certificates.md')
->action(
function () use ($response) {
$response->json(['size' => Resque::size('v1-usage')]);
$response->json(['size' => Resque::size('v1-certificates')]);
}
);
+2 -2
View File
@@ -361,7 +361,7 @@ $utopia->patch('/v1/projects/:projectId/oauth2')
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
->param('provider', '', function () { return new WhiteList(array_keys(Config::getParam('providers'))); }, 'Provider Name', false)
->param('appId', '', function () { return new Text(256); }, 'Provider app ID.', true)
->param('secret', '', function () { return new text(256); }, 'Provider secret key.', true)
->param('secret', '', function () { return new text(512); }, 'Provider secret key.', true)
->action(
function ($projectId, $provider, $appId, $secret) use ($request, $response, $consoleDB) {
$project = $consoleDB->getDocument($projectId);
@@ -400,7 +400,7 @@ $utopia->delete('/v1/projects/:projectId')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'delete')
->param('projectId', '', function () { return new UID(); }, 'Project unique ID.')
->param('password', '', function () { return new UID(); }, 'Your user password for confirmation.')
->param('password', '', function () { return new UID(); }, 'Your user password for confirmation. Must be between 6 to 32 chars.')
->action(
function ($projectId, $password) use ($response, $consoleDB, $user, $deletes) {
if (!Auth::passwordVerify($password, $user->getAttribute('password'))) { // Double check user password
+1 -1
View File
@@ -31,7 +31,7 @@ $utopia->post('/v1/users')
->label('sdk.method', 'create')
->label('sdk.description', '/docs/references/users/create-user.md')
->param('email', '', function () { return new Email(); }, 'User email.')
->param('password', '', function () { return new Password(); }, 'User password.')
->param('password', '', function () { return new Password(); }, 'User password. Must be between 6 to 32 chars.')
->param('name', '', function () { return new Text(100); }, 'User name.', true)
->action(
function ($email, $password, $name) use ($response, $projectDB) {
+1 -1
View File
@@ -33,7 +33,7 @@ const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 15;
const APP_CACHE_BUSTER = 125;
const APP_VERSION_STABLE = '0.6.1';
const APP_VERSION_STABLE = '0.6.2';
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_CERTIFICATES = '/storage/certificates';
+1 -1
View File
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.name = 'appwrite'
s.version = '1.0.10'
s.version = '1.0.11'
s.summary = "Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way.
Use the Ruby SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools.
For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)"
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
avatars = Appwrite::Avatars.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
database = Appwrite::Database.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
health = Appwrite::Health.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
locale = Appwrite::Locale.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
storage = Appwrite::Storage.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
teams = Appwrite::Teams.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
@@ -4,8 +4,8 @@ client = Appwrite::Client.new()
client
.set_endpoint('https://[HOSTNAME_OR_IP]/v1') # Your API Endpoint
.setproject('5df5acd0d48c2') # Your project ID
.setkey('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
.set_project('5df5acd0d48c2') # Your project ID
.set_key('919c2d18fb5d4...a2ae413da83346ad2') # Your secret API key
;
users = Appwrite::Users.new(client);
+1 -1
View File
@@ -20,7 +20,7 @@ module Appwrite
@headers = {
'content-type' => '',
'user-agent' => RUBY_PLATFORM + ':ruby-' + RUBY_VERSION,
'x-sdk-version' => 'appwrite:ruby:1.0.10'
'x-sdk-version' => 'appwrite:ruby:1.0.11'
}
@endpoint = 'https://appwrite.io/v1';
end
@@ -33,7 +33,7 @@ module Appwrite
def get_collection(collection_id:)
path = '/database/collections/{collectionId}'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
}
@@ -45,7 +45,7 @@ module Appwrite
def update_collection(collection_id:, name:, read:, write:, rules: [])
path = '/database/collections/{collectionId}'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
'name': name,
@@ -61,7 +61,7 @@ module Appwrite
def delete_collection(collection_id:)
path = '/database/collections/{collectionId}'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
}
@@ -73,7 +73,7 @@ module Appwrite
def list_documents(collection_id:, filters: [], offset: 0, limit: 50, order_field: '$id', order_type: 'ASC', order_cast: 'string', search: '', first: 0, last: 0)
path = '/database/collections/{collectionId}/documents'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
'filters': filters,
@@ -94,7 +94,7 @@ module Appwrite
def create_document(collection_id:, data:, read:, write:, parent_document: '', parent_property: '', parent_property_type: 'assign')
path = '/database/collections/{collectionId}/documents'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
'data': data,
@@ -112,8 +112,8 @@ module Appwrite
def get_document(collection_id:, document_id:)
path = '/database/collections/{collectionId}/documents/{documentId}'
.gsub('{collection_id}', collection_id)
.gsub('{document_id}', document_id)
.gsub('{collectionId}', collection_id)
.gsub('{documentId}', document_id)
params = {
}
@@ -125,8 +125,8 @@ module Appwrite
def update_document(collection_id:, document_id:, data:, read:, write:)
path = '/database/collections/{collectionId}/documents/{documentId}'
.gsub('{collection_id}', collection_id)
.gsub('{document_id}', document_id)
.gsub('{collectionId}', collection_id)
.gsub('{documentId}', document_id)
params = {
'data': data,
@@ -141,8 +141,8 @@ module Appwrite
def delete_document(collection_id:, document_id:)
path = '/database/collections/{collectionId}/documents/{documentId}'
.gsub('{collection_id}', collection_id)
.gsub('{document_id}', document_id)
.gsub('{collectionId}', collection_id)
.gsub('{documentId}', document_id)
params = {
}
@@ -154,7 +154,7 @@ module Appwrite
def get_collection_logs(collection_id:)
path = '/database/collections/{collectionId}/logs'
.gsub('{collection_id}', collection_id)
.gsub('{collectionId}', collection_id)
params = {
}
@@ -32,7 +32,7 @@ module Appwrite
def get_file(file_id:)
path = '/storage/files/{fileId}'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
}
@@ -44,7 +44,7 @@ module Appwrite
def update_file(file_id:, read:, write:)
path = '/storage/files/{fileId}'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
'read': read,
@@ -58,7 +58,7 @@ module Appwrite
def delete_file(file_id:)
path = '/storage/files/{fileId}'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
}
@@ -70,7 +70,7 @@ module Appwrite
def get_file_download(file_id:)
path = '/storage/files/{fileId}/download'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
}
@@ -82,7 +82,7 @@ module Appwrite
def get_file_preview(file_id:, width: 0, height: 0, quality: 100, background: '', output: '')
path = '/storage/files/{fileId}/preview'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
'width': width,
@@ -99,7 +99,7 @@ module Appwrite
def get_file_view(file_id:, as: '')
path = '/storage/files/{fileId}/view'
.gsub('{file_id}', file_id)
.gsub('{fileId}', file_id)
params = {
'as': as
@@ -31,7 +31,7 @@ module Appwrite
def get(team_id:)
path = '/teams/{teamId}'
.gsub('{team_id}', team_id)
.gsub('{teamId}', team_id)
params = {
}
@@ -43,7 +43,7 @@ module Appwrite
def update(team_id:, name:)
path = '/teams/{teamId}'
.gsub('{team_id}', team_id)
.gsub('{teamId}', team_id)
params = {
'name': name
@@ -56,7 +56,7 @@ module Appwrite
def delete(team_id:)
path = '/teams/{teamId}'
.gsub('{team_id}', team_id)
.gsub('{teamId}', team_id)
params = {
}
@@ -68,7 +68,7 @@ module Appwrite
def get_memberships(team_id:)
path = '/teams/{teamId}/memberships'
.gsub('{team_id}', team_id)
.gsub('{teamId}', team_id)
params = {
}
@@ -80,7 +80,7 @@ module Appwrite
def create_membership(team_id:, email:, roles:, url:, name: '')
path = '/teams/{teamId}/memberships'
.gsub('{team_id}', team_id)
.gsub('{teamId}', team_id)
params = {
'email': email,
@@ -96,8 +96,8 @@ module Appwrite
def delete_membership(team_id:, invite_id:)
path = '/teams/{teamId}/memberships/{inviteId}'
.gsub('{team_id}', team_id)
.gsub('{invite_id}', invite_id)
.gsub('{teamId}', team_id)
.gsub('{inviteId}', invite_id)
params = {
}
@@ -32,7 +32,7 @@ module Appwrite
def get(user_id:)
path = '/users/{userId}'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
}
@@ -44,7 +44,7 @@ module Appwrite
def get_logs(user_id:)
path = '/users/{userId}/logs'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
}
@@ -56,7 +56,7 @@ module Appwrite
def get_prefs(user_id:)
path = '/users/{userId}/prefs'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
}
@@ -68,7 +68,7 @@ module Appwrite
def update_prefs(user_id:, prefs:)
path = '/users/{userId}/prefs'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
'prefs': prefs
@@ -81,7 +81,7 @@ module Appwrite
def get_sessions(user_id:)
path = '/users/{userId}/sessions'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
}
@@ -93,7 +93,7 @@ module Appwrite
def delete_sessions(user_id:)
path = '/users/{userId}/sessions'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
}
@@ -105,8 +105,8 @@ module Appwrite
def delete_session(user_id:, session_id:)
path = '/users/{userId}/sessions/{sessionId}'
.gsub('{user_id}', user_id)
.gsub('{session_id}', session_id)
.gsub('{userId}', user_id)
.gsub('{sessionId}', session_id)
params = {
}
@@ -118,7 +118,7 @@ module Appwrite
def update_status(user_id:, status:)
path = '/users/{userId}/status'
.gsub('{user_id}', user_id)
.gsub('{userId}', user_id)
params = {
'status': status
+4 -1
View File
@@ -174,9 +174,10 @@ $rules = $collection->getAttribute('rules', []);
data-scope="sdk"
data-event="submit"
data-param-collection-id="{{router.params.id}}"
data-success="alert,trigger"
data-success="alert,trigger,redirect"
data-success-param-alert-text="Updated collection successfully"
data-success-param-trigger-events="database.updateCollection"
data-success-param-redirect-url="/console/database/collection/settings?id={{serviceData.$id}}&project={{router.params.project}}"
data-failure="alert"
data-failure-param-alert-text="Failed to update collection"
data-failure-param-alert-classname="error">
@@ -308,9 +309,11 @@ $rules = $collection->getAttribute('rules', []);
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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>
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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>
<button>Update</button>
+3 -1
View File
@@ -254,9 +254,11 @@ $collections = [];
<label for="collection-read">Read Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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>
<label for="collection-write">Write Access <span class="text-size-small">(<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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>
<button data-ls-if="({{project-document.$id}})">Update</button>
+1 -1
View File
@@ -41,7 +41,7 @@ $graph = $this->getParam('graph', false);
<div class="chart-metric">
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.requests.total|statsTotal}}">N/A</span></div>
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests this month"><i class="icon-info-circled"></i></span></div>
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests last 30 days"><i class="icon-info-circled"></i></span></div>
<div class="range">Last 30 days</div>
</div>
</div>
+15 -11
View File
@@ -17,7 +17,7 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<li data-state="/console/database?project={{router.params.project}}">
<h2 class="margin-bottom">Files</h2>
<div data-ui-modal class="box modal close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
<div data-ui-modal class="box modal sticky-footer close" data-button-text="" data-button-class="fly round" data-button-icon="icon-plus">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1>Upload File</h1>
@@ -41,17 +41,19 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
<label for="file-read">File</label>
<input type="file" name="file" id="file-file" size="1" required>
<div class="text-fade text-size-small margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
<input type="hidden" id="file-read" name="read" required data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" />
<input type="hidden" id="file-read" name="read" data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" 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>
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
<input type="hidden" id="file-write" name="write" required data-forms-tags data-cast-to="json" value="<?php echo htmlentities(json_encode(['*'])); ?>" />
<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>
<hr />
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
<footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
</footer>
</form>
</div>
@@ -141,11 +143,13 @@ $fileLimitHuman = $this->getParam('fileLimitHuman', 0);
</div>
<input type="hidden" data-ls-attrs="id=file-folderId-{{file.$id}}" name="folderId" data-cast-to="int" value="1">
<label for="file-read">Read Permissions (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-read-{{file.$id}}" name="read" required data-forms-tags data-cast-to="json" data-ls-bind="{{file.$permissions.read}}" />
<label for="file-read">Read Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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.$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>
<label for="file-write">Write Permissions (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">Learn more</a>)</label>
<input type="hidden" data-ls-attrs="id=file-write-{{file.$id}}" name="write" required data-forms-tags data-cast-to="json" data-ls-bind="{{file.$permissions.write}}" />
<label for="file-write">Write Access (<a data-ls-attrs="href={{env.HOME}}/docs/permissions" target="_blank">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.$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>
</form>
<form class="strip"
+24 -15
View File
@@ -337,12 +337,14 @@ $providers = $this->getParam('providers', []);
<?php foreach ($providers as $provider => $data):
if (isset($data['enabled']) && !$data['enabled']) { continue; }
if (isset($data['mock']) && $data['mock']) { continue; }
$form = (isset($data['form'])) ? $data['form'] : false;
$beta = (isset($data['beta'])) ? $data['beta'] : false;
?>
<li class="clear <?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 ucfirst($provider); ?> OAuth2 Settings</h1>
<h1><?php echo $this->escape(ucfirst($provider)); ?> OAuth2 Settings</h1>
<form
data-analytics-event="submit"
@@ -358,23 +360,30 @@ $providers = $this->getParam('providers', []);
data-failure="alert"
data-failure-param-alert-text="Failed to update project OAuth2 settings"
data-failure-param-alert-classname="error">
<input name="provider" id="provider<?php echo ucfirst($provider); ?>" type="hidden" autocomplete="off" value="<?php echo $provider; ?>">
<input name="provider" id="provider<?php echo $this->escape(ucfirst($provider)); ?>" type="hidden" autocomplete="off" value="<?php echo $this->escape($provider); ?>">
<label for="oauth2<?php echo ucfirst($provider); ?>Appid">App ID</label>
<input name="appId" id="oauth2<?php echo ucfirst($provider); ?>Appid" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}}">
<?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}}">
<label for="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret">App Secret</label>
<input name="secret" id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?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" />
<label for="oauth2<?php echo ucfirst($provider); ?>Secret">App Secret</label>
<input name="secret" id="oauth2<?php echo ucfirst($provider); ?>Secret" type="text" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
<input name="secret" data-forms-oauth-apple id="oauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid" type="hidden" autocomplete="off" data-ls-bind="{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}" />
<?php endif; ?>
<div class="info row thin margin-bottom margin-top">
<div class="col span-1">
<i class="icon-info-circled text-sign"></i>
</div>
<div class="col span-11">
<p>To complete set up, add this OAuth2 redirect URI to your <?php echo ucfirst($provider); ?> app configuration.</p>
<p>To complete set up, add this OAuth2 redirect URI to your <?php echo $this->escape(ucfirst($provider)); ?> app configuration.</p>
<div class="input-copy">
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1/account/sessions/oauth2/callback/<?php echo $provider; ?>/{{router.params.project}}" class="margin-bottom-no" />
<input data-forms-copy type="text" disabled data-ls-bind="{{env.PROTOCOL}}://{{env.DOMAIN}}/v1/account/sessions/oauth2/callback/<?php echo $this->escape($provider); ?>/{{router.params.project}}" class="margin-bottom-no" />
</div>
</div>
</div>
@@ -384,19 +393,19 @@ $providers = $this->getParam('providers', []);
</div>
<span data-ls-if="
{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}} &&
{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} &&
{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<button class="switch on pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $provider; ?>"></button>
</span>
<span data-ls-if="
!{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Appid}} ||
!{{console-project.usersOauth2<?php echo ucfirst($provider); ?>Secret}}">
<button class="switch pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $provider; ?>"></button>
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Appid}} ||
!{{console-project.usersOauth2<?php echo $this->escape(ucfirst($provider)); ?>Secret}}">
<button class="switch pull-end margin-top-small" data-ls-ui-trigger="provider-update-<?php echo $this->escape($provider); ?>"></button>
</span>
<img src="/images/oauth2/<?php echo strtolower($provider); ?>.png?buster=<?php echo APP_CACHE_BUSTER; ?>" alt="<?php echo ucfirst($provider); ?> Logo" class="pull-start provider margin-end" />
<img src="/images/oauth2/<?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>
<?php echo ucfirst($provider); ?>
<?php echo ucfirst($provider); ?> <?php if($beta): ?>(beta)<?php endif; ?>
</span>
<p class="margin-bottom-no margin-top-small text-one-liner">
<a href="<?php echo $data['developers']; ?>" target="_blank" rel="noopener">OAuth2 Developer Docs<i class="icon-link-ext"></i></a>
Generated
+7 -7
View File
@@ -1741,7 +1741,7 @@
"source": {
"type": "git",
"url": "https://github.com/appwrite/sdk-generator",
"reference": "ca18c48a3252e1e2e7c7d823871cc4f3453b6ee0"
"reference": "a1672098ecc6a08cc400314e373b0d1cd5885f79"
},
"require": {
"ext-curl": "*",
@@ -1771,7 +1771,7 @@
}
],
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
"time": "2020-05-29T18:54:37+00:00"
"time": "2020-05-30T11:38:32+00:00"
},
{
"name": "doctrine/instantiator",
@@ -1779,16 +1779,16 @@
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "6a1471ddbf2f448b35f3a8e390c903435e6dd5de"
"reference": "a390fde13fc9bc2ffb73340bb8f07201a8e85af8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/6a1471ddbf2f448b35f3a8e390c903435e6dd5de",
"reference": "6a1471ddbf2f448b35f3a8e390c903435e6dd5de",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/a390fde13fc9bc2ffb73340bb8f07201a8e85af8",
"reference": "a390fde13fc9bc2ffb73340bb8f07201a8e85af8",
"shasum": ""
},
"require": {
"php": "^7.1"
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^6.0",
@@ -1827,7 +1827,7 @@
"constructor",
"instantiate"
],
"time": "2019-12-23T19:18:31+00:00"
"time": "2020-05-30T16:47:47+00:00"
},
{
"name": "matthiasmullie/minify",
+1 -1
View File
@@ -1 +1 @@
Create a new Document.
Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](/docs/server/database?sdk=nodejs#createCollection) API or directly from your database console.
+3 -3
View File
@@ -1,7 +1,7 @@
The Database service allows you to create structured collections of documents, query and filter lists of documents, and manage an advanced set of read and write access.
The Database service allows you to create structured collections of documents, query and filter lists of documents, and manage an advanced set of read and write access permissions.
All the data in the database service is stored in structured JSON documents. The Appwrite database service also allows you to nest child documents in documents and use advanced filters to both search and query the database just like you would with a classic graph database.
All the data in the database service is stored in structured JSON documents. The Appwrite database service also allows you to nest child documents in parent documents and use deep filters to both search and query your data.
Each database document structure in your project is defined using the Appwrite [collection rules](/docs/rules). The collections rules help you ensure all your user-submitted data is validated and stored according to the collection structure.
Using Appwrite permissions architecture, you can assign read or write access to each document in your project for either a specific user, team, user role, or even grant it with public access. You can learn more about [how Appwrite handles permissions and access control](/docs/permissions).
Using Appwrite permissions architecture, you can assign read or write access to each document in your project for either a specific user, team, user role, or even grant it with public access (*). You can learn more about [how Appwrite handles permissions and access control](/docs/permissions).
+1
View File
@@ -47,6 +47,7 @@ const configApp = {
'public/scripts/views/forms/move-down.js',
'public/scripts/views/forms/move-up.js',
'public/scripts/views/forms/nav.js',
'public/scripts/views/forms/oauth-apple.js',
'public/scripts/views/forms/password-meter.js',
'public/scripts/views/forms/pell.js',
'public/scripts/views/forms/remove.js',
+7 -3
View File
@@ -2402,7 +2402,7 @@ container.set(as,container.path(context),true,watch);container.set(key,index,tru
element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,repeat:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}else{if(debug){console.error('Missing template "'+source+'"');}}
if(!init){view.render(element);}
return;}
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){console.error("ERROR-APP",error);};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){window.location='/console';},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);window.location='/console';};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){window.location='/console';},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('console',function(window){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject('console').setLocale(APP_ENV.LOCALE);return sdk;},true);})(window);(function(window){"use strict";window.ls.container.set('date',function(){function format(format,timestamp){var jsdate,f
@@ -2568,7 +2568,7 @@ return"< 1s";}).add("markdown",function($value,markdown){return markdown.render(
let thresh=1000;if(Math.abs($value)<thresh){return $value+" B";}
let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;++u;}while(Math.abs($value)>=thresh&&u<units.length-1);return($value.toFixed(1)+'<span class="text-size-small unit">'+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmpty",function($value){return(!!$value);}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
$value=abbreviate($value,0,false,false);return $value==="0"?"N/A":$value;}).add("isEmpty",function($value){return(!!$value);}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
@@ -2640,7 +2640,11 @@ list["filters-"+filter.key]=params[key][i];}}}}
return list;};let apply=function(params){let cached=container.get(name);cached=cached?cached.params:[];params=Object.assign(cached,params);container.set(name,{name:name,params:params,query:serialize(params),forward:parseInt(params.offset)+parseInt(params.limit),backward:parseInt(params.offset)-parseInt(params.limit),keys:flatten(params)},true,name);document.dispatchEvent(new CustomEvent(name+"-changed",{bubbles:false,cancelable:true}));};switch(element.tagName){case"INPUT":break;case"TEXTAREA":break;case"BUTTON":element.addEventListener("click",function(){apply(JSON.parse(expression.parse(element.dataset["params"]||"{}")));});break;case"FORM":element.addEventListener("input",function(){apply(form.toJson(element));});element.addEventListener("change",function(){apply(form.toJson(element));});element.addEventListener("reset",function(){setTimeout(function(){apply(form.toJson(element));},0);});events=events.trim().split(",");for(let y=0;y<events.length;y++){if(events[y]==="init"){element.addEventListener("rendered",function(){apply(form.toJson(element));},{once:true});}else{}
element.setAttribute("data-event","none");}
break;default:break;}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-down",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-down]")).map(function(obj){obj.addEventListener("click",function(){if(element.nextElementSibling){element.parentNode.insertBefore(element.nextElementSibling,element);element.scrollIntoView(true);}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-up",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-up]")).map(function(obj){obj.addEventListener("click",function(){if(element.previousElementSibling){element.parentNode.insertBefore(element,element.previousElementSibling);element.scrollIntoView(true);}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-nav",repeat:false,controller:function(element,view,container,document){let titles=document.querySelectorAll('[data-forms-nav-anchor]');let links=element.querySelectorAll('[data-forms-nav-link]');let minLink=null;let check=function(){let minDistance=null;let minElement=null;for(let i=0;i<titles.length;++i){let title=titles[i];let distance=title.getBoundingClientRect().top;console.log(i);if((minDistance===null||minDistance>=distance)&&(distance>=0)){if(minLink){minLink.classList.remove('selected');}
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-password-meter",controller:function(element,window){var calc=function(password){var score=0;if(!password)return score;var letters=new window.Object();for(var i=0;i<password.length;i++){letters[password[i]]=(letters[password[i]]||0)+1;score+=5.0/letters[password[i]];}
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-oauth-apple",controller:function(element){let container=document.createElement("div");let row=document.createElement("div");let col1=document.createElement("div");let col2=document.createElement("div");let keyID=document.createElement("input");let keyLabel=document.createElement("label");let teamID=document.createElement("input");let teamLabel=document.createElement("label");let p8=document.createElement("textarea");let p8Label=document.createElement("label");keyLabel.textContent='Key ID';teamLabel.textContent='Team ID';p8Label.textContent='P8 File';row.classList.add('row');row.classList.add('thin');container.appendChild(row);container.appendChild(p8Label);container.appendChild(p8);row.appendChild(col1);row.appendChild(col2);col1.classList.add('col');col1.classList.add('span-6');col1.appendChild(keyLabel);col1.appendChild(keyID);col2.classList.add('col');col2.classList.add('span-6');col2.appendChild(teamLabel);col2.appendChild(teamID);keyID.type='text';keyID.placeholder='SHAB13ROFN';teamID.type='text';teamID.placeholder='ELA2CD3AED';p8.accept='.p8';p8.classList.add('margin-bottom-no');element.parentNode.insertBefore(container,element.nextSibling);element.addEventListener('change',sync);keyID.addEventListener('change',update);teamID.addEventListener('change',update);p8.addEventListener('change',update);function update(){let json={};json.keyID=keyID.value;json.teamID=teamID.value;json.p8=p8.value;element.value=JSON.stringify(json);}
function sync(){console.log('sync');if(!element.value){return;}
let json={};try{json=JSON.parse(element.value);}catch(error){console.error('Failed to parse secret key');}
teamID.value=json.teamID||'';keyID.value=json.keyID||'';p8.value=json.p8||'';}
sync();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-password-meter",controller:function(element,window){var calc=function(password){var score=0;if(!password)return score;var letters=new window.Object();for(var i=0;i<password.length;i++){letters[password[i]]=(letters[password[i]]||0)+1;score+=5.0/letters[password[i]];}
var variations={digits:/\d/.test(password),lower:/[a-z]/.test(password),upper:/[A-Z]/.test(password),nonWords:/\W/.test(password)};var variationCount=0;for(var check in variations){if(variations.hasOwnProperty(check)){variationCount+=variations[check]===true?1:0;}}
score+=(variationCount-1)*10;return parseInt(score);};var callback=function(){var score=calc(this.value);if(""===this.value)return(meter.className="password-meter");if(score>60)return(meter.className="password-meter strong");if(score>30)return(meter.className="password-meter medium");if(score>=0)return(meter.className="password-meter weak");};var meter=window.document.createElement("div");meter.className="password-meter";element.parentNode.insertBefore(meter,element.nextSibling);element.addEventListener("change",callback);element.addEventListener("keypress",callback);element.addEventListener("keyup",callback);element.addEventListener("keydown",callback);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-pell",controller:function(element,window,document,markdown,rtl){var div=document.createElement("div");element.className="pell hide";div.className="input pell";element.parentNode.insertBefore(div,element);element.tabIndex=-1;var turndownService=new TurndownService();turndownService.addRule("underline",{filter:["u"],replacement:function(content){return"__"+content+"__";}});var editor=window.pell.init({element:div,onChange:function onChange(html){alignText();element.value=turndownService.turndown(html);},defaultParagraphSeparator:"p",actions:[{name:"bold",icon:'<i class="icon-bold"></i>'},{name:"underline",icon:'<i class="icon-underline"></i>'},{name:"italic",icon:'<i class="icon-italic"></i>'},{name:"olist",icon:'<i class="icon-list-numbered"></i>'},{name:"ulist",icon:'<i class="icon-list-bullet"></i>'},{name:"link",icon:'<i class="icon-link"></i>'}]});var clean=function(e){e.stopPropagation();e.preventDefault();var clipboardData=e.clipboardData||window.clipboardData;console.log(clipboardData.getData("Text"));window.pell.exec("insertText",clipboardData.getData("Text"));return true;};var alignText=function(){let paragraphs=editor.content.querySelectorAll('p,li');let last='';for(let paragraph of paragraphs){var content=paragraph.textContent;if(content.trim()===''){content=last.textContent;}
if(rtl.isRTL(content)){paragraph.style.direction='rtl';paragraph.style.textAlign='right';}
+7 -3
View File
@@ -118,7 +118,7 @@ container.set(as,container.path(context),true,watch);container.set(key,index,tru
element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,repeat:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}else{if(debug){console.error('Missing template "'+source+'"');}}
if(!init){view.render(element);}
return;}
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){console.error("ERROR-APP",error);};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){window.location='/console';},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);window.location='/console';};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){window.location='/console';},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('console',function(window){var sdk=new window.Appwrite();sdk.setEndpoint(APP_ENV.API).setProject('console').setLocale(APP_ENV.LOCALE);return sdk;},true);})(window);(function(window){"use strict";window.ls.container.set('date',function(){function format(format,timestamp){var jsdate,f
@@ -284,7 +284,7 @@ return"< 1s";}).add("markdown",function($value,markdown){return markdown.render(
let thresh=1000;if(Math.abs($value)<thresh){return $value+" B";}
let units=["kB","MB","GB","TB","PB","EB","ZB","YB"];let u=-1;do{$value/=thresh;++u;}while(Math.abs($value)>=thresh&&u<units.length-1);return($value.toFixed(1)+'<span class="text-size-small unit">'+
units[u]+"</span>");}).add("statsTotal",function($value){if(!$value){return 0;}
$value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add("isEmpty",function($value){return(!!$value);}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
$value=abbreviate($value,0,false,false);return $value==="0"?"N/A":$value;}).add("isEmpty",function($value){return(!!$value);}).add("isEmptyObject",function($value){return((Object.keys($value).length===0&&$value.constructor===Object)||$value.length===0)}).add("activeDomainsCount",function($value){let result=[];if(Array.isArray($value)){result=$value.filter(function(node){return(node.verification&&node.certificateId);});}
return result.length;}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
@@ -356,7 +356,11 @@ list["filters-"+filter.key]=params[key][i];}}}}
return list;};let apply=function(params){let cached=container.get(name);cached=cached?cached.params:[];params=Object.assign(cached,params);container.set(name,{name:name,params:params,query:serialize(params),forward:parseInt(params.offset)+parseInt(params.limit),backward:parseInt(params.offset)-parseInt(params.limit),keys:flatten(params)},true,name);document.dispatchEvent(new CustomEvent(name+"-changed",{bubbles:false,cancelable:true}));};switch(element.tagName){case"INPUT":break;case"TEXTAREA":break;case"BUTTON":element.addEventListener("click",function(){apply(JSON.parse(expression.parse(element.dataset["params"]||"{}")));});break;case"FORM":element.addEventListener("input",function(){apply(form.toJson(element));});element.addEventListener("change",function(){apply(form.toJson(element));});element.addEventListener("reset",function(){setTimeout(function(){apply(form.toJson(element));},0);});events=events.trim().split(",");for(let y=0;y<events.length;y++){if(events[y]==="init"){element.addEventListener("rendered",function(){apply(form.toJson(element));},{once:true});}else{}
element.setAttribute("data-event","none");}
break;default:break;}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-down",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-down]")).map(function(obj){obj.addEventListener("click",function(){if(element.nextElementSibling){element.parentNode.insertBefore(element.nextElementSibling,element);element.scrollIntoView(true);}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-move-up",controller:function(element){Array.prototype.slice.call(element.querySelectorAll("[data-move-up]")).map(function(obj){obj.addEventListener("click",function(){if(element.previousElementSibling){element.parentNode.insertBefore(element,element.previousElementSibling);element.scrollIntoView(true);}});});}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-nav",repeat:false,controller:function(element,view,container,document){let titles=document.querySelectorAll('[data-forms-nav-anchor]');let links=element.querySelectorAll('[data-forms-nav-link]');let minLink=null;let check=function(){let minDistance=null;let minElement=null;for(let i=0;i<titles.length;++i){let title=titles[i];let distance=title.getBoundingClientRect().top;console.log(i);if((minDistance===null||minDistance>=distance)&&(distance>=0)){if(minLink){minLink.classList.remove('selected');}
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-password-meter",controller:function(element,window){var calc=function(password){var score=0;if(!password)return score;var letters=new window.Object();for(var i=0;i<password.length;i++){letters[password[i]]=(letters[password[i]]||0)+1;score+=5.0/letters[password[i]];}
console.log('old',minLink);minDistance=distance;minElement=title;minLink=links[i];minLink.classList.add('selected');console.log('new',minLink);}}};window.addEventListener('scroll',check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-oauth-apple",controller:function(element){let container=document.createElement("div");let row=document.createElement("div");let col1=document.createElement("div");let col2=document.createElement("div");let keyID=document.createElement("input");let keyLabel=document.createElement("label");let teamID=document.createElement("input");let teamLabel=document.createElement("label");let p8=document.createElement("textarea");let p8Label=document.createElement("label");keyLabel.textContent='Key ID';teamLabel.textContent='Team ID';p8Label.textContent='P8 File';row.classList.add('row');row.classList.add('thin');container.appendChild(row);container.appendChild(p8Label);container.appendChild(p8);row.appendChild(col1);row.appendChild(col2);col1.classList.add('col');col1.classList.add('span-6');col1.appendChild(keyLabel);col1.appendChild(keyID);col2.classList.add('col');col2.classList.add('span-6');col2.appendChild(teamLabel);col2.appendChild(teamID);keyID.type='text';keyID.placeholder='SHAB13ROFN';teamID.type='text';teamID.placeholder='ELA2CD3AED';p8.accept='.p8';p8.classList.add('margin-bottom-no');element.parentNode.insertBefore(container,element.nextSibling);element.addEventListener('change',sync);keyID.addEventListener('change',update);teamID.addEventListener('change',update);p8.addEventListener('change',update);function update(){let json={};json.keyID=keyID.value;json.teamID=teamID.value;json.p8=p8.value;element.value=JSON.stringify(json);}
function sync(){console.log('sync');if(!element.value){return;}
let json={};try{json=JSON.parse(element.value);}catch(error){console.error('Failed to parse secret key');}
teamID.value=json.teamID||'';keyID.value=json.keyID||'';p8.value=json.p8||'';}
sync();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-password-meter",controller:function(element,window){var calc=function(password){var score=0;if(!password)return score;var letters=new window.Object();for(var i=0;i<password.length;i++){letters[password[i]]=(letters[password[i]]||0)+1;score+=5.0/letters[password[i]];}
var variations={digits:/\d/.test(password),lower:/[a-z]/.test(password),upper:/[A-Z]/.test(password),nonWords:/\W/.test(password)};var variationCount=0;for(var check in variations){if(variations.hasOwnProperty(check)){variationCount+=variations[check]===true?1:0;}}
score+=(variationCount-1)*10;return parseInt(score);};var callback=function(){var score=calc(this.value);if(""===this.value)return(meter.className="password-meter");if(score>60)return(meter.className="password-meter strong");if(score>30)return(meter.className="password-meter medium");if(score>=0)return(meter.className="password-meter weak");};var meter=window.document.createElement("div");meter.className="password-meter";element.parentNode.insertBefore(meter,element.nextSibling);element.addEventListener("change",callback);element.addEventListener("keypress",callback);element.addEventListener("keyup",callback);element.addEventListener("keydown",callback);}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-pell",controller:function(element,window,document,markdown,rtl){var div=document.createElement("div");element.className="pell hide";div.className="input pell";element.parentNode.insertBefore(div,element);element.tabIndex=-1;var turndownService=new TurndownService();turndownService.addRule("underline",{filter:["u"],replacement:function(content){return"__"+content+"__";}});var editor=window.pell.init({element:div,onChange:function onChange(html){alignText();element.value=turndownService.turndown(html);},defaultParagraphSeparator:"p",actions:[{name:"bold",icon:'<i class="icon-bold"></i>'},{name:"underline",icon:'<i class="icon-underline"></i>'},{name:"italic",icon:'<i class="icon-italic"></i>'},{name:"olist",icon:'<i class="icon-list-numbered"></i>'},{name:"ulist",icon:'<i class="icon-list-bullet"></i>'},{name:"link",icon:'<i class="icon-link"></i>'}]});var clean=function(e){e.stopPropagation();e.preventDefault();var clipboardData=e.clipboardData||window.clipboardData;console.log(clipboardData.getData("Text"));window.pell.exec("insertText",clipboardData.getData("Text"));return true;};var alignText=function(){let paragraphs=editor.content.querySelectorAll('p,li');let last='';for(let paragraph of paragraphs){var content=paragraph.textContent;if(content.trim()===''){content=last.textContent;}
if(rtl.isRTL(content)){paragraph.style.direction='rtl';paragraph.style.textAlign='right';}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

+2 -1
View File
@@ -2,7 +2,8 @@
window.ls.error = function() {
return function(error) {
console.error("ERROR-APP", error);
window.console.error(error);
window.location = '/console';
};
};
+94
View File
@@ -0,0 +1,94 @@
(function(window) {
"use strict";
window.ls.container.get("view").add({
selector: "data-forms-oauth-apple",
controller: function(element) {
let container = document.createElement("div");
let row = document.createElement("div");
let col1 = document.createElement("div");
let col2 = document.createElement("div");
let keyID = document.createElement("input");
let keyLabel = document.createElement("label");
let teamID = document.createElement("input");
let teamLabel = document.createElement("label");
let p8 = document.createElement("textarea");
let p8Label = document.createElement("label");
keyLabel.textContent = 'Key ID';
teamLabel.textContent = 'Team ID';
p8Label.textContent = 'P8 File';
row.classList.add('row');
row.classList.add('thin');
container.appendChild(row);
container.appendChild(p8Label);
container.appendChild(p8);
row.appendChild(col1);
row.appendChild(col2);
col1.classList.add('col');
col1.classList.add('span-6');
col1.appendChild(keyLabel);
col1.appendChild(keyID);
col2.classList.add('col');
col2.classList.add('span-6');
col2.appendChild(teamLabel);
col2.appendChild(teamID);
keyID.type = 'text';
keyID.placeholder = 'SHAB13ROFN';
teamID.type = 'text';
teamID.placeholder = 'ELA2CD3AED';
p8.accept = '.p8';
p8.classList.add('margin-bottom-no');
element.parentNode.insertBefore(container, element.nextSibling);
element.addEventListener('change', sync);
keyID.addEventListener('change', update);
teamID.addEventListener('change', update);
p8.addEventListener('change', update);
function update() {
let json = {};
json.keyID = keyID.value;
json.teamID = teamID.value;
json.p8 = p8.value;
element.value = JSON.stringify(json);
}
function sync() {
console.log('sync');
if(!element.value) {
return;
}
let json = {};
try {
json = JSON.parse(element.value);
} catch (error) {
console.error('Failed to parse secret key');
}
teamID.value = json.teamID || '';
keyID.value = json.keyID || '';
p8.value = json.p8 || '';
}
// function syncB() {
// picker.value = element.value;
// }
// element.parentNode.insertBefore(preview, element);
// update();
sync();
}
});
})(window);
+117 -26
View File
@@ -3,6 +3,7 @@
namespace Appwrite\Auth\OAuth2;
use Appwrite\Auth\OAuth2;
use Exception;
// Reference Material
// https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple
@@ -22,6 +23,11 @@ class Apple extends OAuth2
"email"
];
/**
* @var array
*/
protected $claims = [];
/**
* @return string
*/
@@ -58,15 +64,18 @@ class Apple extends OAuth2
'https://appleid.apple.com/auth/token',
$headers,
http_build_query([
'grant_type' => 'authorization_code',
'code' => $code,
'client_id' => $this->appID,
'client_secret' => $this->appSecret,
'client_secret' => $this->getAppSecret(),
'redirect_uri' => $this->callback,
'grant_type' => 'authorization_code'
])
);
$accessToken = json_decode($accessToken, true);
$accessToken = json_decode($accessToken, true);
$this->claims = (isset($accessToken['id_token'])) ? explode('.', $accessToken['id_token']) : [0 => '', 1 => ''];
$this->claims = (isset($this->claims[1])) ? json_decode(base64_decode($this->claims[1]), true) : [];
if (isset($accessToken['access_token'])) {
return $accessToken['access_token'];
@@ -82,10 +91,8 @@ class Apple extends OAuth2
*/
public function getUserID(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['account_id'])) {
return $user['account_id'];
if (isset($this->claims['sub']) && !empty($this->claims['sub'])) {
return $this->claims['sub'];
}
return '';
@@ -98,10 +105,11 @@ class Apple extends OAuth2
*/
public function getUserEmail(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['email'])) {
return $user['email'];
if (isset($this->claims['email']) &&
!empty($this->claims['email']) &&
isset($this->claims['email_verified']) &&
$this->claims['email_verified'] === 'true') {
return $this->claims['email'];
}
return '';
@@ -114,28 +122,111 @@ class Apple extends OAuth2
*/
public function getUserName(string $accessToken): string
{
$user = $this->getUser($accessToken);
if (isset($user['name'])) {
return $user['name']['display_name'];
if (isset($this->claims['email']) &&
!empty($this->claims['email']) &&
isset($this->claims['email_verified']) &&
$this->claims['email_verified'] === 'true') {
return $this->claims['email'];
}
return '';
}
/**
* @param string $accessToken
*
* @return array
*/
protected function getUser(string $accessToken): array
protected function getAppSecret():string
{
if (empty($this->user)) {
$headers[] = 'Authorization: Bearer '. urlencode($accessToken);
$user = $this->request('POST', '', $headers);
$this->user = json_decode($user, true);
try {
$secret = json_decode($this->appSecret, true);
} catch (\Throwable $th) {
throw new Exception('Invalid secret');
}
return $this->user;
$keyfile = (isset($secret['p8'])) ? $secret['p8'] : ''; // Your p8 Key file
$keyID = (isset($secret['keyID'])) ? $secret['keyID'] : ''; // Your Key ID
$teamID = (isset($secret['teamID'])) ? $secret['teamID'] : ''; // Your Team ID (see Developer Portal)
$bundleID = $this->appID; // Your Bundle ID
$headers = [
'alg' => 'ES256',
'kid' => $keyID,
];
$claims = [
'iss' => $teamID,
'iat' => time(),
'exp' => time() + 86400*180,
'aud' => 'https://appleid.apple.com',
'sub' => $bundleID,
];
$pkey = openssl_pkey_get_private($keyfile);
$payload = $this->encode(json_encode($headers)).'.'.$this->encode(json_encode($claims));
$signature = '';
$success = openssl_sign($payload, $signature, $pkey, OPENSSL_ALGO_SHA256);
if (!$success) return '';
return $payload.'.'.$this->encode($this->fromDER($signature, 64));
}
/**
* @param string $data
*/
protected function encode($data)
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}
/**
* @param string $data
*/
protected function retrievePositiveInteger(string $data): string
{
while ('00' === mb_substr($data, 0, 2, '8bit') && mb_substr($data, 2, 2, '8bit') > '7f') {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
/**
* @param string $der
* @param int $partLength
*/
protected function fromDER(string $der, int $partLength):string
{
$hex = \unpack('H*', $der)[1];
if ('30' !== \mb_substr($hex, 0, 2, '8bit')) { // SEQUENCE
throw new \RuntimeException();
}
if ('81' === \mb_substr($hex, 2, 2, '8bit')) { // LENGTH > 128
$hex = \mb_substr($hex, 6, null, '8bit');
}
else {
$hex = \mb_substr($hex, 4, null, '8bit');
}
if ('02' !== \mb_substr($hex, 0, 2, '8bit')) { // INTEGER
throw new \RuntimeException();
}
$Rl = \hexdec(\mb_substr($hex, 2, 2, '8bit'));
$R = $this->retrievePositiveInteger(\mb_substr($hex, 4, $Rl * 2, '8bit'));
$R = \str_pad($R, $partLength, '0', STR_PAD_LEFT);
$hex = \mb_substr($hex, 4 + $Rl * 2, null, '8bit');
if ('02' !== \mb_substr($hex, 0, 2, '8bit')) { // INTEGER
throw new \RuntimeException();
}
$Sl = \hexdec(\mb_substr($hex, 2, 2, '8bit'));
$S = $this->retrievePositiveInteger(\mb_substr($hex, 4, $Sl * 2, '8bit'));
$S = \str_pad($S, $partLength, '0', STR_PAD_LEFT);
return \pack('H*', $R.$S);
}
}