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

Merge branch '0.7.x' of https://github.com/appwrite/appwrite into feat-migration-v06

This commit is contained in:
Torsten Dittmann 2021-01-15 15:11:17 +01:00
commit a965268826
13 changed files with 402 additions and 124 deletions

View file

@ -13,20 +13,20 @@ services:
- docker
before_install:
- curl -fsSL https://get.docker.com | sh
- echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json
- mkdir -p $HOME/.docker
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
- sudo service docker start
- >
if [ ! -z "${DOCKERHUB_PULL_USERNAME:-}" ]; then
set +x
echo "${DOCKERHUB_PULL_PASSWORD}" | docker login --username "${DOCKERHUB_PULL_USERNAME}" --password-stdin
set -x
fi
- curl -fsSL https://get.docker.com | sh
- echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json
- mkdir -p $HOME/.docker
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
- sudo service docker start
- >
if [ ! -z "${DOCKERHUB_PULL_USERNAME:-}" ]; then
set +x
echo "${DOCKERHUB_PULL_PASSWORD}" | docker login --username "${DOCKERHUB_PULL_USERNAME}" --password-stdin
set -x
fi
- docker --version
install:
- docker --version
- docker-compose up -d
- sleep 10

View file

@ -37,9 +37,11 @@
- Added new environment variables for ClamAV hostname and port ([#780](https://github.com/appwrite/appwrite/pull/780))
- New OAuth adapter for Box.com (@armino-dev - [#420](https://github.com/appwrite/appwrite/issues/410))
- New OAuth adapter for PayPal sandbox (@armino-dev - [#420](https://github.com/appwrite/appwrite/issues/410))
- Introducing new permssion types: role:guest, role:member, role:app.
- Introducing new permssion types: role:guest, role:member, role:app
- Disabled rate-limits on server side integrations
### User Interface
- Updated grid for OAuth2 providers list in the console ([#413](https://github.com/appwrite/appwrite/issues/413))
- Added Google Fonts to Appwrite for offline availability
- Added option to delete user from the console (@PineappleIOnic - [#538](https://github.com/appwrite/appwrite/issues/538))
@ -54,6 +56,7 @@
- Added toggle to hide/show secret keys and passwords inside the dashboard (@kodumbeats, [#535](https://github.com/appwrite/appwrite/issues/535))
### Upgrades
- Upgraded QR codes generator library (@PedroCisnerosSantana - [#475](https://github.com/appwrite/appwrite/issues/475))
- Upgraded Traefik image to version 2.3
- Upgraded MariaDB to version 10.5.5
@ -64,6 +67,7 @@
- Upgraded device detctor to version 3.12.6
## Breaking Changes (Read before upgrading!)
- **Deprecated** `first` and `last` query params for documents list route in the database API
- **Deprecated** Deprectaed Pubjabi Translations ('pn')
- **Deprecated** `PATCH /account/prefs` is now updating the prefs payload and not just merging it
@ -101,6 +105,7 @@
- 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
- Fixed a bug making read permission overwrite write permission in some cases
## Security
- Access to Health API now requires authentication with an API Key with access to `health.read` scope allowed

View file

@ -1,5 +1,6 @@
<?php
use Ahc\Jwt\JWT;
use Utopia\App;
use Utopia\Exception;
use Utopia\Config\Config;
@ -637,6 +638,49 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
;
});
App::post('/v1/account/jwt')
->desc('Create Account JWT')
->groups(['api', 'account'])
->label('scope', 'account')
->label('sdk.platform', [APP_PLATFORM_CLIENT])
->label('sdk.namespace', 'account')
->label('sdk.method', 'createJWT')
->label('sdk.description', '/docs/references/account/create-jwt.md')
->label('abuse-limit', 10)
->label('abuse-key', 'url:{url},userId:{param-userId}')
->inject('response')
->inject('user')
->action(function ($response, $user) {
/** @var Appwrite\Utopia\Response $response */
/** @var Appwrite\Database\Document $user */
$tokens = $user->getAttribute('tokens', []);
$session = new Document();
foreach ($tokens as $token) { /** @var Appwrite\Database\Document $token */
if ($token->getAttribute('secret') == Auth::hash(Auth::$secret)) { // If current session delete the cookies too
$session = $token;
}
}
if($session->isEmpty()) {
throw new Exception('No valid session found', 401);
}
$jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic(new Document(['jwt' => $jwt->encode([
// 'uid' => 1,
// 'aud' => 'http://site.com',
// 'scopes' => ['user'],
// 'iss' => 'http://api.mysite.com',
'userId' => $user->getId(),
'sessionId' => $session->getId(),
])]), Response::MODEL_JWT);
});
App::get('/v1/account')
->desc('Get Account')
->groups(['api', 'account'])

View file

@ -157,7 +157,7 @@ App::get('/v1/functions/:functionId/usage')
throw new Exception('Function not found', 404);
}
if($App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$period = [
'24h' => [
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),

View file

@ -164,27 +164,31 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
$roles = Config::getParam('roles', []);
$scope = $route->getLabel('scope', 'none'); // Allowed scope for chosen route
$scopes = $roles[$role]['scopes']; // Allowed scopes for user role
// Check if given key match project API keys
$key = $project->search('secret', $request->getHeader('x-appwrite-key', ''), $project->getAttribute('keys', []));
/*
* Try app auth when we have project key and no user
* Mock user to app and grant API key scopes in addition to default app scopes
*/
if (null !== $key && $user->isEmpty()) {
$user = new Document([
'$id' => '',
'status' => Auth::USER_STATUS_ACTIVATED,
'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(),
'password' => '',
'name' => $project->getAttribute('name', 'Untitled'),
]);
$role = Auth::USER_ROLE_APP;
$scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', []));
$authKey = $request->getHeader('x-appwrite-key', '');
Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys.
if (!empty($authKey)) { // API Key authentication
// Check if given key match project API keys
$key = $project->search('secret', $authKey, $project->getAttribute('keys', []));
/*
* Try app auth when we have project key and no user
* Mock user to app and grant API key scopes in addition to default app scopes
*/
if ($key && $user->isEmpty()) {
$user = new Document([
'$id' => '',
'status' => Auth::USER_STATUS_ACTIVATED,
'email' => 'app.'.$project->getId().'@service.'.$request->getHostname(),
'password' => '',
'name' => $project->getAttribute('name', 'Untitled'),
]);
$role = Auth::USER_ROLE_APP;
$scopes = \array_merge($roles[$role]['scopes'], $key->getAttribute('scopes', []));
Authorization::setDefaultStatus(false); // Cancel security segmentation for API keys.
}
}
if ($user->getId()) {

View file

@ -11,6 +11,8 @@ if (\file_exists(__DIR__.'/../vendor/autoload.php')) {
require_once __DIR__.'/../vendor/autoload.php';
}
use Ahc\Jwt\JWT;
use Ahc\Jwt\JWTException;
use Appwrite\Auth\Auth;
use Appwrite\Database\Database;
use Appwrite\Database\Adapter\MySQL as MySQLAdapter;
@ -412,6 +414,29 @@ App::setResource('user', function($mode, $project, $console, $request, $response
}
}
$authJWT = $request->getHeader('x-appwrite-jwt', '');
if (!empty($authJWT)) { // JWT authentication
$jwt = new JWT(App::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', 900, 10); // Instantiate with key, algo, maxAge and leeway.
try {
$payload = $jwt->decode($authJWT);
} catch (JWTException $error) {
throw new Exception('Failed to verify JWT. '.$error->getMessage(), 401);
}
$jwtUserId = $payload['userId'] ?? '';
$jwtSessionId = $payload['sessionId'] ?? '';
if($jwtUserId && $jwtSessionId) {
$user = $projectDB->getDocument($jwtUserId);
}
if (empty($user->search('$id', $jwtSessionId, $user->getAttribute('tokens')))) { // Match JWT to active token
$user = new Document(['$id' => '', '$collection' => Database::SYSTEM_COLLECTION_USERS]);
}
}
return $user;
}, ['mode', 'project', 'console', 'request', 'response', 'projectDB', 'consoleDB']);

View file

@ -471,7 +471,7 @@ class FunctionsV1
->setParam('networkResponseSize', 0)
;
if($App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
$usage->trigger();
}

View file

@ -52,7 +52,8 @@
"domnikl/statsd": "3.0.2",
"influxdb/influxdb-php": "1.15.1",
"phpmailer/phpmailer": "6.1.7",
"chillerlan/php-qrcode": "4.3.0"
"chillerlan/php-qrcode": "4.3.0",
"adhocore/jwt": "1.1.0"
},
"require-dev": {
"swoole/ide-helper": "4.5.5",

233
composer.lock generated
View file

@ -4,8 +4,65 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "249dc088c5f9f74a1c0e91661f93f96b",
"content-hash": "2a235acbc30e22872101713bf3602351",
"packages": [
{
"name": "adhocore/jwt",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/adhocore/php-jwt.git",
"reference": "424a1d66b729a316dd074e6382167765b810cd3d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/adhocore/php-jwt/zipball/424a1d66b729a316dd074e6382167765b810cd3d",
"reference": "424a1d66b729a316dd074e6382167765b810cd3d",
"shasum": ""
},
"require": {
"php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "^6.5 || ^7.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Ahc\\Jwt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jitendra Adhikari",
"email": "jiten.adhikary@gmail.com"
}
],
"description": "Ultra lightweight JSON web token (JWT) library for PHP5.5+.",
"keywords": [
"auth",
"json-web-token",
"jwt",
"jwt-auth",
"jwt-php",
"token"
],
"support": {
"issues": "https://github.com/adhocore/php-jwt/issues",
"source": "https://github.com/adhocore/php-jwt/tree/1.1.0"
},
"funding": [
{
"url": "https://paypal.me/ji10",
"type": "custom"
}
],
"time": "2020-10-09T00:34:35+00:00"
},
{
"name": "appwrite/php-clamav",
"version": "v1.0.1",
@ -1702,23 +1759,23 @@
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "efca2b32a7580087adb8aabbff6be1dc1bb924a9"
"reference": "7d4bbc6e0b47c6bb39b6cce1a4b5942e0c5125fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/efca2b32a7580087adb8aabbff6be1dc1bb924a9",
"reference": "efca2b32a7580087adb8aabbff6be1dc1bb924a9",
"url": "https://api.github.com/repos/amphp/amp/zipball/7d4bbc6e0b47c6bb39b6cce1a4b5942e0c5125fb",
"reference": "7d4bbc6e0b47c6bb39b6cce1a4b5942e0c5125fb",
"shasum": ""
},
"require": {
"php": ">=7"
"php": ">=7.1"
},
"require-dev": {
"amphp/php-cs-fixer-config": "dev-master",
"amphp/phpunit-util": "^1",
"ext-json": "*",
"jetbrains/phpstorm-stubs": "^2019.3",
"phpunit/phpunit": "^6.0.9 | ^7",
"phpunit/phpunit": "^7 | ^8 | ^9",
"psalm/phar": "^3.11@dev",
"react/promise": "^2"
},
@ -1776,7 +1833,7 @@
"support": {
"irc": "irc://irc.freenode.org/amphp",
"issues": "https://github.com/amphp/amp/issues",
"source": "https://github.com/amphp/amp/tree/v2.5.2"
"source": "https://github.com/amphp/amp/tree/master"
},
"funding": [
{
@ -1784,7 +1841,7 @@
"type": "github"
}
],
"time": "2021-01-10T17:06:37+00:00"
"time": "2021-01-13T19:16:50+00:00"
},
{
"name": "amphp/byte-stream",
@ -3102,12 +3159,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cdb8225b328ef5e9647049954299211804000ce0"
"reference": "0837b6d36db129e8e9478d39f2f2cd9e40eaef97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cdb8225b328ef5e9647049954299211804000ce0",
"reference": "cdb8225b328ef5e9647049954299211804000ce0",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/0837b6d36db129e8e9478d39f2f2cd9e40eaef97",
"reference": "0837b6d36db129e8e9478d39f2f2cd9e40eaef97",
"shasum": ""
},
"require": {
@ -3155,7 +3212,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:20+00:00"
"time": "2021-01-14T08:06:22+00:00"
},
{
"name": "phpunit/php-invoker",
@ -3163,12 +3220,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
"reference": "6fdda2828180f7d86cf66d822e6ad4bc124baf5d"
"reference": "cc5d70ab3d26c07ca2c5a7edaa4df1b64ffce737"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/6fdda2828180f7d86cf66d822e6ad4bc124baf5d",
"reference": "6fdda2828180f7d86cf66d822e6ad4bc124baf5d",
"url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/cc5d70ab3d26c07ca2c5a7edaa4df1b64ffce737",
"reference": "cc5d70ab3d26c07ca2c5a7edaa4df1b64ffce737",
"shasum": ""
},
"require": {
@ -3219,7 +3276,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:25+00:00"
"time": "2021-01-14T08:06:31+00:00"
},
{
"name": "phpunit/php-text-template",
@ -3227,12 +3284,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "081fc9efc54b1b858b3497c142d82a0c36bc6755"
"reference": "4bf8e2b779618907e744fd8c221a669d481ae522"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/081fc9efc54b1b858b3497c142d82a0c36bc6755",
"reference": "081fc9efc54b1b858b3497c142d82a0c36bc6755",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/4bf8e2b779618907e744fd8c221a669d481ae522",
"reference": "4bf8e2b779618907e744fd8c221a669d481ae522",
"shasum": ""
},
"require": {
@ -3279,7 +3336,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:47+00:00"
"time": "2021-01-14T08:07:09+00:00"
},
{
"name": "phpunit/php-timer",
@ -3287,12 +3344,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "2194371fec37b03cfda3f8ab08aee33787350228"
"reference": "5b6fb138e2bba0d33bc043ccfc58caa585a1b666"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2194371fec37b03cfda3f8ab08aee33787350228",
"reference": "2194371fec37b03cfda3f8ab08aee33787350228",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5b6fb138e2bba0d33bc043ccfc58caa585a1b666",
"reference": "5b6fb138e2bba0d33bc043ccfc58caa585a1b666",
"shasum": ""
},
"require": {
@ -3339,7 +3396,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:31+00:00"
"time": "2021-01-14T08:06:40+00:00"
},
{
"name": "phpunit/phpunit",
@ -3504,12 +3561,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "1012bd8df812778b8386c5e76cacd85b45cf329e"
"reference": "b9d0154b00cd0c232d2fb04c7a41aef04a3ef388"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/1012bd8df812778b8386c5e76cacd85b45cf329e",
"reference": "1012bd8df812778b8386c5e76cacd85b45cf329e",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/b9d0154b00cd0c232d2fb04c7a41aef04a3ef388",
"reference": "b9d0154b00cd0c232d2fb04c7a41aef04a3ef388",
"shasum": ""
},
"require": {
@ -3553,7 +3610,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:23:03+00:00"
"time": "2021-01-14T08:07:37+00:00"
},
{
"name": "sebastian/code-unit",
@ -3617,12 +3674,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
"reference": "f0a408b6519db241e624a62576dc5871d4ac8c14"
"reference": "e9fb7de0109de478aa512d6001b95c9111259cb4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/f0a408b6519db241e624a62576dc5871d4ac8c14",
"reference": "f0a408b6519db241e624a62576dc5871d4ac8c14",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/e9fb7de0109de478aa512d6001b95c9111259cb4",
"reference": "e9fb7de0109de478aa512d6001b95c9111259cb4",
"shasum": ""
},
"require": {
@ -3665,7 +3722,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:21:36+00:00"
"time": "2021-01-14T08:05:02+00:00"
},
{
"name": "sebastian/comparator",
@ -3673,12 +3730,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "fe4c68c639d9e580ec31bfc88b32641dc80a08d0"
"reference": "1803ef9c6631bec96ba12adb392d9bdd80bffccc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fe4c68c639d9e580ec31bfc88b32641dc80a08d0",
"reference": "fe4c68c639d9e580ec31bfc88b32641dc80a08d0",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1803ef9c6631bec96ba12adb392d9bdd80bffccc",
"reference": "1803ef9c6631bec96ba12adb392d9bdd80bffccc",
"shasum": ""
},
"require": {
@ -3740,7 +3797,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:21:42+00:00"
"time": "2021-01-14T08:05:14+00:00"
},
{
"name": "sebastian/complexity",
@ -3748,12 +3805,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "c182133e92fc7a8b0a923b5d20f3a9fdfa534818"
"reference": "c2deec80b7a2df9556d77cb98e238a8a4780ca32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c182133e92fc7a8b0a923b5d20f3a9fdfa534818",
"reference": "c182133e92fc7a8b0a923b5d20f3a9fdfa534818",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c2deec80b7a2df9556d77cb98e238a8a4780ca32",
"reference": "c2deec80b7a2df9556d77cb98e238a8a4780ca32",
"shasum": ""
},
"require": {
@ -3798,7 +3855,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:53+00:00"
"time": "2021-01-14T08:07:18+00:00"
},
{
"name": "sebastian/diff",
@ -3806,12 +3863,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "33f7bf3c1741b2a10e16d5c41c369c402b933e4c"
"reference": "3768e4448231a9ed88b8b82d14e3c86c60bc24e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/33f7bf3c1741b2a10e16d5c41c369c402b933e4c",
"reference": "33f7bf3c1741b2a10e16d5c41c369c402b933e4c",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3768e4448231a9ed88b8b82d14e3c86c60bc24e0",
"reference": "3768e4448231a9ed88b8b82d14e3c86c60bc24e0",
"shasum": ""
},
"require": {
@ -3865,7 +3922,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:21:47+00:00"
"time": "2021-01-14T08:05:23+00:00"
},
{
"name": "sebastian/environment",
@ -3873,12 +3930,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "b885263b3601b7570ef386a468d6a827c95c8994"
"reference": "23c7b3502969bd25c425f74484a99763e48bdeec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/b885263b3601b7570ef386a468d6a827c95c8994",
"reference": "b885263b3601b7570ef386a468d6a827c95c8994",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/23c7b3502969bd25c425f74484a99763e48bdeec",
"reference": "23c7b3502969bd25c425f74484a99763e48bdeec",
"shasum": ""
},
"require": {
@ -3929,7 +3986,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:21:52+00:00"
"time": "2021-01-14T08:05:33+00:00"
},
{
"name": "sebastian/exporter",
@ -3937,12 +3994,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "f670c4f17dffab83b44048f6fe6747a7c6097179"
"reference": "3e0ddb2289e17efc39cf03cb6a93286d3ac37de9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f670c4f17dffab83b44048f6fe6747a7c6097179",
"reference": "f670c4f17dffab83b44048f6fe6747a7c6097179",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3e0ddb2289e17efc39cf03cb6a93286d3ac37de9",
"reference": "3e0ddb2289e17efc39cf03cb6a93286d3ac37de9",
"shasum": ""
},
"require": {
@ -4007,7 +4064,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:21:58+00:00"
"time": "2021-01-14T08:05:42+00:00"
},
{
"name": "sebastian/global-state",
@ -4015,12 +4072,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "a74d82a0654a7f685f80016cc3570d7a387f9da0"
"reference": "d172b1d21828f3034f064b02b584b6c86399baa1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a74d82a0654a7f685f80016cc3570d7a387f9da0",
"reference": "a74d82a0654a7f685f80016cc3570d7a387f9da0",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/d172b1d21828f3034f064b02b584b6c86399baa1",
"reference": "d172b1d21828f3034f064b02b584b6c86399baa1",
"shasum": ""
},
"require": {
@ -4072,7 +4129,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:03+00:00"
"time": "2021-01-14T08:05:52+00:00"
},
{
"name": "sebastian/lines-of-code",
@ -4080,12 +4137,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "db62e01f14ea9485d5a52dfb5706061fd0f50425"
"reference": "ec5577068ba8a8f56fcfe66239bfbae6c2af6819"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/db62e01f14ea9485d5a52dfb5706061fd0f50425",
"reference": "db62e01f14ea9485d5a52dfb5706061fd0f50425",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/ec5577068ba8a8f56fcfe66239bfbae6c2af6819",
"reference": "ec5577068ba8a8f56fcfe66239bfbae6c2af6819",
"shasum": ""
},
"require": {
@ -4130,7 +4187,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:58+00:00"
"time": "2021-01-14T08:07:28+00:00"
},
{
"name": "sebastian/object-enumerator",
@ -4138,12 +4195,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
"reference": "fccb61351e8a3a10ffacfad9544bb2905905b69c"
"reference": "9d9fa9141b9dbc5141a930d30c932634ea714bf2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/fccb61351e8a3a10ffacfad9544bb2905905b69c",
"reference": "fccb61351e8a3a10ffacfad9544bb2905905b69c",
"url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/9d9fa9141b9dbc5141a930d30c932634ea714bf2",
"reference": "9d9fa9141b9dbc5141a930d30c932634ea714bf2",
"shasum": ""
},
"require": {
@ -4188,7 +4245,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:09+00:00"
"time": "2021-01-14T08:06:01+00:00"
},
{
"name": "sebastian/object-reflector",
@ -4196,12 +4253,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
"reference": "c0ad4ce74e040797d5f8abfc23ab79fd79b064c3"
"reference": "3c2c8cdd6e598e61fe9182663bc5c65152570af0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/c0ad4ce74e040797d5f8abfc23ab79fd79b064c3",
"reference": "c0ad4ce74e040797d5f8abfc23ab79fd79b064c3",
"url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/3c2c8cdd6e598e61fe9182663bc5c65152570af0",
"reference": "3c2c8cdd6e598e61fe9182663bc5c65152570af0",
"shasum": ""
},
"require": {
@ -4244,7 +4301,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:14+00:00"
"time": "2021-01-14T08:06:12+00:00"
},
{
"name": "sebastian/recursion-context",
@ -4252,12 +4309,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "c5616ce32278e62c77066f72b1fe413a8c958cee"
"reference": "f56f4b45cf5b284977639e9c13bcabb8e10e0d95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/c5616ce32278e62c77066f72b1fe413a8c958cee",
"reference": "c5616ce32278e62c77066f72b1fe413a8c958cee",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f56f4b45cf5b284977639e9c13bcabb8e10e0d95",
"reference": "f56f4b45cf5b284977639e9c13bcabb8e10e0d95",
"shasum": ""
},
"require": {
@ -4308,7 +4365,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:36+00:00"
"time": "2021-01-14T08:06:50+00:00"
},
{
"name": "sebastian/resource-operations",
@ -4372,12 +4429,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
"reference": "655e3b59cc2e508306dba9c3df08b774055548e7"
"reference": "d9383363efecc03b461b82922410e470ee4d13d8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/655e3b59cc2e508306dba9c3df08b774055548e7",
"reference": "655e3b59cc2e508306dba9c3df08b774055548e7",
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/d9383363efecc03b461b82922410e470ee4d13d8",
"reference": "d9383363efecc03b461b82922410e470ee4d13d8",
"shasum": ""
},
"require": {
@ -4421,7 +4478,7 @@
"type": "github"
}
],
"time": "2021-01-02T06:22:42+00:00"
"time": "2021-01-14T08:06:59+00:00"
},
{
"name": "sebastian/version",
@ -4521,12 +4578,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5ff54ffca91d307dfcb144af4748571eb9346b71"
"reference": "356c70659d6b48595f9f275cd7c4de0d5544c49c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5ff54ffca91d307dfcb144af4748571eb9346b71",
"reference": "5ff54ffca91d307dfcb144af4748571eb9346b71",
"url": "https://api.github.com/repos/symfony/console/zipball/356c70659d6b48595f9f275cd7c4de0d5544c49c",
"reference": "356c70659d6b48595f9f275cd7c4de0d5544c49c",
"shasum": ""
},
"require": {
@ -4611,7 +4668,7 @@
"type": "tidelift"
}
],
"time": "2021-01-11T06:08:00+00:00"
"time": "2021-01-14T15:43:35+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -5192,12 +5249,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "7a62495108b3dc7e749b709357ae720fccb5a39b"
"reference": "2f833cf54d5fe9646638c50778016a06b6fe1603"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/7a62495108b3dc7e749b709357ae720fccb5a39b",
"reference": "7a62495108b3dc7e749b709357ae720fccb5a39b",
"url": "https://api.github.com/repos/symfony/string/zipball/2f833cf54d5fe9646638c50778016a06b6fe1603",
"reference": "2f833cf54d5fe9646638c50778016a06b6fe1603",
"shasum": ""
},
"require": {
@ -5268,7 +5325,7 @@
"type": "tidelift"
}
],
"time": "2021-01-10T16:38:27+00:00"
"time": "2021-01-12T14:28:55+00:00"
},
{
"name": "theseer/tokenizer",
@ -5326,12 +5383,12 @@
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "a0e2cc25723f3cdb6bbaf617664c4e228f1e9886"
"reference": "1a0162a612658790cb1f7b468c7698a7ee58001a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a0e2cc25723f3cdb6bbaf617664c4e228f1e9886",
"reference": "a0e2cc25723f3cdb6bbaf617664c4e228f1e9886",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1a0162a612658790cb1f7b468c7698a7ee58001a",
"reference": "1a0162a612658790cb1f7b468c7698a7ee58001a",
"shasum": ""
},
"require": {
@ -5397,7 +5454,7 @@
"type": "tidelift"
}
],
"time": "2021-01-05T15:39:16+00:00"
"time": "2021-01-14T07:57:35+00:00"
},
{
"name": "vimeo/psalm",

View file

@ -0,0 +1 @@
Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout.

View file

@ -21,6 +21,7 @@ use Appwrite\Utopia\Response\Model\ErrorDev;
use Appwrite\Utopia\Response\Model\Execution;
use Appwrite\Utopia\Response\Model\File;
use Appwrite\Utopia\Response\Model\Func;
use Appwrite\Utopia\Response\Model\JWT;
use Appwrite\Utopia\Response\Model\Key;
use Appwrite\Utopia\Response\Model\Language;
use Appwrite\Utopia\Response\Model\User;
@ -66,7 +67,8 @@ class Response extends SwooleResponse
const MODEL_USER_LIST = 'userList';
const MODEL_SESSION = 'session';
const MODEL_SESSION_LIST = 'sessionList';
const MODEL_TOKEN = 'token'; // - Missing
const MODEL_TOKEN = 'token';
const MODEL_JWT = 'jwt';
// Storage
const MODEL_FILE = 'file';
@ -168,6 +170,7 @@ class Response extends SwooleResponse
->setModel(new User())
->setModel(new Session())
->setModel(new Token())
->setModel(new JWT())
->setModel(new Locale())
->setModel(new File())
->setModel(new Team())

View file

@ -0,0 +1,40 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class JWT extends Model
{
public function __construct()
{
$this
->addRule('jwt', [
'type' => self::TYPE_STRING,
'description' => 'JWT encoded string.',
'example' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
])
;
}
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'JWT';
}
/**
* Get Collection
*
* @return string
*/
public function getType():string
{
return Response::MODEL_JWT;
}
}

View file

@ -128,4 +128,102 @@ class AccountCustomClientTest extends Scope
return [];
}
public function testCreateJWT():array
{
$email = uniqid().'user@localhost.test';
$password = 'password';
$name = 'User Name (JWT)';
/**
* Test for SUCCESS
*/
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'email' => $email,
'password' => $password,
'name' => $name,
]);
$id = $response['body']['$id'];
$this->assertEquals($response['headers']['status-code'], 201);
$response = $this->client->call(Client::METHOD_POST, '/account/sessions', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'email' => $email,
'password' => $password,
]);
$this->assertEquals($response['headers']['status-code'], 201);
$sessionId = $response['body']['$id'];
$session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_'.$this->getProject()['$id']];
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]));
$this->assertEquals($response['headers']['status-code'], 200);
$response = $this->client->call(Client::METHOD_POST, '/account/jwt', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]));
$this->assertEquals($response['headers']['status-code'], 201);
$this->assertNotEmpty($response['body']['jwt']);
$this->assertIsString($response['body']['jwt']);
$jwt = $response['body']['jwt'];
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-jwt' => 'wrong-token',
]));
$this->assertEquals($response['headers']['status-code'], 401);
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-jwt' => $jwt,
]));
$this->assertEquals($response['headers']['status-code'], 200);
$response = $this->client->call(Client::METHOD_DELETE, '/account/sessions/'.$sessionId, array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
]));
$this->assertEquals($response['headers']['status-code'], 204);
$response = $this->client->call(Client::METHOD_GET, '/account', array_merge([
'origin' => 'http://localhost',
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-jwt' => $jwt,
]));
$this->assertEquals($response['headers']['status-code'], 401);
return [];
}
}