Merge branch 'master' of github.com:appwrite/appwrite into graphql
This commit is contained in:
commit
8458438465
41 changed files with 363 additions and 441 deletions
|
@ -30,4 +30,4 @@ install:
|
|||
|
||||
script:
|
||||
- docker ps
|
||||
- docker exec appwrite /bin/bash -c '/usr/share/nginx/html/vendor/bin/phpunit'
|
||||
- docker exec appwrite test
|
||||
|
|
13
CHANGES.md
13
CHANGES.md
|
@ -11,18 +11,18 @@
|
|||
- Added support for Brotli compression (@PedroCisnerosSantana, @Rohitub222)
|
||||
- New UI micro-interactions and CSS fixes (@AnatoleLucet)
|
||||
- UI performance & accessibility improvments (#406)
|
||||
- Updated ClamAV conntainer to version 1.0.9
|
||||
- New Doctor CLI to debug the Appwrite server ([#415](https://github.com/appwrite/appwrite/issues/415))
|
||||
- All emails are now sent asynchronously for improved performance (@TorstenDittmann)
|
||||
- Updated grid for OAuth2 providers list in the console
|
||||
- Upgraded Redis Resque queue library to version 1.3.6
|
||||
- Added container names to docker-compose.yml (@drandell)
|
||||
- Upgraded ClamAV container image to version 1.0.9
|
||||
- Upgraded ClamAV container image to version 1.0.11 ([#412](https://github.com/appwrite/appwrite/issues/412))
|
||||
- Optimised function execution by using fully-qualified function calls
|
||||
- New and consistent response format for all API object + new response examples in the docs
|
||||
- Removed user roles attribute from user object (can be fetched from /v1/teams/memberships) **
|
||||
- Removed type attribute from session object response (used only internally)
|
||||
- ** - might be changed before merging to master
|
||||
- Added support for boolean 'true' and 'false' in query strings alongside 1 and 0
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
@ -38,6 +38,15 @@
|
|||
- Fixed wrong JSON validation when creating and updating database documnets
|
||||
- Fixed bug where max file size was limited to max of 10MB
|
||||
- Fixed bug preventing the deletion of the project logo
|
||||
- Fixed Bug when trying to overwrite OAuth cookie in the Flutter SDK
|
||||
- Fixed OAuth redirect when using the self-hosted instance default success URL ([#454](https://github.com/appwrite/appwrite/issues/454))
|
||||
- Fixed bug denying authentication with Github OAuth provider
|
||||
- New OAuth adapter for Box.com
|
||||
- New OAuth adapter for PayPal sandbox
|
||||
|
||||
## Breaking Changes
|
||||
- **Deprecated** `first` and `last` query params for documents list route in the database API
|
||||
- **Deprecated** Deprectaed Pubjabi Translations ('pn')
|
||||
|
||||
## Security
|
||||
|
||||
|
|
|
@ -153,6 +153,12 @@ bash ./build.sh 1.0.0
|
|||
|
||||
Before running the command, make sure you have proper write permissions to the Appwrite docker hub team.
|
||||
|
||||
**Build for multicore**
|
||||
|
||||
```bash
|
||||
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t appwrite/multicore:0.0.0 --push
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
To run tests manually, run phpunit from your command line:
|
||||
|
|
11
app/app.php
11
app/app.php
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
// Init
|
||||
require_once __DIR__.'/init.php';
|
||||
|
||||
global $utopia, $request, $response, $register, $consoleDB, $project;
|
||||
|
@ -22,9 +21,6 @@ use Appwrite\Utopia\Response;
|
|||
/*
|
||||
* Configuration files
|
||||
*/
|
||||
$roles = include __DIR__.'/config/roles.php'; // User roles and scopes
|
||||
$services = include __DIR__.'/config/services.php'; // List of services
|
||||
|
||||
$webhook = new Event('v1-webhooks', 'WebhooksV1');
|
||||
$audit = new Event('v1-audits', 'AuditsV1');
|
||||
$usage = new Event('v1-usage', 'UsageV1');
|
||||
|
@ -55,7 +51,7 @@ $clients = \array_unique(\array_merge($clientsConsole, \array_map(function ($nod
|
|||
return false;
|
||||
}))));
|
||||
|
||||
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $console, $roles, $webhook, $mail, $audit, $usage, $clients) {
|
||||
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $console, $webhook, $mail, $audit, $usage, $clients) {
|
||||
|
||||
$route = $utopia->match($request);
|
||||
|
||||
|
@ -143,6 +139,7 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
|
|||
}
|
||||
}
|
||||
|
||||
$roles = Config::getParam('roles', []);
|
||||
$scope = $route->getLabel('scope', 'none'); // Allowed scope for chosen route
|
||||
$scopes = $roles[$role]['scopes']; // Allowed scopes for user role
|
||||
|
||||
|
@ -428,8 +425,8 @@ $utopia->get('/.well-known/acme-challenge')
|
|||
include_once __DIR__ . '/controllers/shared/api.php';
|
||||
include_once __DIR__ . '/controllers/shared/web.php';
|
||||
|
||||
foreach($services as $key => $service) {
|
||||
include_once $services[$key]['controller'];
|
||||
foreach(Config::getParam('services', []) as $service) {
|
||||
include_once $service['controller'];
|
||||
}
|
||||
|
||||
$utopia->run($request, $response);
|
|
@ -31,7 +31,6 @@ return [
|
|||
'no', // Norwegian
|
||||
'ph', // Filipino
|
||||
'pl', // Polish
|
||||
'pn', // Punjabi
|
||||
'pt-br', // Portuguese - Brazil
|
||||
'pt-pt', // Portuguese - Portugal
|
||||
'ro', // Romanian
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'AF' => 'ਅਫਰੀਕਾ',
|
||||
'AN' => 'ਅੰਤਾਰਕਟੀਕਾ',
|
||||
'AS' => 'ਏਸੀਆਈ',
|
||||
'EU' => 'ਯੂਰੋਪਾ',
|
||||
'NA' => 'ਨੂਰਡ-ਅਮੇਰਿਕਾ',
|
||||
'OC' => 'ਓਸੀਆਨੀ',
|
||||
'SA' => 'ਸੂਡ-ਅਮੇਰਿਕਾ',
|
||||
];
|
|
@ -1,197 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'AF' => 'ਅਫਗਾਨਿਸਤਾਨ',
|
||||
'AO' => 'ਅੰਗੋਲਾ',
|
||||
'AL' => 'ਅਲਬਾਨੀë',
|
||||
'AD' => 'ਅੰਡੋਰਾ',
|
||||
'AE' => 'Verenigde ਅਰਬਿਅਨ ਅਮੀਰਾਤ',
|
||||
'AR' => 'ਅਰਜਨਟੀਨੀë',
|
||||
'AM' => 'ਅਰਮੀਨੀë',
|
||||
'AG' => 'ਐਂਟੀਗੁਆ ਐਨ ਬਾਰਬੁਡਾ',
|
||||
'AU' => 'ਆਸਟਰੇਲੀਆਈ',
|
||||
'AT' => 'ਓਓਸਟੇਨਰੀਕ',
|
||||
'AZ' => 'ਅਜ਼ਰਬਾਈਜਾਨ',
|
||||
'BI' => 'ਬੁਰੂੰਡੀ',
|
||||
'BE' => 'ਬੈਲਜੀë',
|
||||
'BJ' => 'ਬੇਨਿਨ',
|
||||
'BF' => 'ਬੁਰਕੀਨਾ ਫਾਸੋ',
|
||||
'BD' => 'ਬੰਗਲਾਦੇਸ਼',
|
||||
'BG' => 'ਬੁਲਗਾਰੀ',
|
||||
'BH' => 'ਬਹਿਰੀਨ',
|
||||
'BS' => 'ਬਾਹਾਮਸ',
|
||||
'BA' => 'ਬੋਸਨੀਅ ਇਨ ਹਰਜ਼ੈਗੋਵਿਨਾ',
|
||||
'BY' => 'ਬੇਲਾਰੂਸ',
|
||||
'BZ' => 'ਬੇਲੀਜ਼',
|
||||
'BO' => 'ਬੋਲੀਵੀਆ',
|
||||
'BR' => 'ਬ੍ਰਾਸੀਲੀë',
|
||||
'BB' => 'ਬਾਰਬਾਡੋਸ',
|
||||
'BN' => 'ਬਰੂਨੇਈ',
|
||||
'BT' => 'ਭੋਏਤਨ',
|
||||
'BW' => 'ਬੋਤਸਵਾਨਾ',
|
||||
'CF' => 'ਮੱਧ ਅਫ਼ਰੀਕੀ ਗਣਰਾਜ',
|
||||
'CA' => 'ਕਨਡਾ',
|
||||
'CH' => 'ਸਵਿਟਜ਼ਰਲੈਂਡ',
|
||||
'CL' => 'ਚਿਲੀ',
|
||||
'CN' => 'ਸਜੀਨਾ',
|
||||
'CI' => 'ਇਵੋੋਰਕਸ',
|
||||
'CM' => 'ਕਾਮਰੋਇਨ',
|
||||
'CD' => 'ਡੈਮੋਕਰੇਟੀਜ਼ ਰਿਪਬਲਿਕ ਵੈਨ ਡਾਈ ਕੌਂਗੋ',
|
||||
'CG' => 'ਰਿਪਬਲਿਕ ਵੈਨ ਡਾਈ ਕੌਂਗੋ',
|
||||
'CO' => 'ਕੋਲੰਬੀਆ',
|
||||
'KM' => 'ਕੋਮੋਰੋਜ਼',
|
||||
'CV' => 'ਕਾਪ ਵਰਡੇ',
|
||||
'CR' => 'ਕੋਸਟਾਰੀਕਾ',
|
||||
'CU' => 'ਕੁਬਾ',
|
||||
'CY' => 'ਸਾਈਪ੍ਰਸ',
|
||||
'CZ' => 'ਸਿਜ਼ੈਗੀ ਰੀਪਬਲਿਕ',
|
||||
'DE' => 'ਡਿਟਸਲੈਂਡ',
|
||||
'DJ' => 'ਜਾਇਬੂਤੀ',
|
||||
'DM' => 'ਡੋਮਿਨਿਕਾ',
|
||||
'DK' => 'ਡੀਨੇਮਾਰਕ',
|
||||
'DO' => 'ਡੋਮੀਨੀਕੇਂਸ ਰਿਪਬਲਿਕ',
|
||||
'DZ' => 'ਅਲਜੀਰੀਆ',
|
||||
'EC' => 'ਇਕੂਏਟਰ',
|
||||
'EG' => 'ਐਗਪੇਟ',
|
||||
'ER' => 'ਏਰੀਟਰੀਆ',
|
||||
'ES' => 'ਸਪੰਜੇ',
|
||||
'EE' => 'ਐਸਟਲੈਂਡ',
|
||||
'ET' => 'ਈਥੀਓਪੀਅ',
|
||||
'FI' => 'ਫਿਨਲੈਂਡ',
|
||||
'FJ' => 'ਫਿਦਜੀ',
|
||||
'FR' => 'ਫ੍ਰੈਂਕ੍ਰੀਕ',
|
||||
'FM' => 'ਮਿਕਰੋਨੇਸੀ',
|
||||
'GA' => 'ਗਾਬੋਅਨ',
|
||||
'GB' => 'Verenigde Koninkryk',
|
||||
'GE' => 'ਜਾਰਜੀਆ',
|
||||
'GH' => 'ਘਾਨਾ',
|
||||
'GN' => 'ਗਿੰਨੀ',
|
||||
'GM' => 'ਗਾਮੀ',
|
||||
'GW' => 'ਗਿੰਨੀ-ਬਿਸਾਉ',
|
||||
'GQ' => 'ਏਕਵੇਟਰਿਆਲ-ਗਿੰਨੀ',
|
||||
'GR' => 'ਗ੍ਰੀਕਲੈਂਡ',
|
||||
'GD' => 'ਗ੍ਰੇਨਾਡਾ',
|
||||
'GT' => 'ਗੁਆਟੇਮਾਲਾ',
|
||||
'GY' => 'ਗੁਆਨਾ',
|
||||
'HN' => 'ਹੌਂਡੂਰਸ',
|
||||
'HR' => 'ਕ੍ਰੋਸੀë',
|
||||
'HT' => 'ਹੈਤੀ',
|
||||
'HU' => 'ਹਾਂਗਰੀ',
|
||||
'ID' => 'ਇੰਡੋਨੇਸ਼ੀਆਈ',
|
||||
'IN' => 'ਇੰਡੀë',
|
||||
'IE' => 'ਆਇਰਲੈਂਡ',
|
||||
'IR' => 'ਇਰਾਨ',
|
||||
'IQ' => 'ਇਰਕ',
|
||||
'IS' => 'Ysland',
|
||||
'IL' => 'ਇਜ਼ਰਾਈਲ',
|
||||
'IT' => 'ਇਟਾਲੀë',
|
||||
'JM' => 'ਜਮਾਏਕਾ',
|
||||
'JO' => 'ਜਾਰਡਨ',
|
||||
'JP' => 'ਜਪਾਨ',
|
||||
'KZ' => 'ਕਜ਼ਾਕਸਤਾਨ',
|
||||
'KE' => 'ਕੀਨੀਆ',
|
||||
'KG' => 'ਕਿਰਗਿਸਤਾਨ',
|
||||
'KH' => 'ਕੰਬੋਡਜਾ',
|
||||
'KI' => 'ਕਿਰੀਬਾਤੀ',
|
||||
'KN' => 'ਸੇਂਟ ਕਿਟਸ ਐਨ ਨੇਵਿਸ',
|
||||
'KR' => 'ਸੂਡ-ਕੋਰੀਆ',
|
||||
'KW' => 'ਕੁਵੈਤ',
|
||||
'LA' => 'ਲਾਓਸ',
|
||||
'LB' => 'ਲਿਬਨਾਨ',
|
||||
'LR' => 'ਲਿਬੇਰੀë',
|
||||
'LY' => 'ਲੀਬੀë',
|
||||
'LC' => 'ਸੇਂਟ ਲੂਸੀਆ',
|
||||
'LI' => 'ਲਿਚਟੇਨਸਟਾਈਨ',
|
||||
'LK' => 'ਸ਼ਿਰੀਲੰਕਾ',
|
||||
'LS' => 'ਲੈਸੋਥੋ',
|
||||
'LT' => 'ਲੀਟਾ',
|
||||
'LU' => 'ਲਕਸਮਬਰਗ',
|
||||
'LV' => 'ਲਾਤਵੀਆ',
|
||||
'MA' => 'ਮਾਰੋਕੋ',
|
||||
'MC' => 'ਮੋਨੈਕੋ',
|
||||
'MD' => 'ਮੋਲਦਾਵੀ',
|
||||
'MG' => 'ਮੈਡਾਗਾਸਕਰ',
|
||||
'MV' => 'ਮਾਲਦੀਵ',
|
||||
'MX' => 'ਮੇਕਸਿਕੋ',
|
||||
'MH' => 'ਮਾਰਸ਼ਲ-ਆਈਲੈਂਡ',
|
||||
'MK' => 'ਮੈਸੇਡੋਨੀë',
|
||||
'ML' => 'ਮਾਲੀ',
|
||||
'MT' => 'ਮਾਲਟਾ',
|
||||
'MM' => 'ਮਿਆਂਮਾਰ',
|
||||
'ME' => 'ਮੌਂਟੇਨੇਗਰੋ',
|
||||
'MN' => 'ਮੰਗੋਲੀë',
|
||||
'MZ' => 'ਮੋਸਾਮਬੀਕ',
|
||||
'MR' => 'ਮੌਰੀਟਨੀë',
|
||||
'MU' => 'ਮਾਰੀਸ਼ਸ',
|
||||
'MW' => 'ਮਾਲਾਵੀ',
|
||||
'MY' => 'ਮਲੇਸੀਆਈ',
|
||||
'NA' => 'ਨਾਮੀਬੀ',
|
||||
'NE' => 'ਨਾਈਜਰ',
|
||||
'NG' => 'ਨਾਈਜੀਰੀë',
|
||||
'NI' => 'ਨਿਕਾਰਾਗੁਆ',
|
||||
'NL' => 'ਨੀਡਰਲੈਂਡ',
|
||||
'NO' => 'ਨੂਰਵੇë',
|
||||
'NP' => 'ਨੇਪਾਲ',
|
||||
'NR' => 'ਨੌਰੂ',
|
||||
'NZ' => 'ਨਿie-ਸੀਲੈਂਡ',
|
||||
'OM' => 'ਓਮਾਨ',
|
||||
'PK' => 'ਪਾਕਿਸਤਾਨ',
|
||||
'PA' => 'ਪਨਾਮਾ',
|
||||
'PE' => 'ਪੇਰੂ',
|
||||
'PH' => 'ਫਿਲਪੀਨ',
|
||||
'PW' => 'ਪਲਾਉ',
|
||||
'PG' => 'ਪਾਪੀਆ-ਨੀਯੂ-ਗਿੰਨੀ',
|
||||
'PL' => 'ਪੋਲ',
|
||||
'KP' => 'ਨੂਰਡ-ਕੋਰੀਆ',
|
||||
'PT' => 'ਪੁਰਤਗਾਲ',
|
||||
'PY' => 'ਪੈਰਾਗੁਏ',
|
||||
'QA' => 'ਕਟਾਰ',
|
||||
'RO' => 'ਰੋਮੇਨੀਅ',
|
||||
'RU' => 'ਰਸਲੈਂਡ',
|
||||
'RW' => 'ਰਵਾਂਡਾ',
|
||||
'SA' => 'ਸਾਓਦੀ-ਅਰਾਬੀ',
|
||||
'SD' => 'ਸੋਦਾਨ',
|
||||
'SN' => 'ਸੇਨੇਗਲ',
|
||||
'SG' => 'ਸਿੰਗਾਪੁਰ',
|
||||
'SB' => 'ਸਲੋਮੋ-ਆਈਲੈਂਡ',
|
||||
'SL' => 'ਸੀਅਰਾ ਲਿਓਨ',
|
||||
'SV' => 'ਐਲ ਸਾਲਵਾਡੋਰ',
|
||||
'SM' => 'ਸੈਨ ਮਰੀਨੋ',
|
||||
'SO' => 'ਸੋਮਾਲੀë',
|
||||
'RS' => 'ਸਰਵੀë',
|
||||
'SS' => 'ਸੂਇਡ-ਸੋਦਾਨ',
|
||||
'ST' => 'ਸਾਓ ਤੋਮੇ ਐਨ ਪ੍ਰਿੰਸੀਪੇ',
|
||||
'SR' => 'ਸੂਰੀਨਾਮ',
|
||||
'SK' => 'ਸਲੋਕਯੇ',
|
||||
'SI' => 'ਹੌਲੀ',
|
||||
'SE' => 'ਸਵੈਡੇ',
|
||||
'SZ' => 'ਸਵਾਜ਼ੀਲੈਂਡ',
|
||||
'SC' => 'ਸੇਸ਼ੇਲ',
|
||||
'SY' => 'ਸਿਰੀ',
|
||||
'TD' => 'ਚਾਡ',
|
||||
'TG' => 'ਹੁਣੇ ਜਾਣਾ',
|
||||
'TH' => 'ਥਾਈਲੈਂਡ',
|
||||
'TJ' => 'ਤਦਜਿਕਿਸਤਾਨ',
|
||||
'TM' => 'ਤੁਰਕਮੇਨਿਸਤਾਨ',
|
||||
'TL' => 'ਓਸ-ਤਿਮੋਰ',
|
||||
'TO' => 'ਟੋਂਗਾ',
|
||||
'TT' => 'ਤ੍ਰਿਨੀਦਾਦ ਅਤੇ ਟੋਬੈਗੋ',
|
||||
'TN' => 'ਟਿisਨੀਸੀਅ',
|
||||
'TR' => 'ਤੁਰਕੀ',
|
||||
'TV' => 'ਤੁਵਾਲੁ',
|
||||
'TZ' => 'ਤਨਜ਼ਾਨੀë',
|
||||
'UG' => 'ਯੂਗਾਂਡਾ',
|
||||
'UA' => 'ਓਕ੍ਰਾੱਨ',
|
||||
'UY' => 'ਉਰੂਗਵੇ',
|
||||
'US' => 'ਵੇਰੇਨਿਗਡੇ ਸਟੇਟ',
|
||||
'UZ' => 'ਓਸਬੀਕਕਿਸਤਾਨ',
|
||||
'VA' => 'ਵਾਟਿਕਾਂਸਟੈਡ',
|
||||
'VC' => 'ਸਿਨਟ ਵਿਨਸੈਂਟ ਏਨ ਡਾਈ ਗ੍ਰੇਨਾਡਾਈਨਜ਼',
|
||||
'VE' => 'ਵੈਨਜ਼ੂਏਲਾ',
|
||||
'VN' => 'ਵਿਯਤਨਮ',
|
||||
'VU' => 'ਵੈਨੂਆਟੂ',
|
||||
'WS' => 'ਸਮੋਆ',
|
||||
'YE' => 'ਜੀਮਨ',
|
||||
'ZA' => 'ਸੂਡ-ਅਫਰੀਕਾ',
|
||||
'ZM' => 'ਜ਼ੈਂਬੀਆ',
|
||||
'ZW' => 'ਜ਼ਿੰਬਾਬਵੇ',
|
||||
];
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
return [
|
||||
'settings.inspire' => '"I love Typing&coding in punjabi :)."', // This is the line printed in the homepage and console 'view-source'
|
||||
'settings.locale' => 'pn',
|
||||
'settings.direction' => 'ltr',
|
||||
// Service - Users
|
||||
'account.emails.team' => '%s ਟੀਮ(Priyanka)',
|
||||
'account.emails.verification.title' => 'ਖਾਤਾ ਪੁਸ਼ਟੀਕਰਣ',
|
||||
'account.emails.verification.body' => 'app/config/locales/templates/pn.email.auth.confirm.tpl',
|
||||
'account.emails.recovery.title' => 'ਪਾਸਵਰਡ ਰੀਸੈੱਟ',
|
||||
'account.emails.recovery.body' => 'app/config/locales/templates/pn.email.auth.recovery.tpl',
|
||||
'account.emails.invitation.title' => '% S ਟੀਮ% s ਤੇ ਸੱਦਾ',
|
||||
'account.emails.invitation.body' => 'app/config/locales/templates/pn.email.auth.invitation.tpl',
|
||||
'locale.country.unknown' => 'India',
|
||||
'countries' => include 'pn.countries.php',
|
||||
'continents' => include 'pn.continents.php',
|
||||
];
|
|
@ -1,15 +0,0 @@
|
|||
<p>
|
||||
ਹੈਲੋ {{name}},
|
||||
</p>
|
||||
<p>
|
||||
ਆਪਣੇ ਈਮੇਲ ਪਤੇ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਇਸ ਲਿੰਕ ਦਾ ਪਾਲਣ ਕਰੋ:
|
||||
</p>
|
||||
{{cta}}
|
||||
<p>
|
||||
ਜੇ ਤੁਸੀਂ ਇਸ ਪਤੇ ਨੂੰ ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਨਹੀਂ ਕਿਹਾ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੁਨੇਹੇ ਨੂੰ ਨਜ਼ਰ ਅੰਦਾਜ਼ ਕਰ ਸਕਦੇ ਹੋ.
|
||||
</p>
|
||||
<p>
|
||||
ਧੰਨਵਾਦ,
|
||||
<br />
|
||||
{{project}} ਟੀਮ
|
||||
</p>
|
|
@ -1,18 +0,0 @@
|
|||
<p>
|
||||
ਸਤ ਸ੍ਰੀ ਅਕਾਲ,
|
||||
</p>
|
||||
<p>
|
||||
ਇਹ ਮੇਲ ਤੁਹਾਨੂੰ ਇਸ ਲਈ ਭੇਜਿਆ ਗਿਆ ਸੀ ਕਿਉਂਕਿ <b> {{owner}} </ b> ਤੁਹਾਨੂੰ <b> {{team} at </b> ਟੀਮ {{project}} 'ਤੇ ਟੀਮ ਦੇ ਮੈਂਬਰ ਬਣਨ ਲਈ ਸੱਦਾ ਦੇਣਾ ਚਾਹੁੰਦਾ ਸੀ.
|
||||
</p>
|
||||
<p>
|
||||
<b> {{team}} </ b> ਟੀਮ ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਲਈ ਇਸ ਲਿੰਕ ਦਾ ਪਾਲਣ ਕਰੋ:
|
||||
</p>
|
||||
{{cta}}
|
||||
<p>
|
||||
ਜੇ ਤੁਸੀਂ ਦਿਲਚਸਪੀ ਨਹੀਂ ਰੱਖਦੇ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੰਦੇਸ਼ ਨੂੰ ਨਜ਼ਰ ਅੰਦਾਜ਼ ਕਰ ਸਕਦੇ ਹੋ.
|
||||
</p>
|
||||
<p>
|
||||
ਧੰਨਵਾਦ,
|
||||
<br />
|
||||
{{project}} ਟੀਮ
|
||||
</p>
|
|
@ -1,15 +0,0 @@
|
|||
<p>
|
||||
ਸਤ ਸ੍ਰੀ ਅਕਾਲ {{name}},
|
||||
</p>
|
||||
<p>
|
||||
ਆਪਣੇ {{project}} ਪਾਸਵਰਡ ਨੂੰ ਰੀਸੈਟ ਕਰਨ ਲਈ ਇਸ ਲਿੰਕ ਦਾ ਪਾਲਣ ਕਰੋ.
|
||||
</p>
|
||||
{{cta}}
|
||||
<p>
|
||||
ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਵਰਡ ਰੀਸੈਟ ਕਰਨ ਲਈ ਨਹੀਂ ਕਿਹਾ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਸੁਨੇਹੇ ਨੂੰ ਨਜ਼ਰ ਅੰਦਾਜ਼ ਕਰ ਸਕਦੇ ਹੋ.
|
||||
</p>
|
||||
<p>
|
||||
ਧੰਨਵਾਦ,
|
||||
<br />
|
||||
{{project}} ਟੀਮ
|
||||
</p>
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
return [ // Ordered by ABC.
|
||||
'amazon' => [
|
||||
'name' => 'Amazon',
|
||||
'developers' => 'https://developer.amazon.com/apps-and-games/services-and-apis',
|
||||
'icon' => 'icon-amazon',
|
||||
'enabled' => true,
|
||||
|
@ -10,6 +11,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'apple' => [
|
||||
'name' => 'Apple',
|
||||
'developers' => 'https://developer.apple.com/',
|
||||
'icon' => 'icon-apple',
|
||||
'enabled' => true,
|
||||
|
@ -18,6 +20,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'bitbucket' => [
|
||||
'name' => 'BitBucket',
|
||||
'developers' => 'https://developer.atlassian.com/bitbucket',
|
||||
'icon' => 'icon-bitbucket',
|
||||
'enabled' => true,
|
||||
|
@ -26,6 +29,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'bitly' => [
|
||||
'name' => 'Bitly',
|
||||
'developers' => 'https://dev.bitly.com/v4_documentation.html',
|
||||
'icon' => 'icon-bitly',
|
||||
'enabled' => true,
|
||||
|
@ -33,7 +37,17 @@ return [ // Ordered by ABC.
|
|||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'box' => [
|
||||
'name' => 'Box',
|
||||
'developers' => 'https://developer.box.com/reference/',
|
||||
'icon' => 'icon-box',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'discord' => [
|
||||
'name' => 'Discord',
|
||||
'developers' => 'https://discordapp.com/developers/docs/topics/oauth2',
|
||||
'icon' => 'icon-discord',
|
||||
'enabled' => true,
|
||||
|
@ -42,6 +56,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'dropbox' => [
|
||||
'name' => 'Dropbox',
|
||||
'developers' => 'https://www.dropbox.com/developers/documentation',
|
||||
'icon' => 'icon-dropbox',
|
||||
'enabled' => true,
|
||||
|
@ -50,6 +65,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'facebook' => [
|
||||
'name' => 'Facebook',
|
||||
'developers' => 'https://developers.facebook.com/',
|
||||
'icon' => 'icon-facebook',
|
||||
'enabled' => true,
|
||||
|
@ -58,6 +74,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'github' => [
|
||||
'name' => 'GitHub',
|
||||
'developers' => 'https://developer.github.com/',
|
||||
'icon' => 'icon-github-circled',
|
||||
'enabled' => true,
|
||||
|
@ -66,6 +83,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'gitlab' => [
|
||||
'name' => 'GitLab',
|
||||
'developers' => 'https://docs.gitlab.com/ee/api/',
|
||||
'icon' => 'icon-gitlab',
|
||||
'enabled' => true,
|
||||
|
@ -74,6 +92,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'google' => [
|
||||
'name' => 'Google',
|
||||
'developers' => 'https://support.google.com/googleapi/answer/6158849',
|
||||
'icon' => 'icon-google',
|
||||
'enabled' => true,
|
||||
|
@ -82,6 +101,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'linkedin' => [
|
||||
'name' => 'LinkedIn',
|
||||
'developers' => 'https://developer.linkedin.com/',
|
||||
'icon' => 'icon-linkedin',
|
||||
'enabled' => true,
|
||||
|
@ -90,6 +110,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'microsoft' => [
|
||||
'name' => 'Microsoft',
|
||||
'developers' => 'https://developer.microsoft.com/en-us/',
|
||||
'icon' => 'icon-windows',
|
||||
'enabled' => true,
|
||||
|
@ -98,6 +119,16 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'paypal' => [
|
||||
'name' => 'PayPal',
|
||||
'developers' => 'https://developer.paypal.com/docs/api/overview/',
|
||||
'icon' => 'icon-paypal',
|
||||
'enabled' => true,
|
||||
'form' => false,
|
||||
'beta' => false,
|
||||
'mock' => false
|
||||
],
|
||||
'paypalSandbox' => [
|
||||
'name' => 'PayPal (Sandbox)',
|
||||
'developers' => 'https://developer.paypal.com/docs/api/overview/',
|
||||
'icon' => 'icon-paypal',
|
||||
'enabled' => true,
|
||||
|
@ -106,6 +137,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false
|
||||
],
|
||||
'salesforce' => [
|
||||
'name' => 'Salesforce',
|
||||
'developers' => 'https://developer.salesforce.com/docs/',
|
||||
'icon' => 'icon-salesforce',
|
||||
'enabled' => true,
|
||||
|
@ -114,6 +146,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'slack' => [
|
||||
'name' => 'Slack',
|
||||
'developers' => 'https://api.slack.com/',
|
||||
'icon' => 'icon-slack',
|
||||
'enabled' => true,
|
||||
|
@ -122,6 +155,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'spotify' => [
|
||||
'name' => 'Spotify',
|
||||
'developers' => 'https://developer.spotify.com/documentation/general/guides/authorization-guide/',
|
||||
'icon' => 'icon-spotify',
|
||||
'enabled' => true,
|
||||
|
@ -130,6 +164,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'twitch' => [
|
||||
'name' => 'Twitch',
|
||||
'developers' => 'https://dev.twitch.tv/docs/authentication',
|
||||
'icon' => 'icon-twitch',
|
||||
'enabled' => true,
|
||||
|
@ -138,6 +173,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'vk' => [
|
||||
'name' => 'VK',
|
||||
'developers' => 'https://vk.com/dev',
|
||||
'icon' => 'icon-vk',
|
||||
'enabled' => true,
|
||||
|
@ -146,6 +182,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'yahoo' => [
|
||||
'name' => 'Yahoo',
|
||||
'developers' => 'https://developer.yahoo.com/oauth2/guide/flows_authcode/',
|
||||
'icon' => 'icon-yahoo',
|
||||
'enabled' => true,
|
||||
|
@ -154,6 +191,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
'yandex' => [
|
||||
'name' => 'Yandex',
|
||||
'developers' => 'https://tech.yandex.com/oauth/',
|
||||
'icon' => 'icon-yandex',
|
||||
'enabled' => true,
|
||||
|
@ -162,6 +200,7 @@ return [ // Ordered by ABC.
|
|||
'mock' => false,
|
||||
],
|
||||
// 'instagram' => [
|
||||
// 'name' => 'Instagram',
|
||||
// 'developers' => 'https://www.instagram.com/developer/',
|
||||
// 'icon' => 'icon-instagram',
|
||||
// 'enabled' => false,
|
||||
|
@ -169,6 +208,7 @@ return [ // Ordered by ABC.
|
|||
// 'mock' => false,
|
||||
// ],
|
||||
// 'twitter' => [
|
||||
// 'name' => 'twitter',
|
||||
// 'developers' => 'https://developer.twitter.com/',
|
||||
// 'icon' => 'icon-twitter',
|
||||
// 'enabled' => false,
|
||||
|
@ -177,6 +217,7 @@ return [ // Ordered by ABC.
|
|||
// ],
|
||||
// Keep Last
|
||||
'mock' => [
|
||||
'name' => 'Mock',
|
||||
'developers' => 'https://appwrite.io',
|
||||
'icon' => 'icon-appwrite',
|
||||
'enabled' => true,
|
||||
|
|
|
@ -29,8 +29,8 @@ use DeviceDetector\DeviceDetector;
|
|||
use GeoIp2\Database\Reader;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
||||
$oauthDefaultSuccess = $request->getServer('_APP_HOME').'/auth/oauth2/success';
|
||||
$oauthDefaultFailure = $request->getServer('_APP_HOME').'/auth/oauth2/failure';
|
||||
$oauthDefaultSuccess = '/auth/oauth2/success';
|
||||
$oauthDefaultFailure = '/auth/oauth2/failure';
|
||||
|
||||
$oauth2Keys = [];
|
||||
|
||||
|
@ -78,9 +78,8 @@ $utopia->post('/v1/account')
|
|||
}
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -153,9 +152,8 @@ $utopia->post('/v1/account/sessions')
|
|||
->action(
|
||||
function ($email, $password) use ($response, $request, $projectDB, $audit, $webhook) {
|
||||
$protocol = Config::getParam('protocol');
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -409,9 +407,8 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$projectDB->deleteDocument($current); //throw new Exception('User already logged in', 401);
|
||||
}
|
||||
|
||||
$user = (empty($user->getId())) ? $projectDB->getCollection([ // Get user by provider id
|
||||
$user = (empty($user->getId())) ? $projectDB->getCollectionFirst([ // Get user by provider id
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'oauth2'.\ucfirst($provider).'='.$oauth2ID,
|
||||
|
@ -422,9 +419,8 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
$name = $oauth2->getUserName($accessToken);
|
||||
$email = $oauth2->getUserEmail($accessToken);
|
||||
|
||||
$user = $projectDB->getCollection([ // Get user by provider email address
|
||||
$user = $projectDB->getCollectionFirst([ // Get user by provider email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -500,8 +496,9 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
|
|||
->addHeader('X-Fallback-Cookies', \json_encode([Auth::$cookieName => Auth::encodeSession($user->getId(), $secret)]))
|
||||
;
|
||||
}
|
||||
|
||||
if ($state['success'] === $oauthDefaultSuccess) { // Add keys for non-web platforms
|
||||
|
||||
// Add keys for non-web platforms - TODO - add verification phase to aviod session sniffing
|
||||
if (parse_url($state['success'], PHP_URL_PATH) === $oauthDefaultSuccess) {
|
||||
$state['success'] = URLParser::parse($state['success']);
|
||||
$query = URLParser::parseQuery($state['success']['query']);
|
||||
$query['project'] = $project->getId();
|
||||
|
@ -774,9 +771,8 @@ $utopia->patch('/v1/account/email')
|
|||
throw new Exception('Invalid credentials', 401);
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -1030,9 +1026,8 @@ $utopia->post('/v1/account/recovery')
|
|||
->param('url', '', function () use ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.')
|
||||
->action(
|
||||
function ($email, $url) use ($request, $response, $projectDB, $mail, $audit, $project) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -1136,9 +1131,8 @@ $utopia->put('/v1/account/recovery')
|
|||
throw new Exception('Passwords must match', 400);
|
||||
}
|
||||
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
@ -1288,9 +1282,8 @@ $utopia->put('/v1/account/verification')
|
|||
->param('secret', '', function () { return new Text(256); }, 'Valid verification token.')
|
||||
->action(
|
||||
function ($userId, $secret) use ($response, $user, $projectDB, $audit) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
global $utopia, $request, $response;
|
||||
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
|
@ -364,7 +365,7 @@ $utopia->get('/v1/avatars/qr')
|
|||
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
|
||||
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
|
||||
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
|
||||
->param('download', 0, function () { return new Range(0, 1); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
|
||||
->param('download', false, function () { return new Boolean(true); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
|
||||
->label('scope', 'avatars.read')
|
||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||
->label('sdk.namespace', 'avatars')
|
||||
|
@ -373,6 +374,8 @@ $utopia->get('/v1/avatars/qr')
|
|||
->label('sdk.description', '/docs/references/avatars/get-qr.md')
|
||||
->action(
|
||||
function ($text, $size, $margin, $download) use ($response) {
|
||||
$download = ($download === '1' || $download === 'true' || $download === 1 || $download === true);
|
||||
|
||||
$renderer = new ImageRenderer(
|
||||
new RendererStyle($size, $margin),
|
||||
new ImagickImageBackEnd('png', 100)
|
||||
|
|
|
@ -5,14 +5,15 @@ global $utopia, $register, $request, $response, $webhook, $audit, $projectDB;
|
|||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\JSON;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
// use Utopia\Locale\Locale;
|
||||
// use Utopia\Audit\Audit;
|
||||
// use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Appwrite\Database\Database;
|
||||
use Appwrite\Database\Document;
|
||||
use Appwrite\Database\Validator\UID;
|
||||
|
@ -22,8 +23,9 @@ use Appwrite\Database\Validator\Collection;
|
|||
use Appwrite\Database\Validator\Authorization;
|
||||
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
||||
use Appwrite\Database\Exception\Structure as StructureException;
|
||||
use DeviceDetector\DeviceDetector;
|
||||
use GeoIp2\Database\Reader;
|
||||
|
||||
// use DeviceDetector\DeviceDetector;
|
||||
// use GeoIp2\Database\Reader;
|
||||
|
||||
$utopia->post('/v1/database/collections')
|
||||
->desc('Create Collection')
|
||||
|
@ -462,10 +464,8 @@ $utopia->get('/v1/database/collections/:collectionId/documents')
|
|||
->param('orderType', 'ASC', function () { return new WhiteList(array('DESC', 'ASC')); }, 'Order direction. Possible values are DESC for descending order, or ASC for ascending order.', true)
|
||||
->param('orderCast', 'string', function () { return new WhiteList(array('int', 'string', 'date', 'time', 'datetime')); }, 'Order field type casting. Possible values are int, string, date, time or datetime. The database will attempt to cast the order field to the value you pass here. The default value is a string.', true)
|
||||
->param('search', '', function () { return new Text(256); }, 'Search query. Enter any free text search. The database will try to find a match against all document attributes and children.', true)
|
||||
->param('first', 0, function () { return new Range(0, 1); }, 'Return only the first document. Pass 1 for true or 0 for false. The default value is 0.', true)
|
||||
->param('last', 0, function () { return new Range(0, 1); }, 'Return only the last document. Pass 1 for true or 0 for false. The default value is 0.', true)
|
||||
->action(
|
||||
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search, $first, $last) use ($response, $projectDB, $utopia) {
|
||||
function ($collectionId, $filters, $offset, $limit, $orderField, $orderType, $orderCast, $search) use ($response, $projectDB, $utopia) {
|
||||
$collection = $projectDB->getDocument($collectionId, false);
|
||||
|
||||
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
||||
|
@ -479,38 +479,32 @@ $utopia->get('/v1/database/collections/:collectionId/documents')
|
|||
'orderType' => $orderType,
|
||||
'orderCast' => $orderCast,
|
||||
'search' => $search,
|
||||
'first' => (bool) $first,
|
||||
'last' => (bool) $last,
|
||||
'filters' => \array_merge($filters, [
|
||||
'$collection='.$collectionId,
|
||||
]),
|
||||
]);
|
||||
|
||||
if ($first || $last) {
|
||||
$response->json((!empty($list) ? $list->getArrayCopy() : []));
|
||||
} else {
|
||||
if ($utopia->isDevelopment()) {
|
||||
$collection
|
||||
->setAttribute('debug', $projectDB->getDebug())
|
||||
->setAttribute('limit', $limit)
|
||||
->setAttribute('offset', $offset)
|
||||
->setAttribute('orderField', $orderField)
|
||||
->setAttribute('orderType', $orderType)
|
||||
->setAttribute('orderCast', $orderCast)
|
||||
->setAttribute('filters', $filters)
|
||||
;
|
||||
}
|
||||
|
||||
if ($utopia->isDevelopment()) {
|
||||
$collection
|
||||
->setAttribute('sum', $projectDB->getSum())
|
||||
->setAttribute('documents', $list)
|
||||
->setAttribute('debug', $projectDB->getDebug())
|
||||
->setAttribute('limit', $limit)
|
||||
->setAttribute('offset', $offset)
|
||||
->setAttribute('orderField', $orderField)
|
||||
->setAttribute('orderType', $orderType)
|
||||
->setAttribute('orderCast', $orderCast)
|
||||
->setAttribute('filters', $filters)
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
||||
}
|
||||
|
||||
$collection
|
||||
->setAttribute('sum', $projectDB->getSum())
|
||||
->setAttribute('documents', $list)
|
||||
;
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ global $utopia, $request, $response, $register, $user, $consoleDB, $projectDB, $
|
|||
use Utopia\Exception;
|
||||
use Utopia\Response;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Domain as DomainValidator;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\URL;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Domains\Domain;
|
||||
|
@ -454,7 +454,7 @@ $utopia->post('/v1/projects/:projectId/webhooks')
|
|||
->param('name', null, function () { return new Text(256); }, 'Webhook name.')
|
||||
->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list.')
|
||||
->param('url', null, function () { return new Text(2000); }, 'Webhook URL.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.')
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true)
|
||||
->action(
|
||||
|
@ -465,6 +465,7 @@ $utopia->post('/v1/projects/:projectId/webhooks')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -587,8 +588,7 @@ $utopia->put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
->param('name', null, function () { return new Text(256); }, 'Webhook name.')
|
||||
->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list.')
|
||||
->param('url', null, function () { return new Text(2000); }, 'Webhook URL.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user.', true)
|
||||
->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password.', true)
|
||||
->action(
|
||||
function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) {
|
||||
|
@ -598,6 +598,7 @@ $utopia->put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -835,8 +836,7 @@ $utopia->post('/v1/projects/:projectId/tasks')
|
|||
->param('name', null, function () { return new Text(256); }, 'Task name.')
|
||||
->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status.')
|
||||
->param('schedule', null, function () { return new Cron(); }, 'Task schedule CRON syntax.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.') ->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('httpUrl', '', function () { return new URL(); }, 'Task HTTP URL')
|
||||
->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true)
|
||||
->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user.', true)
|
||||
|
@ -852,6 +852,7 @@ $utopia->post('/v1/projects/:projectId/tasks')
|
|||
$cron = CronExpression::factory($schedule);
|
||||
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
@ -985,7 +986,7 @@ $utopia->put('/v1/projects/:projectId/tasks/:taskId')
|
|||
->param('name', null, function () { return new Text(256); }, 'Task name.')
|
||||
->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status.')
|
||||
->param('schedule', null, function () { return new Cron(); }, 'Task schedule CRON syntax.')
|
||||
->param('security', null, function () { return new Range(0, 1); }, 'Certificate verification, 0 for disabled or 1 for enabled.')
|
||||
->param('security', false, function () { return new Boolean(true); }, 'Certificate verification, false for disabled or true for enabled.')
|
||||
->param('httpMethod', '', function () { return new WhiteList(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']); }, 'Task HTTP method.')
|
||||
->param('httpUrl', '', function () { return new URL(); }, 'Task HTTP URL.')
|
||||
->param('httpHeaders', null, function () { return new ArrayList(new Text(256)); }, 'Task HTTP headers list.', true)
|
||||
|
@ -1008,6 +1009,7 @@ $utopia->put('/v1/projects/:projectId/tasks/:taskId')
|
|||
$cron = CronExpression::factory($schedule);
|
||||
$next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null;
|
||||
|
||||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
$key = $request->getServer('_APP_OPENSSL_KEY_V1');
|
||||
$iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM));
|
||||
$tag = null;
|
||||
|
|
|
@ -237,9 +237,8 @@ $utopia->post('/v1/teams/:teamId/memberships')
|
|||
],
|
||||
]);
|
||||
|
||||
$invitee = $projectDB->getCollection([ // Get user by email address
|
||||
$invitee = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
@ -468,9 +467,8 @@ $utopia->patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
|||
}
|
||||
|
||||
if (empty($user->getId())) {
|
||||
$user = $projectDB->getCollection([ // Get user
|
||||
$user = $projectDB->getCollectionFirst([ // Get user
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'$id='.$userId,
|
||||
|
|
|
@ -34,9 +34,8 @@ $utopia->post('/v1/users')
|
|||
->param('name', '', function () { return new Text(100); }, 'User name.', true)
|
||||
->action(
|
||||
function ($email, $password, $name) use ($response, $projectDB) {
|
||||
$profile = $projectDB->getCollection([ // Get user by email address
|
||||
$profile = $projectDB->getCollectionFirst([ // Get user by email address
|
||||
'limit' => 1,
|
||||
'first' => true,
|
||||
'filters' => [
|
||||
'$collection='.Database::SYSTEM_COLLECTION_USERS,
|
||||
'email='.$email,
|
||||
|
|
|
@ -167,7 +167,9 @@ $utopia->get('/open-api-2.json')
|
|||
->param('extensions', 0, function () {return new Range(0, 1);}, 'Show extra data.', true)
|
||||
->param('tests', 0, function () {return new Range(0, 1);}, 'Include only test services.', true)
|
||||
->action(
|
||||
function ($platform, $extensions, $tests) use ($response, $request, $utopia, $services) {
|
||||
function ($platform, $extensions, $tests) use ($response, $request, $utopia) {
|
||||
$services = Config::getParam('services', []);
|
||||
|
||||
function fromCamelCase($input)
|
||||
{
|
||||
\preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
|
||||
|
@ -455,6 +457,10 @@ $utopia->get('/open-api-2.json')
|
|||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(fromCamelCase($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
$node['type'] = 'boolean';
|
||||
$node['x-example'] = false;
|
||||
break;
|
||||
case 'Appwrite\Database\Validator\UID':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(fromCamelCase($node['name'])).']';
|
||||
|
|
|
@ -62,6 +62,8 @@ Config::load('providers', __DIR__.'/../app/config/providers.php');
|
|||
Config::load('platforms', __DIR__.'/../app/config/platforms.php');
|
||||
Config::load('locales', __DIR__.'/../app/config/locales.php');
|
||||
Config::load('collections', __DIR__.'/../app/config/collections.php');
|
||||
Config::load('roles', __DIR__.'/../app/config/roles.php'); // User roles and scopes
|
||||
Config::load('services', __DIR__.'/../app/config/services.php'); // List of services
|
||||
|
||||
Config::setParam('env', $utopia->getMode());
|
||||
Config::setParam('domain', $request->getServer('HTTP_HOST', ''));
|
||||
|
@ -200,7 +202,6 @@ Locale::setLanguage('nl', include __DIR__.'/config/locales/nl.php');
|
|||
Locale::setLanguage('no', include __DIR__.'/config/locales/no.php');
|
||||
Locale::setLanguage('ph', include __DIR__.'/config/locales/ph.php');
|
||||
Locale::setLanguage('pl', include __DIR__.'/config/locales/pl.php');
|
||||
Locale::setLanguage('pn', include __DIR__.'/config/locales/pn.php');
|
||||
Locale::setLanguage('pt-br', include __DIR__.'/config/locales/pt-br.php');
|
||||
Locale::setLanguage('pt-pt', include __DIR__.'/config/locales/pt-pt.php');
|
||||
Locale::setLanguage('ro', include __DIR__.'/config/locales/ro.php');
|
||||
|
|
|
@ -309,13 +309,14 @@ $providers = $this->getParam('providers', []);
|
|||
if (isset($data['enabled']) && !$data['enabled']) { continue; }
|
||||
if (isset($data['mock']) && $data['mock']) { continue; }
|
||||
$form = (isset($data['form'])) ? $data['form'] : false;
|
||||
$name = (isset($data['name'])) ? $data['name'] : 'Unknown';
|
||||
$beta = (isset($data['beta'])) ? $data['beta'] : false;
|
||||
?>
|
||||
<li class="<?php echo (isset($data['enabled']) && !$data['enabled']) ? 'dev-feature' : ''; ?>">
|
||||
<div data-ui-modal class="modal close" data-button-alias="none" data-open-event="provider-update-<?php echo $provider; ?>">
|
||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||
|
||||
<h1><?php echo $this->escape(ucfirst($provider)); ?> OAuth2 Settings</h1>
|
||||
<h1><?php echo $this->escape($name); ?> OAuth2 Settings</h1>
|
||||
|
||||
<form
|
||||
data-analytics-event="submit"
|
||||
|
@ -379,7 +380,7 @@ $providers = $this->getParam('providers', []);
|
|||
<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 class="text-size-small">
|
||||
<?php echo ucfirst($provider); ?> <?php if($beta): ?>(beta)<?php endif; ?>
|
||||
<?php echo $this->escape($name); ?> <?php if($beta): ?>(beta)<?php endif; ?>
|
||||
</span>
|
||||
|
||||
<p class="margin-bottom-no text-one-liner text-size-small">
|
||||
|
|
|
@ -77,7 +77,7 @@ class CertificatesV1
|
|||
}
|
||||
}
|
||||
|
||||
$certificate = $consoleDB->getCollection([
|
||||
$certificate = $consoleDB->getCollectionFirst([
|
||||
'limit' => 1,
|
||||
'offset' => 0,
|
||||
'orderField' => 'id',
|
||||
|
@ -87,7 +87,6 @@ class CertificatesV1
|
|||
'$collection='.Database::SYSTEM_COLLECTION_CERTIFICATES,
|
||||
'domain='.$domain->get(),
|
||||
],
|
||||
'first' => true,
|
||||
]);
|
||||
|
||||
// $condition = ($certificate
|
||||
|
|
1
bin/test
1
bin/test
|
@ -1,4 +1,3 @@
|
|||
|
||||
#!/bin/bash
|
||||
|
||||
/usr/share/nginx/html/vendor/bin/phpunit --configuration /usr/share/nginx/html/phpunit.xml
|
25
composer.lock
generated
25
composer.lock
generated
|
@ -1998,16 +1998,16 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "a491d65139e2411c75704e871dd02bdddf5a4bdc"
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/a491d65139e2411c75704e871dd02bdddf5a4bdc",
|
||||
"reference": "a491d65139e2411c75704e871dd02bdddf5a4bdc",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"myclabs/deep-copy": "self.version"
|
||||
|
@ -2038,7 +2038,7 @@
|
|||
"object",
|
||||
"object graph"
|
||||
],
|
||||
"time": "2020-03-12T21:49:07+00:00"
|
||||
"time": "2020-06-29T13:22:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
|
@ -2197,24 +2197,23 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "790426f28bfcbfc1a6f1d59ee8c986edfa45395c"
|
||||
"reference": "664187301bfbc87e686df212094e6817805c3ab8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/790426f28bfcbfc1a6f1d59ee8c986edfa45395c",
|
||||
"reference": "790426f28bfcbfc1a6f1d59ee8c986edfa45395c",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/664187301bfbc87e686df212094e6817805c3ab8",
|
||||
"reference": "664187301bfbc87e686df212094e6817805c3ab8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-filter": "^7.1",
|
||||
"php": "^7.2",
|
||||
"ext-filter": "*",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpdocumentor/reflection-common": "^2.0",
|
||||
"phpdocumentor/type-resolver": "^1.0",
|
||||
"webmozart/assert": "^1"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/instantiator": "^1",
|
||||
"mockery/mockery": "^1"
|
||||
"mockery/mockery": "1.3.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -2242,7 +2241,7 @@
|
|||
}
|
||||
],
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"time": "2020-06-19T18:58:43+00:00"
|
||||
"time": "2020-06-27T17:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
|
|
|
@ -2,7 +2,7 @@ version: '3'
|
|||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.1.4
|
||||
image: traefik:2.2
|
||||
container_name: appwrite_traefik
|
||||
command:
|
||||
- --log.level=DEBUG
|
||||
|
@ -50,7 +50,7 @@ services:
|
|||
- ./phpunit.xml:/usr/share/nginx/html/phpunit.xml
|
||||
- ./tests:/usr/share/nginx/html/tests
|
||||
- ./app:/usr/share/nginx/html/app
|
||||
# - ./vendor:/usr/share/nginx/html/vendor
|
||||
# - ./vendor:/usr/share/nginx/html/vendor
|
||||
- ./docs:/usr/share/nginx/html/docs
|
||||
- ./public:/usr/share/nginx/html/public
|
||||
- ./src:/usr/share/nginx/html/src
|
||||
|
@ -130,7 +130,7 @@ services:
|
|||
- appwrite-redis:/data:rw
|
||||
|
||||
clamav:
|
||||
image: appwrite/clamav:1.0.9
|
||||
image: appwrite/clamav:1.0.12
|
||||
container_name: appwrite_clamav
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
|
4
public/dist/scripts/app-all.js
vendored
4
public/dist/scripts/app-all.js
vendored
|
@ -2630,8 +2630,8 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
|
|||
if(target){target=document.getElementById(target);}
|
||||
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
|
||||
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
|
||||
element.disabled=true;alerts.add({text:"Copied to clipboard",class:""},3000);});let check=function(){if(!element.value){return;}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
window.getSelection().removeAllRanges();});let check=function(){if(!element.value){return;}
|
||||
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
|
||||
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}
|
||||
function syncA(){element.value=picker.value;update();}
|
||||
|
|
4
public/dist/scripts/app.js
vendored
4
public/dist/scripts/app.js
vendored
|
@ -316,8 +316,8 @@ var project=router.params["project"]||'None';ga("set","page",window.location.pat
|
|||
if(target){target=document.getElementById(target);}
|
||||
button.addEventListener("click",function(){var clone=document.createElement(element.tagName);if(element.name){clone.name=element.name;}
|
||||
clone.innerHTML=template;clone.className=element.className;view.render(clone);if(target){target.appendChild(clone);}else{button.parentNode.insertBefore(clone,button);}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){element.disabled=false;element.focus();element.select();document.execCommand("Copy");if(document.selection){document.selection.empty();}else if(window.getSelection){window.getSelection().removeAllRanges();}
|
||||
element.disabled=true;alerts.add({text:"Copied to clipboard",class:""},3000);});let check=function(){if(!element.value){return;}
|
||||
clone.querySelector("input").focus();Array.prototype.slice.call(clone.querySelectorAll("[data-remove]")).map(function(obj){obj.addEventListener("click",function(){clone.parentNode.removeChild(clone);obj.scrollIntoView({behavior:"smooth"});});});Array.prototype.slice.call(clone.querySelectorAll("[data-up]")).map(function(obj){obj.addEventListener("click",function(){if(clone.previousElementSibling){clone.parentNode.insertBefore(clone,clone.previousElementSibling);obj.scrollIntoView({behavior:"smooth"});}});});Array.prototype.slice.call(clone.querySelectorAll("[data-down]")).map(function(obj){obj.addEventListener("click",function(){if(clone.nextElementSibling){clone.parentNode.insertBefore(clone.nextElementSibling,clone);obj.scrollIntoView({behavior:"smooth"});}});});});element.parentNode.insertBefore(button,element.nextSibling);element.parentNode.removeChild(element);if(first){button.click();}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-add",repeat:false,controller:function(element,view,container,document){for(var i=0;i<element.children.length;i++){let button=document.createElement("button");let template=element.children[i].cloneNode(true);let as=element.getAttribute('data-ls-as');let counter=0;button.type="button";button.innerText="Add";button.classList.add("reverse");button.classList.add("margin-end-small");button.addEventListener('click',function(){container.addNamespace(as,'new-'+counter++);console.log(container.namespaces,container.get(as),as);container.set(as,null,true,true);let child=template.cloneNode(true);view.render(child);element.appendChild(child);element.style.visibility='visible';let inputs=child.querySelectorAll('input,textarea');for(let index=0;index<inputs.length;++index){if(inputs[index].type!=='hidden'){inputs[index].focus();break;}}});element.after(button);}}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-code",controller:function(element,alerts){let lang=element.dataset["formsCode"]||"json";let div=document.createElement("div");let pre=document.createElement("pre");let code=document.createElement("code");let copy=document.createElement("i");div.appendChild(pre);div.appendChild(copy);pre.appendChild(code);element.parentNode.appendChild(div);div.className="ide";pre.className="line-numbers";code.className="prism language-"+lang;copy.className="icon-docs copy";copy.textContent="Click Here to Copy";copy.title="Copy to Clipboard";copy.addEventListener("click",function(){window.getSelection().removeAllRanges();let range=document.createRange();range.selectNode(code);window.getSelection().addRange(range);try{document.execCommand("copy");alerts.add({text:"Copied to clipboard",class:""},3000);}catch(err){alerts.add({text:"Failed to copy text ",class:"error"},3000);}
|
||||
window.getSelection().removeAllRanges();});let check=function(){if(!element.value){return;}
|
||||
let value=null;try{value=JSON.stringify(JSON.parse(element.value),null,4);}catch(error){value=element.value;}
|
||||
code.innerHTML=value;Prism.highlightElement(code);div.scrollTop=0;};element.addEventListener("change",check);check();}});})(window);(function(window){"use strict";window.ls.container.get("view").add({selector:"data-forms-color",controller:function(element){var preview=document.createElement("div");var picker=document.createElement("input");picker.type="color";preview.className="color-preview";preview.appendChild(picker);picker.addEventListener("change",syncA);picker.addEventListener("input",syncA);element.addEventListener("input",update);element.addEventListener("change",update);function update(){if(element.validity.valid){preview.style.background=element.value;syncB();}}
|
||||
function syncA(){element.value=picker.value;update();}
|
||||
|
|
2
public/dist/styles/default-ltr.css
vendored
2
public/dist/styles/default-ltr.css
vendored
File diff suppressed because one or more lines are too long
2
public/dist/styles/default-rtl.css
vendored
2
public/dist/styles/default-rtl.css
vendored
File diff suppressed because one or more lines are too long
BIN
public/images/oauth2/box.png
Normal file
BIN
public/images/oauth2/box.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4 KiB |
BIN
public/images/oauth2/paypalsandbox.png
Normal file
BIN
public/images/oauth2/paypalsandbox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
|
@ -20,26 +20,26 @@
|
|||
pre.className = "line-numbers";
|
||||
code.className = "prism language-" + lang;
|
||||
copy.className = "icon-docs copy";
|
||||
|
||||
copy.textContent = "Click Here to Copy";
|
||||
copy.title = "Copy to Clipboard";
|
||||
|
||||
copy.addEventListener("click", function() {
|
||||
element.disabled = false;
|
||||
window.getSelection().removeAllRanges();
|
||||
|
||||
element.focus();
|
||||
element.select();
|
||||
let range = document.createRange();
|
||||
|
||||
document.execCommand("Copy");
|
||||
range.selectNode(code);
|
||||
|
||||
if (document.selection) {
|
||||
document.selection.empty();
|
||||
} else if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(range);
|
||||
|
||||
try {
|
||||
document.execCommand("copy");
|
||||
alerts.add({ text: "Copied to clipboard", class: "" }, 3000);
|
||||
} catch (err) {
|
||||
alerts.add({ text: "Failed to copy text ", class: "error" }, 3000);
|
||||
}
|
||||
|
||||
element.disabled = true;
|
||||
|
||||
alerts.add({ text: "Copied to clipboard", class: "" }, 3000);
|
||||
window.getSelection().removeAllRanges();
|
||||
});
|
||||
|
||||
let check = function() {
|
||||
|
|
|
@ -555,7 +555,7 @@
|
|||
|
||||
.community {
|
||||
a {
|
||||
padding: 5px 10px;
|
||||
padding: 0 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ abstract class OAuth2
|
|||
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
\curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
\curl_setopt($ch, CURLOPT_USERAGENT, '');
|
||||
\curl_setopt($ch, CURLOPT_USERAGENT, 'Appwrite OAuth2');
|
||||
|
||||
if (!empty($payload)) {
|
||||
\curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
|
|
152
src/Appwrite/Auth/OAuth2/Box.php
Normal file
152
src/Appwrite/Auth/OAuth2/Box.php
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2;
|
||||
|
||||
// Reference Material
|
||||
// https://developer.box.com/reference/
|
||||
|
||||
class Box extends OAuth2
|
||||
{
|
||||
|
||||
private $endpoint = 'https://account.box.com/api/oauth2/';
|
||||
|
||||
private $resourceEndpoint = 'https://api.box.com/2.0/';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $user = [];
|
||||
|
||||
protected $scopes = [
|
||||
'manage_app_users',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'box';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLoginURL(): string
|
||||
{
|
||||
$url = $this->endpoint . 'authorize?'.
|
||||
\http_build_query([
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->appID,
|
||||
'scope' => \implode(',', $this->getScopes()),
|
||||
'redirect_uri' => $this->callback,
|
||||
'state' => \json_encode($this->state),
|
||||
]);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessToken(string $code): string
|
||||
{
|
||||
$header = "Content-Type: application/x-www-form-urlencoded";
|
||||
$accessToken = $this->request(
|
||||
'POST',
|
||||
$this->endpoint . 'token',
|
||||
[$header],
|
||||
\http_build_query([
|
||||
"client_id" => $this->appID,
|
||||
"client_secret" => $this->appSecret,
|
||||
"code" => $code,
|
||||
"grant_type" => "authorization_code",
|
||||
"scope" => \implode(',', $this->getScopes()),
|
||||
"redirect_uri" => $this->callback
|
||||
])
|
||||
);
|
||||
|
||||
$accessToken = \json_decode($accessToken, true);
|
||||
|
||||
if (array_key_exists('access_token', $accessToken)) {
|
||||
return $accessToken['access_token'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserID(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['id'])) {
|
||||
return $user['id'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserEmail(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['login'])) {
|
||||
return $user['login'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(string $accessToken): string
|
||||
{
|
||||
$user = $this->getUser($accessToken);
|
||||
|
||||
if (isset($user['name'])) {
|
||||
return $user['name'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $accessToken
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken): array
|
||||
{
|
||||
$header = [
|
||||
'Authorization: Bearer '.\urlencode($accessToken),
|
||||
];
|
||||
if (empty($this->user)) {
|
||||
$user = $this->request(
|
||||
'GET',
|
||||
$this->resourceEndpoint . 'me',
|
||||
$header
|
||||
);
|
||||
$this->user = \json_decode($user, true);
|
||||
}
|
||||
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,7 @@ class Github extends OAuth2
|
|||
* @var array
|
||||
*/
|
||||
protected $scopes = [
|
||||
'user:email'
|
||||
'user:email',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -125,7 +125,7 @@ class Github extends OAuth2
|
|||
* @return array
|
||||
*/
|
||||
protected function getUser(string $accessToken)
|
||||
{
|
||||
{
|
||||
if (empty($this->user)) {
|
||||
$this->user = \json_decode($this->request('GET', 'https://api.github.com/user', ['Authorization: token '.\urlencode($accessToken)]), true);
|
||||
}
|
|
@ -22,7 +22,7 @@ class Paypal extends OAuth2
|
|||
'live' => 'https://api.paypal.com/v1/',
|
||||
];
|
||||
|
||||
private $environment = 'live';
|
||||
protected $environment = 'live';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
|
|
19
src/Appwrite/Auth/OAuth2/PaypalSandbox.php
Normal file
19
src/Appwrite/Auth/OAuth2/PaypalSandbox.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Auth\OAuth2;
|
||||
|
||||
use Appwrite\Auth\OAuth2\Paypal;
|
||||
|
||||
|
||||
class PaypalSandbox extends Paypal
|
||||
{
|
||||
protected $environment = 'sandbox';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'paypalSandbox';
|
||||
}
|
||||
}
|
|
@ -130,8 +130,6 @@ class Database
|
|||
'orderField' => '$id',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'first' => false,
|
||||
'last' => false,
|
||||
'filters' => [],
|
||||
], $options);
|
||||
|
||||
|
@ -141,17 +139,31 @@ class Database
|
|||
$node = new Document($node);
|
||||
}
|
||||
|
||||
if ($options['first']) {
|
||||
$results = \reset($results);
|
||||
}
|
||||
|
||||
if ($options['last']) {
|
||||
$results = \end($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function getCollectionFirst(array $options)
|
||||
{
|
||||
$results = $this->getCollection($options);
|
||||
return \reset($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function getCollectionLast(array $options)
|
||||
{
|
||||
$results = $this->getCollection($options);
|
||||
return \end($results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param bool $mock is mocked data allowed?
|
||||
|
|
|
@ -317,41 +317,6 @@ trait DatabaseBase
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDocument
|
||||
*/
|
||||
public function testListDocumentsFirstAndLast(array $data):array
|
||||
{
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'limit' => 1,
|
||||
'orderField' => 'releaseYear',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'first' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(1944, $documents['body']['releaseYear']);
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'limit' => 2,
|
||||
'offset' => 1,
|
||||
'orderField' => 'releaseYear',
|
||||
'orderType' => 'ASC',
|
||||
'orderCast' => 'int',
|
||||
'last' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(2019, $documents['body']['releaseYear']);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreateDocument
|
||||
*/
|
||||
|
|
|
@ -227,7 +227,7 @@ trait LocaleBase
|
|||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-locale' => $lang,
|
||||
]);
|
||||
|
||||
|
||||
foreach ($response['body'] as $i => $code) {
|
||||
$this->assertArrayHasKey($i, $defaultCountries, $i . ' country should be removed from ' . $lang);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue