First commit
This commit is contained in:
parent
64ee540086
commit
e81fb88736
|
@ -28,23 +28,10 @@ use Utopia\Validator\ArrayList;
|
||||||
$oauthDefaultSuccess = App::getEnv('_APP_HOME').'/auth/oauth2/success';
|
$oauthDefaultSuccess = App::getEnv('_APP_HOME').'/auth/oauth2/success';
|
||||||
$oauthDefaultFailure = App::getEnv('_APP_HOME').'/auth/oauth2/failure';
|
$oauthDefaultFailure = App::getEnv('_APP_HOME').'/auth/oauth2/failure';
|
||||||
|
|
||||||
$oauth2Keys = [];
|
|
||||||
|
|
||||||
App::init(function() use (&$oauth2Keys) {
|
|
||||||
foreach (Config::getParam('providers') as $key => $provider) {
|
|
||||||
if (!$provider['enabled']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
|
|
||||||
}
|
|
||||||
}, [], 'account');
|
|
||||||
|
|
||||||
App::post('/v1/account')
|
App::post('/v1/account')
|
||||||
->desc('Create Account')
|
->desc('Create Account')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.create')
|
->label('event', 'account.create')
|
||||||
->label('scope', 'public')
|
->label('scope', 'public')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
|
@ -54,12 +41,11 @@ App::post('/v1/account')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.', true)
|
||||||
->action(function ($email, $password, $name, $request, $response, $project, $projectDB, $webhooks, $audits) use ($oauth2Keys) {
|
->action(function ($email, $password, $name, $request, $response, $project, $projectDB, $audits) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $project */
|
/** @var Appwrite\Database\Document $project */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
if ('console' === $project->getId()) {
|
if ('console' === $project->getId()) {
|
||||||
|
@ -120,36 +106,24 @@ App::post('/v1/account')
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', [
|
|
||||||
'name' => $name,
|
|
||||||
'email' => $email,
|
|
||||||
])
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('userId', $user->getId())
|
->setParam('userId', $user->getId())
|
||||||
->setParam('event', 'account.create')
|
->setParam('event', 'account.create')
|
||||||
->setParam('resource', 'users/'.$user->getId())
|
->setParam('resource', 'users/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response
|
$user
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
->setAttribute('roles', Authorization::getRoles())
|
||||||
->json(\array_merge($user->getArrayCopy(\array_merge(
|
;
|
||||||
[
|
|
||||||
'$id',
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
'email',
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
'registration',
|
}, ['request', 'response', 'project', 'projectDB', 'audits']);
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => Authorization::getRoles()]));
|
|
||||||
}, ['request', 'response', 'project', 'projectDB', 'webhooks', 'audits']);
|
|
||||||
|
|
||||||
App::post('/v1/account/sessions')
|
App::post('/v1/account/sessions')
|
||||||
->desc('Create Account Session')
|
->desc('Create Account Session')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.sessions.create')
|
->label('event', 'account.sessions.create')
|
||||||
->label('scope', 'public')
|
->label('scope', 'public')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
|
@ -159,11 +133,12 @@ App::post('/v1/account/sessions')
|
||||||
->label('abuse-key', 'url:{url},email:{param-email}')
|
->label('abuse-key', 'url:{url},email:{param-email}')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
||||||
->action(function ($email, $password, $request, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($email, $password, $request, $response, $projectDB, $locale, $geodb, $audits) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
|
/** @var MaxMind\Db\Reader $geodb */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
|
@ -185,6 +160,23 @@ App::post('/v1/account/sessions')
|
||||||
throw new Exception('Invalid credentials', 401); // Wrong password or username
|
throw new Exception('Invalid credentials', 401); // Wrong password or username
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dd = new DeviceDetector($request->getUserAgent('UNKNOWN'));
|
||||||
|
|
||||||
|
$dd->parse();
|
||||||
|
|
||||||
|
$os = $dd->getOs();
|
||||||
|
$osCode = (isset($os['short_name'])) ? $os['short_name'] : '';
|
||||||
|
$osName = (isset($os['name'])) ? $os['name'] : '';
|
||||||
|
$osVersion = (isset($os['version'])) ? $os['version'] : '';
|
||||||
|
|
||||||
|
$client = $dd->getClient();
|
||||||
|
$clientType = (isset($client['type'])) ? $client['type'] : '';
|
||||||
|
$clientCode = (isset($client['short_name'])) ? $client['short_name'] : '';
|
||||||
|
$clientName = (isset($client['name'])) ? $client['name'] : '';
|
||||||
|
$clientVersion = (isset($client['version'])) ? $client['version'] : '';
|
||||||
|
$clientEngine = (isset($client['engine'])) ? $client['engine'] : '';
|
||||||
|
$clientEngineVersion = (isset($client['engine_version'])) ? $client['engine_version'] : '';
|
||||||
|
|
||||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||||
$secret = Auth::tokenGenerator();
|
$secret = Auth::tokenGenerator();
|
||||||
$session = new Document([
|
$session = new Document([
|
||||||
|
@ -195,8 +187,33 @@ App::post('/v1/account/sessions')
|
||||||
'expire' => $expiry,
|
'expire' => $expiry,
|
||||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||||
'ip' => $request->getIP(),
|
'ip' => $request->getIP(),
|
||||||
|
|
||||||
|
'osCode' => $osCode,
|
||||||
|
'osName' => $osName,
|
||||||
|
'osVersion' => $osVersion,
|
||||||
|
'clientType' => $clientType,
|
||||||
|
'clientCode' => $clientCode,
|
||||||
|
'clientName' => $clientName,
|
||||||
|
'clientVersion' => $clientVersion,
|
||||||
|
'clientEngine' => $clientEngine,
|
||||||
|
'clientEngineVersion' => $clientEngineVersion,
|
||||||
|
'deviceName' => $dd->getDeviceName(),
|
||||||
|
'deviceBrand' => $dd->getBrandName(),
|
||||||
|
'deviceModel' => $dd->getModel(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$record = $geodb->get($request->getIP());
|
||||||
|
|
||||||
|
if($record) {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', \strtolower($record['country']['iso_code']))
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', '--')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
Authorization::setRole('user:'.$profile->getId());
|
Authorization::setRole('user:'.$profile->getId());
|
||||||
|
|
||||||
$session = $projectDB->createDocument($session->getArrayCopy());
|
$session = $projectDB->createDocument($session->getArrayCopy());
|
||||||
|
@ -212,14 +229,7 @@ App::post('/v1/account/sessions')
|
||||||
if (false === $profile) {
|
if (false === $profile) {
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', [
|
|
||||||
'name' => $profile->getAttribute('name', ''),
|
|
||||||
'email' => $profile->getAttribute('email', ''),
|
|
||||||
])
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('userId', $profile->getId())
|
->setParam('userId', $profile->getId())
|
||||||
->setParam('event', 'account.sessions.create')
|
->setParam('event', 'account.sessions.create')
|
||||||
|
@ -237,10 +247,14 @@ App::post('/v1/account/sessions')
|
||||||
->addCookie(Auth::$cookieName, Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
->addCookie(Auth::$cookieName, Auth::encodeSession($profile->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$session
|
||||||
|
->setAttribute('current', true)
|
||||||
|
->setAttribute('countryName', (isset($countries[$session->getAttribute('countryCode')])) ? $countries[$session->getAttribute('countryCode')] : $locale->getText('locale.country.unknown'))
|
||||||
|
;
|
||||||
|
|
||||||
$response->dynamic($session, Response::MODEL_SESSION);
|
$response->dynamic($session, Response::MODEL_SESSION);
|
||||||
;
|
}, ['request', 'response', 'projectDB', 'locale', 'geodb', 'audits']);
|
||||||
}, ['request', 'response', 'projectDB', 'webhooks', 'audits']);
|
|
||||||
|
|
||||||
App::get('/v1/account/sessions/oauth2/:provider')
|
App::get('/v1/account/sessions/oauth2/:provider')
|
||||||
->desc('Create Account Session with OAuth2')
|
->desc('Create Account Session with OAuth2')
|
||||||
|
@ -348,7 +362,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
->desc('OAuth2 Redirect')
|
->desc('OAuth2 Redirect')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('error', __DIR__.'/../../views/general/error.phtml')
|
->label('error', __DIR__.'/../../views/general/error.phtml')
|
||||||
->label('webhook', 'account.sessions.create')
|
->label('event', 'account.sessions.create')
|
||||||
->label('scope', 'public')
|
->label('scope', 'public')
|
||||||
->label('abuse-limit', 50)
|
->label('abuse-limit', 50)
|
||||||
->label('abuse-key', 'ip:{ip}')
|
->label('abuse-key', 'ip:{ip}')
|
||||||
|
@ -356,12 +370,13 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 provider.')
|
->param('provider', '', new WhiteList(\array_keys(Config::getParam('providers')), true), 'OAuth2 provider.')
|
||||||
->param('code', '', new Text(1024), 'OAuth2 code.')
|
->param('code', '', new Text(1024), 'OAuth2 code.')
|
||||||
->param('state', '', new Text(2048), 'OAuth2 state params.', true)
|
->param('state', '', new Text(2048), 'OAuth2 state params.', true)
|
||||||
->action(function ($provider, $code, $state, $request, $response, $project, $user, $projectDB, $audits) use ($oauthDefaultSuccess) {
|
->action(function ($provider, $code, $state, $request, $response, $project, $user, $projectDB, $geodb, $audits) use ($oauthDefaultSuccess) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $project */
|
/** @var Appwrite\Database\Document $project */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var MaxMind\Db\Reader $geodb */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
|
@ -482,6 +497,24 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
|
|
||||||
// Create session token, verify user account and update OAuth2 ID and Access Token
|
// Create session token, verify user account and update OAuth2 ID and Access Token
|
||||||
|
|
||||||
|
|
||||||
|
$dd = new DeviceDetector($request->getUserAgent('UNKNOWN'));
|
||||||
|
|
||||||
|
$dd->parse();
|
||||||
|
|
||||||
|
$os = $dd->getOs();
|
||||||
|
$osCode = (isset($os['short_name'])) ? $os['short_name'] : '';
|
||||||
|
$osName = (isset($os['name'])) ? $os['name'] : '';
|
||||||
|
$osVersion = (isset($os['version'])) ? $os['version'] : '';
|
||||||
|
|
||||||
|
$client = $dd->getClient();
|
||||||
|
$clientType = (isset($client['type'])) ? $client['type'] : '';
|
||||||
|
$clientCode = (isset($client['short_name'])) ? $client['short_name'] : '';
|
||||||
|
$clientName = (isset($client['name'])) ? $client['name'] : '';
|
||||||
|
$clientVersion = (isset($client['version'])) ? $client['version'] : '';
|
||||||
|
$clientEngine = (isset($client['engine'])) ? $client['engine'] : '';
|
||||||
|
$clientEngineVersion = (isset($client['engine_version'])) ? $client['engine_version'] : '';
|
||||||
|
|
||||||
$secret = Auth::tokenGenerator();
|
$secret = Auth::tokenGenerator();
|
||||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||||
$session = new Document([
|
$session = new Document([
|
||||||
|
@ -492,8 +525,33 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
'expire' => $expiry,
|
'expire' => $expiry,
|
||||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||||
'ip' => $request->getIP(),
|
'ip' => $request->getIP(),
|
||||||
|
|
||||||
|
'osCode' => $osCode,
|
||||||
|
'osName' => $osName,
|
||||||
|
'osVersion' => $osVersion,
|
||||||
|
'clientType' => $clientType,
|
||||||
|
'clientCode' => $clientCode,
|
||||||
|
'clientName' => $clientName,
|
||||||
|
'clientVersion' => $clientVersion,
|
||||||
|
'clientEngine' => $clientEngine,
|
||||||
|
'clientEngineVersion' => $clientEngineVersion,
|
||||||
|
'deviceName' => $dd->getDeviceName(),
|
||||||
|
'deviceBrand' => $dd->getBrandName(),
|
||||||
|
'deviceModel' => $dd->getModel(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$record = $geodb->get($request->getIP());
|
||||||
|
|
||||||
|
if($record) {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', \strtolower($record['country']['iso_code']))
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', '--')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
$user
|
$user
|
||||||
->setAttribute('oauth2'.\ucfirst($provider), $oauth2ID)
|
->setAttribute('oauth2'.\ucfirst($provider), $oauth2ID)
|
||||||
->setAttribute('oauth2'.\ucfirst($provider).'AccessToken', $accessToken)
|
->setAttribute('oauth2'.\ucfirst($provider).'AccessToken', $accessToken)
|
||||||
|
@ -523,7 +581,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add keys for non-web platforms - TODO - add verification phase to aviod session sniffing
|
// Add keys for non-web platforms - TODO - add verification phase to aviod session sniffing
|
||||||
if (parse_url($state['success'], PHP_URL_PATH) === $oauthDefaultSuccess) {
|
if (parse_url($state['success'], PHP_URL_PATH) === parse_url($oauthDefaultSuccess, PHP_URL_PATH)) {
|
||||||
$state['success'] = URLParser::parse($state['success']);
|
$state['success'] = URLParser::parse($state['success']);
|
||||||
$query = URLParser::parseQuery($state['success']['query']);
|
$query = URLParser::parseQuery($state['success']['query']);
|
||||||
$query['project'] = $project->getId();
|
$query['project'] = $project->getId();
|
||||||
|
@ -541,7 +599,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||||
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), $expiry, '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
|
||||||
->redirect($state['success'])
|
->redirect($state['success'])
|
||||||
;
|
;
|
||||||
}, ['request', 'response', 'project', 'user', 'projectDB', 'audits']);
|
}, ['request', 'response', 'project', 'user', 'projectDB', 'geodb', 'audits']);
|
||||||
|
|
||||||
App::get('/v1/account')
|
App::get('/v1/account')
|
||||||
->desc('Get Account')
|
->desc('Get Account')
|
||||||
|
@ -552,20 +610,15 @@ App::get('/v1/account')
|
||||||
->label('sdk.method', 'get')
|
->label('sdk.method', 'get')
|
||||||
->label('sdk.description', '/docs/references/account/get.md')
|
->label('sdk.description', '/docs/references/account/get.md')
|
||||||
->label('sdk.response', ['200' => 'user'])
|
->label('sdk.response', ['200' => 'user'])
|
||||||
->action(function ($response, $user) use ($oauth2Keys) {
|
->action(function ($response, $user) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
|
|
||||||
$response->json(\array_merge($user->getArrayCopy(\array_merge(
|
$user
|
||||||
[
|
->setAttribute('roles', Authorization::getRoles())
|
||||||
'$id',
|
;
|
||||||
'email',
|
|
||||||
'emailVerification',
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
'registration',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => Authorization::getRoles()]));
|
|
||||||
}, ['response', 'user']);
|
}, ['response', 'user']);
|
||||||
|
|
||||||
App::get('/v1/account/prefs')
|
App::get('/v1/account/prefs')
|
||||||
|
@ -580,14 +633,7 @@ App::get('/v1/account/prefs')
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
|
|
||||||
$prefs = $user->getAttribute('prefs', '{}');
|
$prefs = $user->getAttribute('prefs', new \stdClass);
|
||||||
|
|
||||||
try {
|
|
||||||
$prefs = \json_decode($prefs, true);
|
|
||||||
$prefs = ($prefs) ? $prefs : [];
|
|
||||||
} catch (\Exception $error) {
|
|
||||||
throw new Exception('Failed to parse prefs', 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->json($prefs);
|
$response->json($prefs);
|
||||||
}, ['response', 'user']);
|
}, ['response', 'user']);
|
||||||
|
@ -600,64 +646,34 @@ App::get('/v1/account/sessions')
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
->label('sdk.method', 'getSessions')
|
->label('sdk.method', 'getSessions')
|
||||||
->label('sdk.description', '/docs/references/account/get-sessions.md')
|
->label('sdk.description', '/docs/references/account/get-sessions.md')
|
||||||
->action(function ($response, $user, $locale, $geodb) {
|
->action(function ($response, $user, $locale) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Utopia\Locale\Locale $locale */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
/** @var MaxMind\Db\Reader $geodb */
|
|
||||||
|
|
||||||
$tokens = $user->getAttribute('tokens', []);
|
$tokens = $user->getAttribute('tokens', []);
|
||||||
$sessions = [];
|
$sessions = [];
|
||||||
$current = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
|
|
||||||
$index = 0;
|
|
||||||
$countries = $locale->getText('countries');
|
$countries = $locale->getText('countries');
|
||||||
|
$current = Auth::tokenVerify($tokens, Auth::TOKEN_TYPE_LOGIN, Auth::$secret);
|
||||||
|
|
||||||
foreach ($tokens as $token) { /* @var $token Document */
|
foreach ($tokens as $token) { /* @var $token Document */
|
||||||
if (Auth::TOKEN_TYPE_LOGIN != $token->getAttribute('type')) {
|
if (Auth::TOKEN_TYPE_LOGIN != $token->getAttribute('type')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$userAgent = (!empty($token->getAttribute('userAgent'))) ? $token->getAttribute('userAgent') : 'UNKNOWN';
|
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
|
||||||
|
? $countries[$token->getAttribute('contryCode')]
|
||||||
|
: $locale->getText('locale.country.unknown'));
|
||||||
|
$token->setAttribute('current', ($current == $token->getId()) ? true : false);
|
||||||
|
|
||||||
$dd = new DeviceDetector($userAgent);
|
$sessions[] = $token;
|
||||||
|
|
||||||
// OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
|
|
||||||
// $dd->skipBotDetection();
|
|
||||||
|
|
||||||
$dd->parse();
|
|
||||||
|
|
||||||
$sessions[$index] = [
|
|
||||||
'$id' => $token->getId(),
|
|
||||||
'OS' => $dd->getOs(),
|
|
||||||
'client' => $dd->getClient(),
|
|
||||||
'device' => $dd->getDevice(),
|
|
||||||
'brand' => $dd->getBrand(),
|
|
||||||
'model' => $dd->getModel(),
|
|
||||||
'ip' => $token->getAttribute('ip', ''),
|
|
||||||
'geo' => [],
|
|
||||||
'current' => ($current == $token->getId()) ? true : false,
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$record = $geodb->get($token->getAttribute('ip', ''));
|
|
||||||
|
|
||||||
if ($record) {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = \strtolower($record['country']['iso_code']);
|
|
||||||
$sessions[$index]['geo']['country'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
|
||||||
} else {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = '--';
|
|
||||||
$sessions[$index]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = '--';
|
|
||||||
$sessions[$index]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
|
||||||
|
|
||||||
++$index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($sessions);
|
$response->dynamic(new Document([
|
||||||
}, ['response', 'user', 'locale', 'geodb']);
|
'sum' => count($sessions),
|
||||||
|
'sessions' => $sessions
|
||||||
|
]), Response::MODEL_SESSION_LIST);
|
||||||
|
}, ['response', 'user', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/account/logs')
|
App::get('/v1/account/logs')
|
||||||
->desc('Get Account Logs')
|
->desc('Get Account Logs')
|
||||||
|
@ -709,48 +725,64 @@ App::get('/v1/account/logs')
|
||||||
|
|
||||||
$dd->parse();
|
$dd->parse();
|
||||||
|
|
||||||
$output[$i] = [
|
$os = $dd->getOs();
|
||||||
|
$osCode = (isset($os['short_name'])) ? $os['short_name'] : '';
|
||||||
|
$osName = (isset($os['name'])) ? $os['name'] : '';
|
||||||
|
$osVersion = (isset($os['version'])) ? $os['version'] : '';
|
||||||
|
|
||||||
|
$client = $dd->getClient();
|
||||||
|
$clientType = (isset($client['type'])) ? $client['type'] : '';
|
||||||
|
$clientCode = (isset($client['short_name'])) ? $client['short_name'] : '';
|
||||||
|
$clientName = (isset($client['name'])) ? $client['name'] : '';
|
||||||
|
$clientVersion = (isset($client['version'])) ? $client['version'] : '';
|
||||||
|
$clientEngine = (isset($client['engine'])) ? $client['engine'] : '';
|
||||||
|
$clientEngineVersion = (isset($client['engine_version'])) ? $client['engine_version'] : '';
|
||||||
|
|
||||||
|
$output[$i] = new Document([
|
||||||
'event' => $log['event'],
|
'event' => $log['event'],
|
||||||
'ip' => $log['ip'],
|
'ip' => $log['ip'],
|
||||||
'time' => \strtotime($log['time']),
|
'time' => \strtotime($log['time']),
|
||||||
'OS' => $dd->getOs(),
|
|
||||||
'client' => $dd->getClient(),
|
|
||||||
'device' => $dd->getDevice(),
|
|
||||||
'brand' => $dd->getBrand(),
|
|
||||||
'model' => $dd->getModel(),
|
|
||||||
'geo' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
'osCode' => $osCode,
|
||||||
$record = $geodb->get($log['ip']);
|
'osName' => $osName,
|
||||||
|
'osVersion' => $osVersion,
|
||||||
|
'clientType' => $clientType,
|
||||||
|
'clientCode' => $clientCode,
|
||||||
|
'clientName' => $clientName,
|
||||||
|
'clientVersion' => $clientVersion,
|
||||||
|
'clientEngine' => $clientEngine,
|
||||||
|
'clientEngineVersion' => $clientEngineVersion,
|
||||||
|
'deviceName' => $dd->getDeviceName(),
|
||||||
|
'deviceBrand' => $dd->getBrandName(),
|
||||||
|
'deviceModel' => $dd->getModel(),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($record) {
|
$record = $geodb->get($log['ip']);
|
||||||
$output[$i]['geo']['isoCode'] = \strtolower($record['country']['iso_code']);
|
|
||||||
$output[$i]['geo']['country'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
if ($record) {
|
||||||
} else {
|
$output[$i]['countryCode'] = (isset($countries[$record['country']['iso_code']])) ? \strtolower($record['country']['iso_code']) : '--';
|
||||||
$output[$i]['geo']['isoCode'] = '--';
|
$output[$i]['countryName'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
||||||
$output[$i]['geo']['country'] = $locale->getText('locale.country.unknown');
|
} else {
|
||||||
}
|
$output[$i]['countryCode'] = '--';
|
||||||
} catch (\Exception $e) {
|
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
|
||||||
$output[$i]['geo']['isoCode'] = '--';
|
|
||||||
$output[$i]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($output);
|
$response->dynamic(new Document(['logs' => $output]), Response::MODEL_LOG_LIST);
|
||||||
}, ['response', 'register', 'project', 'user', 'locale', 'geodb']);
|
}, ['response', 'register', 'project', 'user', 'locale', 'geodb']);
|
||||||
|
|
||||||
App::patch('/v1/account/name')
|
App::patch('/v1/account/name')
|
||||||
->desc('Update Account Name')
|
->desc('Update Account Name')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.update.name')
|
->label('event', 'account.update.name')
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
->label('sdk.method', 'updateName')
|
->label('sdk.method', 'updateName')
|
||||||
->label('sdk.description', '/docs/references/account/update-name.md')
|
->label('sdk.description', '/docs/references/account/update-name.md')
|
||||||
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
|
->param('name', '', new Text(128), 'User name. Max length: 128 chars.')
|
||||||
->action(function ($name, $response, $user, $projectDB, $audits) use ($oauth2Keys) {
|
->action(function ($name, $response, $user, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
@ -764,27 +796,21 @@ App::patch('/v1/account/name')
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->setAttribute('roles', Authorization::getRoles());
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('userId', $user->getId())
|
->setParam('userId', $user->getId())
|
||||||
->setParam('event', 'account.update.name')
|
->setParam('event', 'account.update.name')
|
||||||
->setParam('resource', 'users/'.$user->getId())
|
->setParam('resource', 'users/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->json(\array_merge($user->getArrayCopy(\array_merge(
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
[
|
|
||||||
'$id',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => Authorization::getRoles()]));
|
|
||||||
}, ['response', 'user', 'projectDB', 'audits']);
|
}, ['response', 'user', 'projectDB', 'audits']);
|
||||||
|
|
||||||
App::patch('/v1/account/password')
|
App::patch('/v1/account/password')
|
||||||
->desc('Update Account Password')
|
->desc('Update Account Password')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.update.password')
|
->label('event', 'account.update.password')
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
|
@ -792,7 +818,7 @@ App::patch('/v1/account/password')
|
||||||
->label('sdk.description', '/docs/references/account/update-password.md')
|
->label('sdk.description', '/docs/references/account/update-password.md')
|
||||||
->param('password', '', new Password(), 'New user password. Must be between 6 to 32 chars.')
|
->param('password', '', new Password(), 'New user password. Must be between 6 to 32 chars.')
|
||||||
->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.')
|
->param('oldPassword', '', new Password(), 'Old user password. Must be between 6 to 32 chars.')
|
||||||
->action(function ($password, $oldPassword, $response, $user, $projectDB, $audits) use ($oauth2Keys) {
|
->action(function ($password, $oldPassword, $response, $user, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
@ -810,27 +836,21 @@ App::patch('/v1/account/password')
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->setAttribute('roles', Authorization::getRoles());
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('userId', $user->getId())
|
->setParam('userId', $user->getId())
|
||||||
->setParam('event', 'account.update.password')
|
->setParam('event', 'account.update.password')
|
||||||
->setParam('resource', 'users/'.$user->getId())
|
->setParam('resource', 'users/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->json(\array_merge($user->getArrayCopy(\array_merge(
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
[
|
|
||||||
'$id',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => Authorization::getRoles()]));
|
|
||||||
}, ['response', 'user', 'projectDB', 'audits']);
|
}, ['response', 'user', 'projectDB', 'audits']);
|
||||||
|
|
||||||
App::patch('/v1/account/email')
|
App::patch('/v1/account/email')
|
||||||
->desc('Update Account Email')
|
->desc('Update Account Email')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.update.email')
|
->label('event', 'account.update.email')
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
|
@ -838,7 +858,7 @@ App::patch('/v1/account/email')
|
||||||
->label('sdk.description', '/docs/references/account/update-email.md')
|
->label('sdk.description', '/docs/references/account/update-email.md')
|
||||||
->param('email', '', new Email(), 'User email.')
|
->param('email', '', new Email(), 'User email.')
|
||||||
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
->param('password', '', new Password(), 'User password. Must be between 6 to 32 chars.')
|
||||||
->action(function ($email, $password, $response, $user, $projectDB, $audits) use ($oauth2Keys) {
|
->action(function ($email, $password, $response, $user, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
@ -871,44 +891,35 @@ App::patch('/v1/account/email')
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user->setAttribute('roles', Authorization::getRoles());
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('userId', $user->getId())
|
->setParam('userId', $user->getId())
|
||||||
->setParam('event', 'account.update.email')
|
->setParam('event', 'account.update.email')
|
||||||
->setParam('resource', 'users/'.$user->getId())
|
->setParam('resource', 'users/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->json(\array_merge($user->getArrayCopy(\array_merge(
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
[
|
|
||||||
'$id',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => Authorization::getRoles()]));
|
|
||||||
}, ['response', 'user', 'projectDB', 'audits']);
|
}, ['response', 'user', 'projectDB', 'audits']);
|
||||||
|
|
||||||
App::patch('/v1/account/prefs')
|
App::patch('/v1/account/prefs')
|
||||||
->desc('Update Account Preferences')
|
->desc('Update Account Preferences')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.update.prefs')
|
->label('event', 'account.update.prefs')
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
->label('sdk.method', 'updatePrefs')
|
->label('sdk.method', 'updatePrefs')
|
||||||
->param('prefs', '', new Assoc(), 'Prefs key-value JSON object.')
|
|
||||||
->label('sdk.description', '/docs/references/account/update-prefs.md')
|
->label('sdk.description', '/docs/references/account/update-prefs.md')
|
||||||
|
->param('prefs', [], new Assoc(), 'Prefs key-value JSON object.')
|
||||||
->action(function ($prefs, $response, $user, $projectDB, $audits) {
|
->action(function ($prefs, $response, $user, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$old = \json_decode($user->getAttribute('prefs', '{}'), true);
|
|
||||||
$old = ($old) ? $old : [];
|
|
||||||
|
|
||||||
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
||||||
'prefs' => \json_encode(\array_merge($old, $prefs)),
|
'prefs' => $prefs,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
if (false === $user) {
|
if (false === $user) {
|
||||||
|
@ -920,14 +931,7 @@ App::patch('/v1/account/prefs')
|
||||||
->setParam('resource', 'users/'.$user->getId())
|
->setParam('resource', 'users/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$prefs = $user->getAttribute('prefs', '{}');
|
$prefs = $user->getAttribute('prefs', new \stdClass);
|
||||||
|
|
||||||
try {
|
|
||||||
$prefs = \json_decode($prefs, true);
|
|
||||||
$prefs = ($prefs) ? $prefs : [];
|
|
||||||
} catch (\Exception $error) {
|
|
||||||
throw new Exception('Failed to parse prefs', 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->json($prefs);
|
$response->json($prefs);
|
||||||
}, ['response', 'user', 'projectDB', 'audits']);
|
}, ['response', 'user', 'projectDB', 'audits']);
|
||||||
|
@ -935,7 +939,7 @@ App::patch('/v1/account/prefs')
|
||||||
App::delete('/v1/account')
|
App::delete('/v1/account')
|
||||||
->desc('Delete Account')
|
->desc('Delete Account')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('webhook', 'account.delete')
|
->label('event', 'account.delete')
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
|
@ -974,10 +978,7 @@ App::delete('/v1/account')
|
||||||
;
|
;
|
||||||
|
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('payload', [
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
'name' => $user->getAttribute('name', ''),
|
|
||||||
'email' => $user->getAttribute('email', ''),
|
|
||||||
])
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!Config::getParam('domainVerification')) {
|
if (!Config::getParam('domainVerification')) {
|
||||||
|
@ -997,7 +998,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||||
->desc('Delete Account Session')
|
->desc('Delete Account Session')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('webhook', 'account.sessions.delete')
|
->label('event', 'account.sessions.delete')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
->label('sdk.method', 'deleteSession')
|
->label('sdk.method', 'deleteSession')
|
||||||
|
@ -1032,10 +1033,7 @@ App::delete('/v1/account/sessions/:sessionId')
|
||||||
;
|
;
|
||||||
|
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('payload', [
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
'name' => $user->getAttribute('name', ''),
|
|
||||||
'email' => $user->getAttribute('email', ''),
|
|
||||||
])
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!Config::getParam('domainVerification')) {
|
if (!Config::getParam('domainVerification')) {
|
||||||
|
@ -1062,7 +1060,7 @@ App::delete('/v1/account/sessions')
|
||||||
->desc('Delete All Account Sessions')
|
->desc('Delete All Account Sessions')
|
||||||
->groups(['api', 'account'])
|
->groups(['api', 'account'])
|
||||||
->label('scope', 'account')
|
->label('scope', 'account')
|
||||||
->label('webhook', 'account.sessions.delete')
|
->label('event', 'account.sessions.delete')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT])
|
||||||
->label('sdk.namespace', 'account')
|
->label('sdk.namespace', 'account')
|
||||||
->label('sdk.method', 'deleteSessions')
|
->label('sdk.method', 'deleteSessions')
|
||||||
|
@ -1089,12 +1087,9 @@ App::delete('/v1/account/sessions')
|
||||||
->setParam('event', 'account.sessions.delete')
|
->setParam('event', 'account.sessions.delete')
|
||||||
->setParam('resource', '/user/'.$user->getId())
|
->setParam('resource', '/user/'.$user->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('payload', [
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
'name' => $user->getAttribute('name', ''),
|
|
||||||
'email' => $user->getAttribute('email', ''),
|
|
||||||
])
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!Config::getParam('domainVerification')) {
|
if (!Config::getParam('domainVerification')) {
|
||||||
|
|
|
@ -2,15 +2,11 @@
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Exception;
|
use Utopia\Exception;
|
||||||
use Utopia\Response;
|
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\JSON;
|
use Utopia\Validator\JSON;
|
||||||
// use Utopia\Locale\Locale;
|
|
||||||
// use Utopia\Audit\Audit;
|
|
||||||
// use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
|
||||||
use Appwrite\Database\Database;
|
use Appwrite\Database\Database;
|
||||||
use Appwrite\Database\Document;
|
use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Validator\UID;
|
use Appwrite\Database\Validator\UID;
|
||||||
|
@ -20,11 +16,12 @@ use Appwrite\Database\Validator\Collection;
|
||||||
use Appwrite\Database\Validator\Authorization;
|
use Appwrite\Database\Validator\Authorization;
|
||||||
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
||||||
use Appwrite\Database\Exception\Structure as StructureException;
|
use Appwrite\Database\Exception\Structure as StructureException;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
|
|
||||||
App::post('/v1/database/collections')
|
App::post('/v1/database/collections')
|
||||||
->desc('Create Collection')
|
->desc('Create Collection')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('webhook', 'database.collections.create')
|
->label('event', 'database.collections.create')
|
||||||
->label('scope', 'collections.write')
|
->label('scope', 'collections.write')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
|
@ -34,10 +31,9 @@ App::post('/v1/database/collections')
|
||||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', false, ['projectDB'])
|
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', false, ['projectDB'])
|
||||||
->action(function ($name, $read, $write, $rules, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($name, $read, $write, $rules, $response, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$parsedRules = [];
|
$parsedRules = [];
|
||||||
|
@ -77,26 +73,15 @@ App::post('/v1/database/collections')
|
||||||
throw new Exception('Failed saving collection to DB', 500);
|
throw new Exception('Failed saving collection to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $data->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $data)
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.collections.create')
|
->setParam('event', 'database.collections.create')
|
||||||
->setParam('resource', 'database/collection/'.$data['$id'])
|
->setParam('resource', 'database/collection/'.$data->getId())
|
||||||
->setParam('data', $data)
|
->setParam('data', $data->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
* View
|
$response->dynamic($data, Response::MODEL_COLLECTION);
|
||||||
*/
|
}, ['response', 'projectDB', 'audits']);
|
||||||
$response
|
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
|
||||||
->json($data)
|
|
||||||
;
|
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
|
||||||
|
|
||||||
App::get('/v1/database/collections')
|
App::get('/v1/database/collections')
|
||||||
->desc('List Collections')
|
->desc('List Collections')
|
||||||
|
@ -126,7 +111,10 @@ App::get('/v1/database/collections')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'collections' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
|
'collections' => $results
|
||||||
|
]), Response::MODEL_COLLECTION_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/database/collections/:collectionId')
|
App::get('/v1/database/collections/:collectionId')
|
||||||
|
@ -148,79 +136,14 @@ App::get('/v1/database/collections/:collectionId')
|
||||||
throw new Exception('Collection not found', 404);
|
throw new Exception('Collection not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($collection->getArrayCopy());
|
$response->dynamic($collection, Response::MODEL_COLLECTION);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
// App::get('/v1/database/collections/:collectionId/logs')
|
|
||||||
// ->desc('Get Collection Logs')
|
|
||||||
// ->groups(['api', 'database'])
|
|
||||||
// ->label('scope', 'collections.read')
|
|
||||||
// ->label('sdk.platform', [APP_PLATFORM_SERVER])
|
|
||||||
// ->label('sdk.namespace', 'database')
|
|
||||||
// ->label('sdk.method', 'getCollectionLogs')
|
|
||||||
// ->label('sdk.description', '/docs/references/database/get-collection-logs.md')
|
|
||||||
// ->param('collectionId', '', new UID(), 'Collection unique ID.')
|
|
||||||
// ->action(
|
|
||||||
// function ($collectionId) use ($response, $register, $projectDB, $project) {
|
|
||||||
// $collection = $projectDB->getDocument($collectionId, false);
|
|
||||||
|
|
||||||
// if (empty($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
|
||||||
// throw new Exception('Collection not found', 404);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $adapter = new AuditAdapter($register->get('db'));
|
|
||||||
// $adapter->setNamespace('app_'.$project->getId());
|
|
||||||
|
|
||||||
// $audit = new Audit($adapter);
|
|
||||||
|
|
||||||
// $countries = Locale::getText('countries');
|
|
||||||
|
|
||||||
// $logs = $audit->getLogsByResource('database/collection/'.$collection->getId());
|
|
||||||
|
|
||||||
// $reader = new Reader(__DIR__.'/../../db/DBIP/dbip-country-lite-2020-01.mmdb');
|
|
||||||
// $output = [];
|
|
||||||
|
|
||||||
// foreach ($logs as $i => &$log) {
|
|
||||||
// $log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
|
|
||||||
|
|
||||||
// $dd = new DeviceDetector($log['userAgent']);
|
|
||||||
|
|
||||||
// $dd->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
|
|
||||||
|
|
||||||
// $dd->parse();
|
|
||||||
|
|
||||||
// $output[$i] = [
|
|
||||||
// 'event' => $log['event'],
|
|
||||||
// 'ip' => $log['ip'],
|
|
||||||
// 'time' => strtotime($log['time']),
|
|
||||||
// 'OS' => $dd->getOs(),
|
|
||||||
// 'client' => $dd->getClient(),
|
|
||||||
// 'device' => $dd->getDevice(),
|
|
||||||
// 'brand' => $dd->getBrand(),
|
|
||||||
// 'model' => $dd->getModel(),
|
|
||||||
// 'geo' => [],
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// $record = $reader->country($log['ip']);
|
|
||||||
// $output[$i]['geo']['isoCode'] = strtolower($record->country->isoCode);
|
|
||||||
// $output[$i]['geo']['country'] = $record->country->name;
|
|
||||||
// $output[$i]['geo']['country'] = (isset($countries[$record->country->isoCode])) ? $countries[$record->country->isoCode] : Locale::getText('locale.country.unknown');
|
|
||||||
// } catch (\Exception $e) {
|
|
||||||
// $output[$i]['geo']['isoCode'] = '--';
|
|
||||||
// $output[$i]['geo']['country'] = Locale::getText('locale.country.unknown');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $response->json($output);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
App::put('/v1/database/collections/:collectionId')
|
App::put('/v1/database/collections/:collectionId')
|
||||||
->desc('Update Collection')
|
->desc('Update Collection')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('scope', 'collections.write')
|
->label('scope', 'collections.write')
|
||||||
->label('webhook', 'database.collections.update')
|
->label('event', 'database.collections.update')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.method', 'updateCollection')
|
->label('sdk.method', 'updateCollection')
|
||||||
|
@ -230,10 +153,9 @@ App::put('/v1/database/collections/:collectionId')
|
||||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.')
|
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions(/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true, ['projectDB'])
|
->param('rules', [], function ($projectDB) { return new ArrayList(new Collection($projectDB, [Database::SYSTEM_COLLECTION_RULES], ['$collection' => Database::SYSTEM_COLLECTION_RULES, '$permissions' => ['read' => [], 'write' => []]])); }, 'Array of [rule objects](/docs/rules). Each rule define a collection field name, data type and validation.', true, ['projectDB'])
|
||||||
->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($collectionId, $name, $read, $write, $rules, $response, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$collection = $projectDB->getDocument($collectionId, false);
|
$collection = $projectDB->getDocument($collectionId, false);
|
||||||
|
@ -277,26 +199,20 @@ App::put('/v1/database/collections/:collectionId')
|
||||||
throw new Exception('Failed saving collection to DB', 500);
|
throw new Exception('Failed saving collection to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $collection->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $data)
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.collections.update')
|
->setParam('event', 'database.collections.update')
|
||||||
->setParam('resource', 'database/collections/'.$data['$id'])
|
->setParam('resource', 'database/collections/'.$collection->getId())
|
||||||
->setParam('data', $data)
|
->setParam('data', $collection->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->json($collection->getArrayCopy());
|
$response->dynamic($collection, Response::MODEL_COLLECTION);
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
}, ['response', 'projectDB', 'audits']);
|
||||||
|
|
||||||
App::delete('/v1/database/collections/:collectionId')
|
App::delete('/v1/database/collections/:collectionId')
|
||||||
->desc('Delete Collection')
|
->desc('Delete Collection')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('scope', 'collections.write')
|
->label('scope', 'collections.write')
|
||||||
->label('webhook', 'database.collections.delete')
|
->label('event', 'database.collections.delete')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.method', 'deleteCollection')
|
->label('sdk.method', 'deleteCollection')
|
||||||
|
@ -318,16 +234,14 @@ App::delete('/v1/database/collections/:collectionId')
|
||||||
throw new Exception('Failed to remove collection from DB', 500);
|
throw new Exception('Failed to remove collection from DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $collection->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('payload', $data)
|
->setParam('payload', $response->output($collection, Response::MODEL_COLLECTION))
|
||||||
;
|
;
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.collections.delete')
|
->setParam('event', 'database.collections.delete')
|
||||||
->setParam('resource', 'database/collections/'.$data['$id'])
|
->setParam('resource', 'database/collections/'.$collection->getId())
|
||||||
->setParam('data', $data)
|
->setParam('data', $collection->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
|
@ -336,7 +250,7 @@ App::delete('/v1/database/collections/:collectionId')
|
||||||
App::post('/v1/database/collections/:collectionId/documents')
|
App::post('/v1/database/collections/:collectionId/documents')
|
||||||
->desc('Create Document')
|
->desc('Create Document')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('webhook', 'database.documents.create')
|
->label('event', 'database.documents.create')
|
||||||
->label('scope', 'documents.write')
|
->label('scope', 'documents.write')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
|
@ -349,10 +263,9 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||||
->param('parentDocument', '', new UID(), 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
|
->param('parentDocument', '', new UID(), 'Parent document unique ID. Use when you want your new document to be a child of a parent document.', true)
|
||||||
->param('parentProperty', '', new Key(), 'Parent document property name. Use when you want your new document to be a child of a parent document.', true)
|
->param('parentProperty', '', new Key(), 'Parent document property name. Use when you want your new document to be a child of a parent document.', true)
|
||||||
->param('parentPropertyType', Document::SET_TYPE_ASSIGN, new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND], true), 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true)
|
->param('parentPropertyType', Document::SET_TYPE_ASSIGN, new WhiteList([Document::SET_TYPE_ASSIGN, Document::SET_TYPE_APPEND, Document::SET_TYPE_PREPEND], true), 'Parent document property connection type. You can set this value to **assign**, **append** or **prepend**, default value is assign. Use when you want your new document to be a child of a parent document.', true)
|
||||||
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($collectionId, $data, $read, $write, $parentDocument, $parentProperty, $parentPropertyType, $response, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||||
|
@ -387,11 +300,11 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Check child has valid structure,
|
* 1. Check child has valid structure,
|
||||||
* 2. Check user have write permission for parent document
|
* 2. Check user have write permission for parent document
|
||||||
* 3. Assign parent data (including child) to $data
|
* 3. Assign parent data (including child) to $data
|
||||||
* 4. Validate the combined result has valid structure (inside $projectDB->createDocument method)
|
* 4. Validate the combined result has valid structure (inside $projectDB->createDocument method)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$new = new Document($data);
|
$new = new Document($data);
|
||||||
|
|
||||||
|
@ -436,26 +349,18 @@ App::post('/v1/database/collections/:collectionId/documents')
|
||||||
throw new Exception('Failed saving document to DB'.$exception->getMessage(), 500);
|
throw new Exception('Failed saving document to DB'.$exception->getMessage(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $data->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $data)
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.documents.create')
|
->setParam('event', 'database.documents.create')
|
||||||
->setParam('resource', 'database/document/'.$data['$id'])
|
->setParam('resource', 'database/document/'.$data['$id'])
|
||||||
->setParam('data', $data)
|
->setParam('data', $data->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
|
||||||
* View
|
|
||||||
*/
|
|
||||||
$response
|
$response
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||||
->json($data)
|
|
||||||
;
|
;
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
|
||||||
|
$response->dynamic($data, Response::MODEL_ANY);
|
||||||
|
}, ['response', 'projectDB', 'audits']);
|
||||||
|
|
||||||
App::get('/v1/database/collections/:collectionId/documents')
|
App::get('/v1/database/collections/:collectionId/documents')
|
||||||
->desc('List Documents')
|
->desc('List Documents')
|
||||||
|
@ -495,27 +400,24 @@ App::get('/v1/database/collections/:collectionId/documents')
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (App::isDevelopment()) {
|
// if (App::isDevelopment()) {
|
||||||
$collection
|
// $collection
|
||||||
->setAttribute('debug', $projectDB->getDebug())
|
// ->setAttribute('debug', $projectDB->getDebug())
|
||||||
->setAttribute('limit', $limit)
|
// ->setAttribute('limit', $limit)
|
||||||
->setAttribute('offset', $offset)
|
// ->setAttribute('offset', $offset)
|
||||||
->setAttribute('orderField', $orderField)
|
// ->setAttribute('orderField', $orderField)
|
||||||
->setAttribute('orderType', $orderType)
|
// ->setAttribute('orderType', $orderType)
|
||||||
->setAttribute('orderCast', $orderCast)
|
// ->setAttribute('orderCast', $orderCast)
|
||||||
->setAttribute('filters', $filters)
|
// ->setAttribute('filters', $filters)
|
||||||
;
|
// ;
|
||||||
}
|
// }
|
||||||
|
|
||||||
$collection
|
$collection
|
||||||
->setAttribute('sum', $projectDB->getSum())
|
->setAttribute('sum', $projectDB->getSum())
|
||||||
->setAttribute('documents', $list)
|
->setAttribute('documents', $list)
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
$response->dynamic($collection, Response::MODEL_DOCUMENT_LIST);
|
||||||
* View
|
|
||||||
*/
|
|
||||||
$response->json($collection->getArrayCopy(/*['$id', '$collection', 'name', 'documents']*/[], ['rules']));
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
|
@ -540,36 +442,13 @@ App::get('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
throw new Exception('No document found', 404);
|
throw new Exception('No document found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = $document->getArrayCopy();
|
$response->dynamic($document, Response::MODEL_ANY);
|
||||||
|
|
||||||
$paths = \explode('/', $request->getParam('q', ''));
|
|
||||||
$paths = \array_slice($paths, 7, \count($paths));
|
|
||||||
|
|
||||||
if (\count($paths) > 0) {
|
|
||||||
if (\count($paths) % 2 == 1) {
|
|
||||||
$output = $document->getAttribute(\implode('.', $paths));
|
|
||||||
} else {
|
|
||||||
$id = (int) \array_pop($paths);
|
|
||||||
$output = $document->search('$id', $id, $document->getAttribute(\implode('.', $paths)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$output = ($output instanceof Document) ? $output->getArrayCopy() : $output;
|
|
||||||
|
|
||||||
if (!\is_array($output)) {
|
|
||||||
throw new Exception('No document found', 404);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* View
|
|
||||||
*/
|
|
||||||
$response->json($output);
|
|
||||||
}, ['request', 'response', 'projectDB']);
|
}, ['request', 'response', 'projectDB']);
|
||||||
|
|
||||||
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->desc('Update Document')
|
->desc('Update Document')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('webhook', 'database.documents.update')
|
->label('event', 'database.documents.update')
|
||||||
->label('scope', 'documents.write')
|
->label('scope', 'documents.write')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
|
@ -580,10 +459,9 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->param('data', [], new JSON(), 'Document data as JSON object.')
|
->param('data', [], new JSON(), 'Document data as JSON object.')
|
||||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($collectionId, $documentId, $data, $read, $write, $response, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$collection = $projectDB->getDocument($collectionId, false);
|
$collection = $projectDB->getDocument($collectionId, false);
|
||||||
|
@ -592,7 +470,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
$data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array
|
||||||
|
|
||||||
if (!\is_array($data)) {
|
if (!\is_array($data)) {
|
||||||
throw new Exception('Data param should be a valid JSON', 400);
|
throw new Exception('Data param should be a valid JSON object', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
if (\is_null($collection->getId()) || Database::SYSTEM_COLLECTION_COLLECTIONS != $collection->getCollection()) {
|
||||||
|
@ -621,6 +499,7 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
throw new Exception('Missing payload', 400);
|
throw new Exception('Missing payload', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $projectDB->updateDocument($data);
|
$data = $projectDB->updateDocument($data);
|
||||||
} catch (AuthorizationException $exception) {
|
} catch (AuthorizationException $exception) {
|
||||||
|
@ -631,29 +510,20 @@ App::patch('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
throw new Exception('Failed saving document to DB', 500);
|
throw new Exception('Failed saving document to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $data->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $data)
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.documents.update')
|
->setParam('event', 'database.documents.update')
|
||||||
->setParam('resource', 'database/document/'.$data['$id'])
|
->setParam('resource', 'database/document/'.$data->getId())
|
||||||
->setParam('data', $data)
|
->setParam('data', $data->getArrayCopy())
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
$response->dynamic($data, Response::MODEL_ANY);
|
||||||
* View
|
}, ['response', 'projectDB', 'audits']);
|
||||||
*/
|
|
||||||
$response->json($data);
|
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
|
||||||
|
|
||||||
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
->desc('Delete Document')
|
->desc('Delete Document')
|
||||||
->groups(['api', 'database'])
|
->groups(['api', 'database'])
|
||||||
->label('scope', 'documents.write')
|
->label('scope', 'documents.write')
|
||||||
->label('webhook', 'database.documents.delete')
|
->label('event', 'database.documents.delete')
|
||||||
->label('sdk.namespace', 'database')
|
->label('sdk.namespace', 'database')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
->label('sdk.method', 'deleteDocument')
|
->label('sdk.method', 'deleteDocument')
|
||||||
|
@ -687,16 +557,14 @@ App::delete('/v1/database/collections/:collectionId/documents/:documentId')
|
||||||
throw new Exception('Failed to remove document from DB', 500);
|
throw new Exception('Failed to remove document from DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $document->getArrayCopy();
|
|
||||||
|
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('payload', $data)
|
->setParam('payload', $response->output($document, Response::MODEL_ANY))
|
||||||
;
|
;
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'database.documents.delete')
|
->setParam('event', 'database.documents.delete')
|
||||||
->setParam('resource', 'database/document/'.$data['$id'])
|
->setParam('resource', 'database/document/'.$document->getId())
|
||||||
->setParam('data', $data) // Audit document in case of malicious or disastrous action
|
->setParam('data', $document->getArrayCopy()) // Audit document in case of malicious or disastrous action
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Appwrite\Database\Database;
|
use Appwrite\Database\Database;
|
||||||
|
use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Validator\UID;
|
use Appwrite\Database\Validator\UID;
|
||||||
use Appwrite\Storage\Storage;
|
use Appwrite\Storage\Storage;
|
||||||
use Appwrite\Storage\Validator\File;
|
use Appwrite\Storage\Validator\File;
|
||||||
use Appwrite\Storage\Validator\FileSize;
|
use Appwrite\Storage\Validator\FileSize;
|
||||||
use Appwrite\Storage\Validator\FileType;
|
use Appwrite\Storage\Validator\FileType;
|
||||||
use Appwrite\Storage\Validator\Upload;
|
use Appwrite\Storage\Validator\Upload;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
use Appwrite\Task\Validator\Cron;
|
use Appwrite\Task\Validator\Cron;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Response;
|
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Assoc;
|
use Utopia\Validator\Assoc;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
|
@ -43,15 +44,15 @@ App::post('/v1/functions')
|
||||||
],
|
],
|
||||||
'dateCreated' => time(),
|
'dateCreated' => time(),
|
||||||
'dateUpdated' => time(),
|
'dateUpdated' => time(),
|
||||||
'status' => 'paused',
|
'status' => 'disabled',
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'env' => $env,
|
'env' => $env,
|
||||||
'tag' => '',
|
'tag' => '',
|
||||||
'vars' => $vars,
|
'vars' => $vars,
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'schedule' => $schedule,
|
'schedule' => $schedule,
|
||||||
'previous' => null,
|
'schedulePrevious' => null,
|
||||||
'next' => null,
|
'scheduleNext' => null,
|
||||||
'timeout' => $timeout,
|
'timeout' => $timeout,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -59,10 +60,8 @@ App::post('/v1/functions')
|
||||||
throw new Exception('Failed saving function to DB', 500);
|
throw new Exception('Failed saving function to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($function, Response::MODEL_FUNCTION);
|
||||||
->json($function->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/functions')
|
App::get('/v1/functions')
|
||||||
|
@ -90,7 +89,10 @@ App::get('/v1/functions')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'functions' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
|
'functions' => $results
|
||||||
|
]), Response::MODEL_FUNCTION_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/functions/:functionId')
|
App::get('/v1/functions/:functionId')
|
||||||
|
@ -106,12 +108,125 @@ App::get('/v1/functions/:functionId')
|
||||||
$function = $projectDB->getDocument($functionId);
|
$function = $projectDB->getDocument($functionId);
|
||||||
|
|
||||||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||||
throw new Exception('function not found', 404);
|
throw new Exception('Function not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($function->getArrayCopy());
|
$response->dynamic($function, Response::MODEL_FUNCTION);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
|
App::get('/v1/functions/:functionId/usage')
|
||||||
|
->desc('Get Function Usage')
|
||||||
|
->groups(['api', 'functions'])
|
||||||
|
->label('scope', 'functions.read')
|
||||||
|
->label('sdk.platform', [APP_PLATFORM_CONSOLE])
|
||||||
|
->label('sdk.namespace', 'functions')
|
||||||
|
->label('sdk.method', 'getUsage')
|
||||||
|
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||||
|
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true)
|
||||||
|
->action(function ($functionId, $range, $response, $project, $projectDB, $register) {
|
||||||
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
|
/** @var Appwrite\Database\Document $project */
|
||||||
|
/** @var Appwrite\Database\Database $consoleDB */
|
||||||
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var Utopia\Registry\Registry $register */
|
||||||
|
|
||||||
|
$function = $projectDB->getDocument($functionId);
|
||||||
|
|
||||||
|
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||||
|
throw new Exception('Function not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$period = [
|
||||||
|
'24h' => [
|
||||||
|
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||||
|
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||||
|
'group' => '30m',
|
||||||
|
],
|
||||||
|
'7d' => [
|
||||||
|
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||||
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
|
'group' => '1d',
|
||||||
|
],
|
||||||
|
'30d' => [
|
||||||
|
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||||
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
|
'group' => '1d',
|
||||||
|
],
|
||||||
|
'90d' => [
|
||||||
|
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||||
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
|
'group' => '1d',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$client = $register->get('influxdb');
|
||||||
|
|
||||||
|
$executions = [];
|
||||||
|
$failures = [];
|
||||||
|
$compute = [];
|
||||||
|
|
||||||
|
if ($client) {
|
||||||
|
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||||
|
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||||
|
$database = $client->selectDB('telegraf');
|
||||||
|
|
||||||
|
// Executions
|
||||||
|
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||||
|
$points = $result->getPoints();
|
||||||
|
|
||||||
|
foreach ($points as $point) {
|
||||||
|
$executions[] = [
|
||||||
|
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||||
|
'date' => \strtotime($point['time']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failures
|
||||||
|
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' AND "functionStatus"=\'failed\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||||
|
$points = $result->getPoints();
|
||||||
|
|
||||||
|
foreach ($points as $point) {
|
||||||
|
$failures[] = [
|
||||||
|
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||||
|
'date' => \strtotime($point['time']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute
|
||||||
|
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_executions_time" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' AND "functionId"=\''.$function->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||||
|
$points = $result->getPoints();
|
||||||
|
|
||||||
|
foreach ($points as $point) {
|
||||||
|
$compute[] = [
|
||||||
|
'value' => round((!empty($point['value'])) ? $point['value'] / 1000 : 0, 2), // minutes
|
||||||
|
'date' => \strtotime($point['time']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->json([
|
||||||
|
'range' => $range,
|
||||||
|
'executions' => [
|
||||||
|
'data' => $executions,
|
||||||
|
'total' => \array_sum(\array_map(function ($item) {
|
||||||
|
return $item['value'];
|
||||||
|
}, $executions)),
|
||||||
|
],
|
||||||
|
'failures' => [
|
||||||
|
'data' => $failures,
|
||||||
|
'total' => \array_sum(\array_map(function ($item) {
|
||||||
|
return $item['value'];
|
||||||
|
}, $failures)),
|
||||||
|
],
|
||||||
|
'compute' => [
|
||||||
|
'data' => $compute,
|
||||||
|
'total' => \array_sum(\array_map(function ($item) {
|
||||||
|
return $item['value'];
|
||||||
|
}, $compute)),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}, ['response', 'project', 'projectDB', 'register']);
|
||||||
|
|
||||||
App::put('/v1/functions/:functionId')
|
App::put('/v1/functions/:functionId')
|
||||||
->groups(['api', 'functions'])
|
->groups(['api', 'functions'])
|
||||||
->desc('Update Function')
|
->desc('Update Function')
|
||||||
|
@ -142,16 +257,29 @@ App::put('/v1/functions/:functionId')
|
||||||
'vars' => $vars,
|
'vars' => $vars,
|
||||||
'events' => $events,
|
'events' => $events,
|
||||||
'schedule' => $schedule,
|
'schedule' => $schedule,
|
||||||
'previous' => null,
|
'schedulePrevious' => null,
|
||||||
'next' => $next,
|
'scheduleNext' => $next,
|
||||||
'timeout' => $timeout,
|
'timeout' => $timeout,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
if ($next) {
|
||||||
|
ResqueScheduler::enqueueAt($next, 'v1-functions', 'FunctionsV1', [
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ->setParam('projectId', $project->getId())
|
||||||
|
// ->setParam('event', $route->getLabel('event', ''))
|
||||||
|
// ->setParam('payload', [])
|
||||||
|
// ->setParam('functionId', null)
|
||||||
|
// ->setParam('executionId', null)
|
||||||
|
// ->setParam('trigger', 'event')
|
||||||
|
}
|
||||||
|
|
||||||
if (false === $function) {
|
if (false === $function) {
|
||||||
throw new Exception('Failed saving function to DB', 500);
|
throw new Exception('Failed saving function to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($function->getArrayCopy());
|
$response->dynamic($function, Response::MODEL_FUNCTION);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::patch('/v1/functions/:functionId/tag')
|
App::patch('/v1/functions/:functionId/tag')
|
||||||
|
@ -182,14 +310,14 @@ App::patch('/v1/functions/:functionId/tag')
|
||||||
|
|
||||||
$function = $projectDB->updateDocument(array_merge($function->getArrayCopy(), [
|
$function = $projectDB->updateDocument(array_merge($function->getArrayCopy(), [
|
||||||
'tag' => $tag->getId(),
|
'tag' => $tag->getId(),
|
||||||
'next' => $next,
|
'scheduleNext' => $next,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
if (false === $function) {
|
if (false === $function) {
|
||||||
throw new Exception('Failed saving function to DB', 500);
|
throw new Exception('Failed saving function to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($function->getArrayCopy());
|
$response->dynamic($function, Response::MODEL_FUNCTION);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::delete('/v1/functions/:functionId')
|
App::delete('/v1/functions/:functionId')
|
||||||
|
@ -201,7 +329,11 @@ App::delete('/v1/functions/:functionId')
|
||||||
->label('sdk.method', 'delete')
|
->label('sdk.method', 'delete')
|
||||||
->label('sdk.description', '/docs/references/functions/delete-function.md')
|
->label('sdk.description', '/docs/references/functions/delete-function.md')
|
||||||
->param('functionId', '', new UID(), 'Function unique ID.')
|
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||||
->action(function ($functionId, $response, $projectDB) {
|
->action(function ($functionId, $response, $projectDB, $deletes) {
|
||||||
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var Appwrite\Event\Event $deletes */
|
||||||
|
|
||||||
$function = $projectDB->getDocument($functionId);
|
$function = $projectDB->getDocument($functionId);
|
||||||
|
|
||||||
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
if (empty($function->getId()) || Database::SYSTEM_COLLECTION_FUNCTIONS != $function->getCollection()) {
|
||||||
|
@ -212,8 +344,12 @@ App::delete('/v1/functions/:functionId')
|
||||||
throw new Exception('Failed to remove function from DB', 500);
|
throw new Exception('Failed to remove function from DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$deletes
|
||||||
|
->setParam('document', $function->getArrayCopy())
|
||||||
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB', 'deletes']);
|
||||||
|
|
||||||
App::post('/v1/functions/:functionId/tags')
|
App::post('/v1/functions/:functionId/tags')
|
||||||
->groups(['api', 'functions'])
|
->groups(['api', 'functions'])
|
||||||
|
@ -276,11 +412,11 @@ App::post('/v1/functions/:functionId/tags')
|
||||||
'read' => [],
|
'read' => [],
|
||||||
'write' => [],
|
'write' => [],
|
||||||
],
|
],
|
||||||
'dateCreated' => time(),
|
|
||||||
'functionId' => $function->getId(),
|
'functionId' => $function->getId(),
|
||||||
|
'dateCreated' => time(),
|
||||||
'command' => $command,
|
'command' => $command,
|
||||||
'codePath' => $path,
|
'path' => $path,
|
||||||
'codeSize' => $size,
|
'size' => $size,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (false === $tag) {
|
if (false === $tag) {
|
||||||
|
@ -288,13 +424,11 @@ App::post('/v1/functions/:functionId/tags')
|
||||||
}
|
}
|
||||||
|
|
||||||
$usage
|
$usage
|
||||||
->setParam('storage', $tag->getAttribute('codeSize', 0))
|
->setParam('storage', $tag->getAttribute('size', 0))
|
||||||
;
|
;
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($tag, Response::MODEL_TAG);
|
||||||
->json($tag->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['request', 'response', 'projectDB', 'usage']);
|
}, ['request', 'response', 'projectDB', 'usage']);
|
||||||
|
|
||||||
App::get('/v1/functions/:functionId/tags')
|
App::get('/v1/functions/:functionId/tags')
|
||||||
|
@ -330,7 +464,10 @@ App::get('/v1/functions/:functionId/tags')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'tags' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
|
'tags' => $results
|
||||||
|
]), Response::MODEL_TAG_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/functions/:functionId/tags/:tagId')
|
App::get('/v1/functions/:functionId/tags/:tagId')
|
||||||
|
@ -360,7 +497,7 @@ App::get('/v1/functions/:functionId/tags/:tagId')
|
||||||
throw new Exception('Tag not found', 404);
|
throw new Exception('Tag not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($tag->getArrayCopy());
|
$response->dynamic($tag, Response::MODEL_TAG);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::delete('/v1/functions/:functionId/tags/:tagId')
|
App::delete('/v1/functions/:functionId/tags/:tagId')
|
||||||
|
@ -392,14 +529,24 @@ App::delete('/v1/functions/:functionId/tags/:tagId')
|
||||||
|
|
||||||
$device = Storage::getDevice('functions');
|
$device = Storage::getDevice('functions');
|
||||||
|
|
||||||
if ($device->delete($tag->getAttribute('codePath', ''))) {
|
if ($device->delete($tag->getAttribute('path', ''))) {
|
||||||
if (!$projectDB->deleteDocument($tag->getId())) {
|
if (!$projectDB->deleteDocument($tag->getId())) {
|
||||||
throw new Exception('Failed to remove tag from DB', 500);
|
throw new Exception('Failed to remove tag from DB', 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($function->getAttribute('tag') === $tag->getId()) { // Reset function tag
|
||||||
|
$function = $projectDB->updateDocument(array_merge($function->getArrayCopy(), [
|
||||||
|
'tag' => '',
|
||||||
|
]));
|
||||||
|
|
||||||
|
if (false === $function) {
|
||||||
|
throw new Exception('Failed saving function to DB', 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$usage
|
$usage
|
||||||
->setParam('storage', $tag->getAttribute('codeSize', 0) * -1)
|
->setParam('storage', $tag->getAttribute('size', 0) * -1)
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
|
@ -414,8 +561,8 @@ App::post('/v1/functions/:functionId/executions')
|
||||||
->label('sdk.method', 'createExecution')
|
->label('sdk.method', 'createExecution')
|
||||||
->label('sdk.description', '/docs/references/functions/create-execution.md')
|
->label('sdk.description', '/docs/references/functions/create-execution.md')
|
||||||
->param('functionId', '', new UID(), 'Function unique ID.')
|
->param('functionId', '', new UID(), 'Function unique ID.')
|
||||||
->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
|
// ->param('async', 1, new Range(0, 1), 'Execute code asynchronously. Pass 1 for true, 0 for false. Default value is 1.', true)
|
||||||
->action(function ($functionId, $async, $response, $project, $projectDB) {
|
->action(function ($functionId, /*$async,*/ $response, $project, $projectDB) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $project */
|
/** @var Appwrite\Database\Document $project */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
@ -444,6 +591,7 @@ App::post('/v1/functions/:functionId/executions')
|
||||||
],
|
],
|
||||||
'dateCreated' => time(),
|
'dateCreated' => time(),
|
||||||
'functionId' => $function->getId(),
|
'functionId' => $function->getId(),
|
||||||
|
'trigger' => 'http', // http / schedule / event
|
||||||
'status' => 'waiting', // waiting / processing / completed / failed
|
'status' => 'waiting', // waiting / processing / completed / failed
|
||||||
'exitCode' => 0,
|
'exitCode' => 0,
|
||||||
'stdout' => '',
|
'stdout' => '',
|
||||||
|
@ -454,22 +602,17 @@ App::post('/v1/functions/:functionId/executions')
|
||||||
if (false === $execution) {
|
if (false === $execution) {
|
||||||
throw new Exception('Failed saving execution to DB', 500);
|
throw new Exception('Failed saving execution to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bool)$async) {
|
// Issue a TLS certificate when domain is verified
|
||||||
// Issue a TLS certificate when domain is verified
|
Resque::enqueue('v1-functions', 'FunctionsV1', [
|
||||||
Resque::enqueue('v1-functions', 'FunctionsV1', [
|
'projectId' => $project->getId(),
|
||||||
'projectId' => $project->getId(),
|
'functionId' => $function->getId(),
|
||||||
'functionId' => $function->getId(),
|
'executionId' => $execution->getId(),
|
||||||
'executionId' => $execution->getId(),
|
'trigger' => 'http',
|
||||||
'functionTag' => $tag->getId(),
|
]);
|
||||||
'functionTrigger' => 'API',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($execution, Response::MODEL_EXECUTION);
|
||||||
->json($execution->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'project', 'projectDB']);
|
}, ['response', 'project', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/functions/:functionId/executions')
|
App::get('/v1/functions/:functionId/executions')
|
||||||
|
@ -505,7 +648,10 @@ App::get('/v1/functions/:functionId/executions')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'executions' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
|
'executions' => $results
|
||||||
|
]), Response::MODEL_EXECUTION_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/functions/:functionId/executions/:executionId')
|
App::get('/v1/functions/:functionId/executions/:executionId')
|
||||||
|
@ -535,5 +681,5 @@ App::get('/v1/functions/:functionId/executions/:executionId')
|
||||||
throw new Exception('Execution not found', 404);
|
throw new Exception('Execution not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($execution->getArrayCopy());
|
$response->dynamic($execution, Response::MODEL_EXECUTION);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Appwrite\Database\Document;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ App::get('/v1/locale')
|
||||||
$time = (60 * 60 * 24 * 45); // 45 days cache
|
$time = (60 * 60 * 24 * 45); // 45 days cache
|
||||||
$countries = $locale->getText('countries');
|
$countries = $locale->getText('countries');
|
||||||
$continents = $locale->getText('continents');
|
$continents = $locale->getText('continents');
|
||||||
|
|
||||||
$output['ip'] = $ip;
|
$output['ip'] = $ip;
|
||||||
|
|
||||||
$currency = null;
|
$currency = null;
|
||||||
|
@ -57,7 +59,8 @@ App::get('/v1/locale')
|
||||||
$response
|
$response
|
||||||
->addHeader('Cache-Control', 'public, max-age='.$time)
|
->addHeader('Cache-Control', 'public, max-age='.$time)
|
||||||
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache
|
->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache
|
||||||
->json($output);
|
;
|
||||||
|
$response->dynamic(new Document($output), Response::MODEL_LOCALE);
|
||||||
}, ['request', 'response', 'locale', 'geodb']);
|
}, ['request', 'response', 'locale', 'geodb']);
|
||||||
|
|
||||||
App::get('/v1/locale/countries')
|
App::get('/v1/locale/countries')
|
||||||
|
@ -73,10 +76,18 @@ App::get('/v1/locale/countries')
|
||||||
/** @var Utopia\Locale\Locale $locale */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
|
|
||||||
$list = $locale->getText('countries'); /* @var $list array */
|
$list = $locale->getText('countries'); /* @var $list array */
|
||||||
|
$output = [];
|
||||||
|
|
||||||
\asort($list);
|
\asort($list); // sort by abc per locale
|
||||||
|
|
||||||
$response->json($list);
|
foreach ($list as $key => $value) {
|
||||||
|
$output[] = new Document([
|
||||||
|
'name' => $value,
|
||||||
|
'code' => $key,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->dynamic(new Document(['countries' => $output, 'sum' => \count($output)]), Response::MODEL_COUNTRY_LIST);
|
||||||
}, ['response', 'locale']);
|
}, ['response', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/locale/countries/eu')
|
App::get('/v1/locale/countries/eu')
|
||||||
|
@ -91,19 +102,22 @@ App::get('/v1/locale/countries/eu')
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Utopia\Locale\Locale $locale */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
|
|
||||||
$countries = $locale->getText('countries'); /* @var $countries array */
|
$list = $locale->getText('countries'); /* @var $countries array */
|
||||||
$eu = Config::getParam('locale-eu');
|
$eu = Config::getParam('locale-eu');
|
||||||
$list = [];
|
$output = [];
|
||||||
|
|
||||||
foreach ($eu as $code) {
|
|
||||||
if (\array_key_exists($code, $countries)) {
|
|
||||||
$list[$code] = $countries[$code];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
\asort($list);
|
\asort($list);
|
||||||
|
|
||||||
$response->json($list);
|
foreach ($eu as $code) {
|
||||||
|
if (\array_key_exists($code, $list)) {
|
||||||
|
$output[] = new Document([
|
||||||
|
'name' => $list[$code],
|
||||||
|
'code' => $code,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->dynamic(new Document(['countries' => $output, 'sum' => \count($output)]), Response::MODEL_COUNTRY_LIST);
|
||||||
}, ['response', 'locale']);
|
}, ['response', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/locale/countries/phones')
|
App::get('/v1/locale/countries/phones')
|
||||||
|
@ -119,18 +133,22 @@ App::get('/v1/locale/countries/phones')
|
||||||
/** @var Utopia\Locale\Locale $locale */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
|
|
||||||
$list = Config::getParam('locale-phones'); /* @var $list array */
|
$list = Config::getParam('locale-phones'); /* @var $list array */
|
||||||
|
|
||||||
$countries = $locale->getText('countries'); /* @var $countries array */
|
$countries = $locale->getText('countries'); /* @var $countries array */
|
||||||
|
$output = [];
|
||||||
|
|
||||||
|
\asort($list);
|
||||||
|
|
||||||
foreach ($list as $code => $name) {
|
foreach ($list as $code => $name) {
|
||||||
if (\array_key_exists($code, $countries)) {
|
if (\array_key_exists($code, $countries)) {
|
||||||
$list[$code] = '+'.$list[$code];
|
$output[] = new Document([
|
||||||
|
'code' => '+'.$list[$code],
|
||||||
|
'countryCode' => $code,
|
||||||
|
'countryName' => $countries[$code],
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
\asort($list);
|
$response->dynamic(new Document(['phones' => $output, 'sum' => \count($output)]), Response::MODEL_PHONE_LIST);
|
||||||
|
|
||||||
$response->json($list);
|
|
||||||
}, ['response', 'locale']);
|
}, ['response', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/locale/continents')
|
App::get('/v1/locale/continents')
|
||||||
|
@ -148,8 +166,15 @@ App::get('/v1/locale/continents')
|
||||||
$list = $locale->getText('continents'); /* @var $list array */
|
$list = $locale->getText('continents'); /* @var $list array */
|
||||||
|
|
||||||
\asort($list);
|
\asort($list);
|
||||||
|
|
||||||
|
foreach ($list as $key => $value) {
|
||||||
|
$output[] = new Document([
|
||||||
|
'name' => $value,
|
||||||
|
'code' => $key,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$response->json($list);
|
$response->dynamic(new Document(['continents' => $output, 'sum' => \count($output)]), Response::MODEL_CONTINENT_LIST);
|
||||||
}, ['response', 'locale']);
|
}, ['response', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/locale/currencies')
|
App::get('/v1/locale/currencies')
|
||||||
|
@ -163,9 +188,13 @@ App::get('/v1/locale/currencies')
|
||||||
->action(function ($response) {
|
->action(function ($response) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
|
|
||||||
$currencies = Config::getParam('locale-currencies');
|
$list = Config::getParam('locale-currencies');
|
||||||
|
|
||||||
$response->json($currencies);
|
$list = array_map(function($node) {
|
||||||
|
return new Document($node);
|
||||||
|
}, $list);
|
||||||
|
|
||||||
|
$response->dynamic(new Document(['currencies' => $list, 'sum' => \count($list)]), Response::MODEL_CURRENCY_LIST);
|
||||||
}, ['response']);
|
}, ['response']);
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,7 +209,11 @@ App::get('/v1/locale/languages')
|
||||||
->action(function ($response) {
|
->action(function ($response) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
|
|
||||||
$languages = Config::getParam('locale-languages');
|
$list = Config::getParam('locale-languages');
|
||||||
|
|
||||||
$response->json($languages);
|
$list = array_map(function($node) {
|
||||||
|
return new Document($node);
|
||||||
|
}, $list);
|
||||||
|
|
||||||
|
$response->dynamic(new Document(['languages' => $list, 'sum' => \count($list)]), Response::MODEL_LANGUAGE_LIST);
|
||||||
}, ['response']);
|
}, ['response']);
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Exception;
|
use Utopia\Exception;
|
||||||
use Utopia\Response;
|
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\Boolean;
|
use Utopia\Validator\Boolean;
|
||||||
use Utopia\Validator\Text;
|
use Utopia\Validator\Text;
|
||||||
|
@ -18,6 +17,7 @@ use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Validator\UID;
|
use Appwrite\Database\Validator\UID;
|
||||||
use Appwrite\Network\Validator\CNAME;
|
use Appwrite\Network\Validator\CNAME;
|
||||||
use Appwrite\Network\Validator\Domain as DomainValidator;
|
use Appwrite\Network\Validator\Domain as DomainValidator;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
use Cron\CronExpression;
|
use Cron\CronExpression;
|
||||||
|
|
||||||
App::post('/v1/projects')
|
App::post('/v1/projects')
|
||||||
|
@ -70,6 +70,7 @@ App::post('/v1/projects')
|
||||||
'webhooks' => [],
|
'webhooks' => [],
|
||||||
'keys' => [],
|
'keys' => [],
|
||||||
'tasks' => [],
|
'tasks' => [],
|
||||||
|
'domains' => [],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -79,10 +80,8 @@ App::post('/v1/projects')
|
||||||
|
|
||||||
$consoleDB->createNamespace($project->getId());
|
$consoleDB->createNamespace($project->getId());
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||||
->json($project->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB', 'projectDB']);
|
}, ['response', 'consoleDB', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/projects')
|
App::get('/v1/projects')
|
||||||
|
@ -111,7 +110,10 @@ App::get('/v1/projects')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $consoleDB->getSum(), 'projects' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $consoleDB->getSum(),
|
||||||
|
'projects' => $results
|
||||||
|
]), Response::MODEL_PROJECT_LIST);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId')
|
App::get('/v1/projects/:projectId')
|
||||||
|
@ -131,7 +133,7 @@ App::get('/v1/projects/:projectId')
|
||||||
throw new Exception('Project not found', 404);
|
throw new Exception('Project not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($project->getArrayCopy());
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/usage')
|
App::get('/v1/projects/:projectId/usage')
|
||||||
|
@ -141,7 +143,7 @@ App::get('/v1/projects/:projectId/usage')
|
||||||
->label('sdk.namespace', 'projects')
|
->label('sdk.namespace', 'projects')
|
||||||
->label('sdk.method', 'getUsage')
|
->label('sdk.method', 'getUsage')
|
||||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||||
->param('range', 'last30', new WhiteList(['daily', 'monthly', 'last30', 'last90'], true), 'Date range.', true)
|
->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), 'Date range.', true)
|
||||||
->action(function ($projectId, $range, $response, $consoleDB, $projectDB, $register) {
|
->action(function ($projectId, $range, $response, $consoleDB, $projectDB, $register) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $consoleDB */
|
/** @var Appwrite\Database\Database $consoleDB */
|
||||||
|
@ -155,31 +157,26 @@ App::get('/v1/projects/:projectId/usage')
|
||||||
}
|
}
|
||||||
|
|
||||||
$period = [
|
$period = [
|
||||||
'daily' => [
|
'24h' => [
|
||||||
'start' => DateTime::createFromFormat('U', \strtotime('today')),
|
'start' => DateTime::createFromFormat('U', \strtotime('-24 hours')),
|
||||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
'end' => DateTime::createFromFormat('U', \strtotime('+1 hour')),
|
||||||
'group' => '1m',
|
'group' => '30m',
|
||||||
],
|
],
|
||||||
'monthly' => [
|
'7d' => [
|
||||||
'start' => DateTime::createFromFormat('U', \strtotime('midnight first day of this month')),
|
'start' => DateTime::createFromFormat('U', \strtotime('-7 days')),
|
||||||
'end' => DateTime::createFromFormat('U', \strtotime('midnight last day of this month')),
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
'group' => '1d',
|
'group' => '1d',
|
||||||
],
|
],
|
||||||
'last30' => [
|
'30d' => [
|
||||||
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
'start' => DateTime::createFromFormat('U', \strtotime('-30 days')),
|
||||||
'end' => DateTime::createFromFormat('U', \strtotime('tomorrow')),
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
'group' => '1d',
|
'group' => '1d',
|
||||||
],
|
],
|
||||||
'last90' => [
|
'90d' => [
|
||||||
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
'start' => DateTime::createFromFormat('U', \strtotime('-90 days')),
|
||||||
'end' => DateTime::createFromFormat('U', \strtotime('today')),
|
'end' => DateTime::createFromFormat('U', \strtotime('now')),
|
||||||
'group' => '1d',
|
'group' => '1d',
|
||||||
],
|
],
|
||||||
// 'yearly' => [
|
|
||||||
// 'start' => DateTime::createFromFormat('U', strtotime('midnight first day of january')),
|
|
||||||
// 'end' => DateTime::createFromFormat('U', strtotime('midnight last day of december')),
|
|
||||||
// 'group' => '4w',
|
|
||||||
// ],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$client = $register->get('influxdb');
|
$client = $register->get('influxdb');
|
||||||
|
@ -257,6 +254,7 @@ App::get('/v1/projects/:projectId/usage')
|
||||||
$tasksTotal = \count($project->getAttribute('tasks', []));
|
$tasksTotal = \count($project->getAttribute('tasks', []));
|
||||||
|
|
||||||
$response->json([
|
$response->json([
|
||||||
|
'range' => $range,
|
||||||
'requests' => [
|
'requests' => [
|
||||||
'data' => $requests,
|
'data' => $requests,
|
||||||
'total' => \array_sum(\array_map(function ($item) {
|
'total' => \array_sum(\array_map(function ($item) {
|
||||||
|
@ -298,7 +296,7 @@ App::get('/v1/projects/:projectId/usage')
|
||||||
) +
|
) +
|
||||||
$projectDB->getCount(
|
$projectDB->getCount(
|
||||||
[
|
[
|
||||||
'attribute' => 'codeSize',
|
'attribute' => 'size',
|
||||||
'filters' => [
|
'filters' => [
|
||||||
'$collection='.Database::SYSTEM_COLLECTION_TAGS,
|
'$collection='.Database::SYSTEM_COLLECTION_TAGS,
|
||||||
],
|
],
|
||||||
|
@ -352,7 +350,7 @@ App::patch('/v1/projects/:projectId')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($project->getArrayCopy());
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::patch('/v1/projects/:projectId/oauth2')
|
App::patch('/v1/projects/:projectId/oauth2')
|
||||||
|
@ -384,7 +382,7 @@ App::patch('/v1/projects/:projectId/oauth2')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($project->getArrayCopy());
|
$response->dynamic($project, Response::MODEL_PROJECT);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId')
|
App::delete('/v1/projects/:projectId')
|
||||||
|
@ -487,10 +485,8 @@ App::post('/v1/projects/:projectId/webhooks')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||||
->json($webhook->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/webhooks')
|
App::get('/v1/projects/:projectId/webhooks')
|
||||||
|
@ -512,7 +508,10 @@ App::get('/v1/projects/:projectId/webhooks')
|
||||||
|
|
||||||
$webhooks = $project->getAttribute('webhooks', []);
|
$webhooks = $project->getAttribute('webhooks', []);
|
||||||
|
|
||||||
$response->json($webhooks);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => count($webhooks),
|
||||||
|
'webhooks' => $webhooks
|
||||||
|
]), Response::MODEL_WEBHOOK_LIST);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
||||||
|
@ -539,7 +538,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId')
|
||||||
throw new Exception('Webhook not found', 404);
|
throw new Exception('Webhook not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($webhook->getArrayCopy());
|
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
||||||
|
@ -587,7 +586,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
||||||
throw new Exception('Failed saving webhook to DB', 500);
|
throw new Exception('Failed saving webhook to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($webhook->getArrayCopy());
|
$response->dynamic($webhook, Response::MODEL_WEBHOOK);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
||||||
|
@ -665,10 +664,8 @@ App::post('/v1/projects/:projectId/keys')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($key, Response::MODEL_KEY);
|
||||||
->json($key->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/keys')
|
App::get('/v1/projects/:projectId/keys')
|
||||||
|
@ -688,7 +685,12 @@ App::get('/v1/projects/:projectId/keys')
|
||||||
throw new Exception('Project not found', 404);
|
throw new Exception('Project not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($project->getAttribute('keys', [])); //FIXME make sure array objects return correctly
|
$keys = $project->getAttribute('keys', []);
|
||||||
|
|
||||||
|
$response->dynamic(new Document([
|
||||||
|
'sum' => count($keys),
|
||||||
|
'keys' => $keys
|
||||||
|
]), Response::MODEL_KEY_LIST);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/keys/:keyId')
|
App::get('/v1/projects/:projectId/keys/:keyId')
|
||||||
|
@ -712,7 +714,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
||||||
throw new Exception('Key not found', 404);
|
throw new Exception('Key not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($key->getArrayCopy());
|
$response->dynamic($key, Response::MODEL_KEY);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::put('/v1/projects/:projectId/keys/:keyId')
|
App::put('/v1/projects/:projectId/keys/:keyId')
|
||||||
|
@ -750,7 +752,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
||||||
throw new Exception('Failed saving key to DB', 500);
|
throw new Exception('Failed saving key to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($key->getArrayCopy());
|
$response->dynamic($key, Response::MODEL_KEY);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId/keys/:keyId')
|
App::delete('/v1/projects/:projectId/keys/:keyId')
|
||||||
|
@ -855,10 +857,8 @@ App::post('/v1/projects/:projectId/tasks')
|
||||||
ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy());
|
ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy());
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($task, Response::MODEL_TASK);
|
||||||
->json($task->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/tasks')
|
App::get('/v1/projects/:projectId/tasks')
|
||||||
|
@ -880,7 +880,11 @@ App::get('/v1/projects/:projectId/tasks')
|
||||||
|
|
||||||
$tasks = $project->getAttribute('tasks', []);
|
$tasks = $project->getAttribute('tasks', []);
|
||||||
|
|
||||||
$response->json($tasks);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => count($tasks),
|
||||||
|
'tasks' => $tasks
|
||||||
|
]), Response::MODEL_TASK_LIST);
|
||||||
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/tasks/:taskId')
|
App::get('/v1/projects/:projectId/tasks/:taskId')
|
||||||
|
@ -907,7 +911,7 @@ App::get('/v1/projects/:projectId/tasks/:taskId')
|
||||||
throw new Exception('Task not found', 404);
|
throw new Exception('Task not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($task->getArrayCopy());
|
$response->dynamic($task, Response::MODEL_TASK);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::put('/v1/projects/:projectId/tasks/:taskId')
|
App::put('/v1/projects/:projectId/tasks/:taskId')
|
||||||
|
@ -970,7 +974,7 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
|
||||||
ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy());
|
ResqueScheduler::enqueueAt($next, 'v1-tasks', 'TasksV1', $task->getArrayCopy());
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($task->getArrayCopy());
|
$response->dynamic($task, Response::MODEL_TASK);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId/tasks/:taskId')
|
App::delete('/v1/projects/:projectId/tasks/:taskId')
|
||||||
|
@ -1055,10 +1059,8 @@ App::post('/v1/projects/:projectId/platforms')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($platform, Response::MODEL_PLATFORM);
|
||||||
->json($platform->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/platforms')
|
App::get('/v1/projects/:projectId/platforms')
|
||||||
|
@ -1080,7 +1082,10 @@ App::get('/v1/projects/:projectId/platforms')
|
||||||
|
|
||||||
$platforms = $project->getAttribute('platforms', []);
|
$platforms = $project->getAttribute('platforms', []);
|
||||||
|
|
||||||
$response->json($platforms);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => count($platforms),
|
||||||
|
'platforms' => $platforms
|
||||||
|
]), Response::MODEL_PLATFORM_LIST);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/platforms/:platformId')
|
App::get('/v1/projects/:projectId/platforms/:platformId')
|
||||||
|
@ -1107,7 +1112,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
||||||
throw new Exception('Platform not found', 404);
|
throw new Exception('Platform not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($platform->getArrayCopy());
|
$response->dynamic($platform, Response::MODEL_PLATFORM);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::put('/v1/projects/:projectId/platforms/:platformId')
|
App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||||
|
@ -1150,7 +1155,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||||
throw new Exception('Failed saving platform to DB', 500);
|
throw new Exception('Failed saving platform to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($platform->getArrayCopy());
|
$response->dynamic($platform, Response::MODEL_PLATFORM);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId/platforms/:platformId')
|
App::delete('/v1/projects/:projectId/platforms/:platformId')
|
||||||
|
@ -1244,10 +1249,8 @@ App::post('/v1/projects/:projectId/domains')
|
||||||
throw new Exception('Failed saving project to DB', 500);
|
throw new Exception('Failed saving project to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($domain, Response::MODEL_DOMAIN);
|
||||||
->json($domain->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/domains')
|
App::get('/v1/projects/:projectId/domains')
|
||||||
|
@ -1268,8 +1271,11 @@ App::get('/v1/projects/:projectId/domains')
|
||||||
}
|
}
|
||||||
|
|
||||||
$domains = $project->getAttribute('domains', []);
|
$domains = $project->getAttribute('domains', []);
|
||||||
|
|
||||||
$response->json($domains);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => count($domains),
|
||||||
|
'domains' => $domains
|
||||||
|
]), Response::MODEL_DOMAIN_LIST);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::get('/v1/projects/:projectId/domains/:domainId')
|
App::get('/v1/projects/:projectId/domains/:domainId')
|
||||||
|
@ -1296,7 +1302,7 @@ App::get('/v1/projects/:projectId/domains/:domainId')
|
||||||
throw new Exception('Domain not found', 404);
|
throw new Exception('Domain not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($domain->getArrayCopy());
|
$response->dynamic($domain, Response::MODEL_DOMAIN);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
||||||
|
@ -1330,7 +1336,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($domain->getAttribute('verification') === true) {
|
if ($domain->getAttribute('verification') === true) {
|
||||||
return $response->json($domain->getArrayCopy());
|
return $response->dynamic($domain, Response::MODEL_DOMAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify Domain with DNS records
|
// Verify Domain with DNS records
|
||||||
|
@ -1354,7 +1360,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
||||||
'domain' => $domain->getAttribute('domain'),
|
'domain' => $domain->getAttribute('domain'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json($domain->getArrayCopy());
|
$response->dynamic($domain, Response::MODEL_DOMAIN);
|
||||||
}, ['response', 'consoleDB']);
|
}, ['response', 'consoleDB']);
|
||||||
|
|
||||||
App::delete('/v1/projects/:projectId/domains/:domainId')
|
App::delete('/v1/projects/:projectId/domains/:domainId')
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use Utopia\App;
|
use Utopia\App;
|
||||||
use Utopia\Exception;
|
use Utopia\Exception;
|
||||||
use Utopia\Response;
|
|
||||||
use Utopia\Validator\ArrayList;
|
use Utopia\Validator\ArrayList;
|
||||||
use Utopia\Validator\WhiteList;
|
use Utopia\Validator\WhiteList;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
|
@ -12,6 +11,7 @@ use Utopia\Cache\Cache;
|
||||||
use Utopia\Cache\Adapter\Filesystem;
|
use Utopia\Cache\Adapter\Filesystem;
|
||||||
use Appwrite\ClamAV\Network;
|
use Appwrite\ClamAV\Network;
|
||||||
use Appwrite\Database\Database;
|
use Appwrite\Database\Database;
|
||||||
|
use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Validator\UID;
|
use Appwrite\Database\Validator\UID;
|
||||||
use Appwrite\Storage\Storage;
|
use Appwrite\Storage\Storage;
|
||||||
use Appwrite\Storage\Validator\File;
|
use Appwrite\Storage\Validator\File;
|
||||||
|
@ -20,13 +20,14 @@ use Appwrite\Storage\Validator\Upload;
|
||||||
use Appwrite\Storage\Compression\Algorithms\GZIP;
|
use Appwrite\Storage\Compression\Algorithms\GZIP;
|
||||||
use Appwrite\Resize\Resize;
|
use Appwrite\Resize\Resize;
|
||||||
use Appwrite\OpenSSL\OpenSSL;
|
use Appwrite\OpenSSL\OpenSSL;
|
||||||
|
use Appwrite\Utopia\Response;
|
||||||
use Utopia\Config\Config;
|
use Utopia\Config\Config;
|
||||||
|
|
||||||
App::post('/v1/storage/files')
|
App::post('/v1/storage/files')
|
||||||
->desc('Create File')
|
->desc('Create File')
|
||||||
->groups(['api', 'storage'])
|
->groups(['api', 'storage'])
|
||||||
->label('scope', 'files.write')
|
->label('scope', 'files.write')
|
||||||
->label('webhook', 'storage.files.create')
|
->label('event', 'storage.files.create')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'storage')
|
->label('sdk.namespace', 'storage')
|
||||||
->label('sdk.method', 'createFile')
|
->label('sdk.method', 'createFile')
|
||||||
|
@ -36,12 +37,11 @@ App::post('/v1/storage/files')
|
||||||
->param('file', [], new File(), 'Binary file.', false)
|
->param('file', [], new File(), 'Binary file.', false)
|
||||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->action(function ($file, $read, $write, $request, $response, $user, $projectDB, $webhooks, $audits, $usage) {
|
->action(function ($file, $read, $write, $request, $response, $user, $projectDB, $audits, $usage) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
/** @var Appwrite\Event\Event $usage */
|
/** @var Appwrite\Event\Event $usage */
|
||||||
|
|
||||||
|
@ -140,10 +140,6 @@ App::post('/v1/storage/files')
|
||||||
throw new Exception('Failed saving file to DB', 500);
|
throw new Exception('Failed saving file to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $file->getArrayCopy())
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'storage.files.create')
|
->setParam('event', 'storage.files.create')
|
||||||
->setParam('resource', 'storage/files/'.$file->getId())
|
->setParam('resource', 'storage/files/'.$file->getId())
|
||||||
|
@ -153,11 +149,9 @@ App::post('/v1/storage/files')
|
||||||
->setParam('storage', $sizeActual)
|
->setParam('storage', $sizeActual)
|
||||||
;
|
;
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($file, Response::MODEL_FILE);
|
||||||
->json($file->getArrayCopy())
|
}, ['request', 'response', 'user', 'projectDB', 'audits', 'usage']);
|
||||||
;
|
|
||||||
}, ['request', 'response', 'user', 'projectDB', 'webhooks', 'audits', 'usage']);
|
|
||||||
|
|
||||||
App::get('/v1/storage/files')
|
App::get('/v1/storage/files')
|
||||||
->desc('List Files')
|
->desc('List Files')
|
||||||
|
@ -187,11 +181,10 @@ App::get('/v1/storage/files')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$results = \array_map(function ($value) { /* @var $value \Database\Document */
|
$response->dynamic(new Document([
|
||||||
return $value->getArrayCopy(['$id', '$permissions', 'name', 'dateCreated', 'signature', 'mimeType', 'sizeOriginal']);
|
'sum' => $projectDB->getSum(),
|
||||||
}, $results);
|
'files' => $results
|
||||||
|
]), Response::MODEL_FILE_LIST);
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'files' => $results]);
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/storage/files/:fileId')
|
App::get('/v1/storage/files/:fileId')
|
||||||
|
@ -213,7 +206,7 @@ App::get('/v1/storage/files/:fileId')
|
||||||
throw new Exception('File not found', 404);
|
throw new Exception('File not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($file->getArrayCopy(['$id', '$permissions', 'name', 'dateCreated', 'signature', 'mimeType', 'sizeOriginal']));
|
$response->dynamic($file, Response::MODEL_FILE);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/storage/files/:fileId/preview')
|
App::get('/v1/storage/files/:fileId/preview')
|
||||||
|
@ -474,7 +467,7 @@ App::put('/v1/storage/files/:fileId')
|
||||||
->desc('Update File')
|
->desc('Update File')
|
||||||
->groups(['api', 'storage'])
|
->groups(['api', 'storage'])
|
||||||
->label('scope', 'files.write')
|
->label('scope', 'files.write')
|
||||||
->label('webhook', 'storage.files.update')
|
->label('event', 'storage.files.update')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'storage')
|
->label('sdk.namespace', 'storage')
|
||||||
->label('sdk.method', 'updateFile')
|
->label('sdk.method', 'updateFile')
|
||||||
|
@ -482,10 +475,9 @@ App::put('/v1/storage/files/:fileId')
|
||||||
->param('fileId', '', new UID(), 'File unique ID.')
|
->param('fileId', '', new UID(), 'File unique ID.')
|
||||||
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('read', [], new ArrayList(new Text(64)), 'An array of strings with read permissions. By default no user is granted with any read permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
->param('write', [], new ArrayList(new Text(64)), 'An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.')
|
||||||
->action(function ($fileId, $read, $write, $response, $projectDB, $webhooks, $audits) {
|
->action(function ($fileId, $read, $write, $response, $projectDB, $audits) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$file = $projectDB->getDocument($fileId);
|
$file = $projectDB->getDocument($fileId);
|
||||||
|
@ -506,23 +498,19 @@ App::put('/v1/storage/files/:fileId')
|
||||||
throw new Exception('Failed saving file to DB', 500);
|
throw new Exception('Failed saving file to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $file->getArrayCopy())
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'storage.files.update')
|
->setParam('event', 'storage.files.update')
|
||||||
->setParam('resource', 'storage/files/'.$file->getId())
|
->setParam('resource', 'storage/files/'.$file->getId())
|
||||||
;
|
;
|
||||||
|
|
||||||
$response->json($file->getArrayCopy());
|
$response->dynamic($file, Response::MODEL_FILE);
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
}, ['response', 'projectDB', 'webhooks', 'audits']);
|
||||||
|
|
||||||
App::delete('/v1/storage/files/:fileId')
|
App::delete('/v1/storage/files/:fileId')
|
||||||
->desc('Delete File')
|
->desc('Delete File')
|
||||||
->groups(['api', 'storage'])
|
->groups(['api', 'storage'])
|
||||||
->label('scope', 'files.write')
|
->label('scope', 'files.write')
|
||||||
->label('webhook', 'storage.files.delete')
|
->label('event', 'storage.files.delete')
|
||||||
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'storage')
|
->label('sdk.namespace', 'storage')
|
||||||
->label('sdk.method', 'deleteFile')
|
->label('sdk.method', 'deleteFile')
|
||||||
|
@ -548,11 +536,7 @@ App::delete('/v1/storage/files/:fileId')
|
||||||
throw new Exception('Failed to remove file from DB', 500);
|
throw new Exception('Failed to remove file from DB', 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$webhooks
|
|
||||||
->setParam('payload', $file->getArrayCopy())
|
|
||||||
;
|
|
||||||
|
|
||||||
$audits
|
$audits
|
||||||
->setParam('event', 'storage.files.delete')
|
->setParam('event', 'storage.files.delete')
|
||||||
->setParam('resource', 'storage/files/'.$file->getId())
|
->setParam('resource', 'storage/files/'.$file->getId())
|
||||||
|
@ -562,6 +546,10 @@ App::delete('/v1/storage/files/:fileId')
|
||||||
->setParam('storage', $file->getAttribute('size', 0) * -1)
|
->setParam('storage', $file->getAttribute('size', 0) * -1)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$webhooks
|
||||||
|
->setParam('payload', $response->output($file, Response::MODEL_FILE))
|
||||||
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
}, ['response', 'projectDB', 'webhooks', 'audits', 'usage']);
|
}, ['response', 'projectDB', 'webhooks', 'audits', 'usage']);
|
||||||
|
|
||||||
|
@ -613,6 +601,5 @@ App::delete('/v1/storage/files/:fileId')
|
||||||
// //var_dump($antiVirus->version());
|
// //var_dump($antiVirus->version());
|
||||||
// //var_dump($antiVirus->fileScan('/storage/uploads/app-1/5/9/f/e/59fecaed49645.pdf'));
|
// //var_dump($antiVirus->fileScan('/storage/uploads/app-1/5/9/f/e/59fecaed49645.pdf'));
|
||||||
|
|
||||||
// //$response->json($antiVirus->continueScan($device->getRoot()));
|
|
||||||
// }
|
// }
|
||||||
// );
|
// );
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Appwrite\Database\Exception\Duplicate;
|
||||||
use Appwrite\Database\Validator\Key;
|
use Appwrite\Database\Validator\Key;
|
||||||
use Appwrite\Template\Template;
|
use Appwrite\Template\Template;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
|
use DeviceDetector\DeviceDetector;
|
||||||
|
|
||||||
App::post('/v1/teams')
|
App::post('/v1/teams')
|
||||||
->desc('Create Team')
|
->desc('Create Team')
|
||||||
|
@ -80,10 +81,8 @@ App::post('/v1/teams')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
$response->dynamic($team, Response::MODEL_TEAM);
|
||||||
->json($team->getArrayCopy())
|
|
||||||
;
|
|
||||||
}, ['response', 'user', 'projectDB', 'mode']);
|
}, ['response', 'user', 'projectDB', 'mode']);
|
||||||
|
|
||||||
App::get('/v1/teams')
|
App::get('/v1/teams')
|
||||||
|
@ -114,7 +113,10 @@ App::get('/v1/teams')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'teams' => $results]);
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
|
'teams' => $results
|
||||||
|
]), Response::MODEL_TEAM_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/teams/:teamId')
|
App::get('/v1/teams/:teamId')
|
||||||
|
@ -136,7 +138,7 @@ App::get('/v1/teams/:teamId')
|
||||||
throw new Exception('Team not found', 404);
|
throw new Exception('Team not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($team->getArrayCopy([]));
|
$response->dynamic($team, Response::MODEL_TEAM);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::put('/v1/teams/:teamId')
|
App::put('/v1/teams/:teamId')
|
||||||
|
@ -166,8 +168,8 @@ App::put('/v1/teams/:teamId')
|
||||||
if (false === $team) {
|
if (false === $team) {
|
||||||
throw new Exception('Failed saving team to DB', 500);
|
throw new Exception('Failed saving team to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($team->getArrayCopy());
|
$response->dynamic($team, Response::MODEL_TEAM);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::delete('/v1/teams/:teamId')
|
App::delete('/v1/teams/:teamId')
|
||||||
|
@ -391,21 +393,12 @@ App::post('/v1/teams/:teamId/memberships')
|
||||||
->setParam('resource', 'teams/'.$teamId)
|
->setParam('resource', 'teams/'.$teamId)
|
||||||
;
|
;
|
||||||
|
|
||||||
$response
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED) // TODO change response of this endpoint
|
|
||||||
->json(\array_merge($membership->getArrayCopy([
|
$response->dynamic(new Document(\array_merge($membership->getArrayCopy(), [
|
||||||
'$id',
|
'email' => $email,
|
||||||
'userId',
|
'name' => $name,
|
||||||
'teamId',
|
])), Response::MODEL_MEMBERSHIP);
|
||||||
'roles',
|
|
||||||
'invited',
|
|
||||||
'joined',
|
|
||||||
'confirm',
|
|
||||||
]), [
|
|
||||||
'email' => $email,
|
|
||||||
'name' => $name,
|
|
||||||
]))
|
|
||||||
;
|
|
||||||
}, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails', 'mode']);
|
}, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails', 'mode']);
|
||||||
|
|
||||||
App::get('/v1/teams/:teamId/memberships')
|
App::get('/v1/teams/:teamId/memberships')
|
||||||
|
@ -453,18 +446,10 @@ App::get('/v1/teams/:teamId/memberships')
|
||||||
|
|
||||||
$temp = $projectDB->getDocument($membership->getAttribute('userId', null))->getArrayCopy(['email', 'name']);
|
$temp = $projectDB->getDocument($membership->getAttribute('userId', null))->getArrayCopy(['email', 'name']);
|
||||||
|
|
||||||
$users[] = \array_merge($temp, $membership->getArrayCopy([
|
$users[] = new Document(\array_merge($temp, $membership->getArrayCopy()));
|
||||||
'$id',
|
|
||||||
'userId',
|
|
||||||
'teamId',
|
|
||||||
'roles',
|
|
||||||
'invited',
|
|
||||||
'joined',
|
|
||||||
'confirm',
|
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'memberships' => $users]);
|
$response->dynamic(new Document(['sum' => $projectDB->getSum(), 'memberships' => $users]), Response::MODEL_MEMBERSHIP_LIST);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
|
@ -479,11 +464,12 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
->param('inviteId', '', new UID(), 'Invite unique ID.')
|
->param('inviteId', '', new UID(), 'Invite unique ID.')
|
||||||
->param('userId', '', new UID(), 'User unique ID.')
|
->param('userId', '', new UID(), 'User unique ID.')
|
||||||
->param('secret', '', new Text(256), 'Secret key.')
|
->param('secret', '', new Text(256), 'Secret key.')
|
||||||
->action(function ($teamId, $inviteId, $userId, $secret, $request, $response, $user, $projectDB, $audits) {
|
->action(function ($teamId, $inviteId, $userId, $secret, $request, $response, $user, $projectDB, $geodb, $audits) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $user */
|
/** @var Appwrite\Database\Document $user */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var MaxMind\Db\Reader $geodb */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
|
|
||||||
$protocol = $request->getProtocol();
|
$protocol = $request->getProtocol();
|
||||||
|
@ -540,10 +526,28 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
;
|
;
|
||||||
|
|
||||||
// Log user in
|
// Log user in
|
||||||
|
|
||||||
|
$dd = new DeviceDetector($request->getUserAgent('UNKNOWN'));
|
||||||
|
|
||||||
|
$dd->parse();
|
||||||
|
|
||||||
|
$os = $dd->getOs();
|
||||||
|
$osCode = (isset($os['short_name'])) ? $os['short_name'] : '';
|
||||||
|
$osName = (isset($os['name'])) ? $os['name'] : '';
|
||||||
|
$osVersion = (isset($os['version'])) ? $os['version'] : '';
|
||||||
|
|
||||||
|
$client = $dd->getClient();
|
||||||
|
$clientType = (isset($client['type'])) ? $client['type'] : '';
|
||||||
|
$clientCode = (isset($client['short_name'])) ? $client['short_name'] : '';
|
||||||
|
$clientName = (isset($client['name'])) ? $client['name'] : '';
|
||||||
|
$clientVersion = (isset($client['version'])) ? $client['version'] : '';
|
||||||
|
$clientEngine = (isset($client['engine'])) ? $client['engine'] : '';
|
||||||
|
$clientEngineVersion = (isset($client['engine_version'])) ? $client['engine_version'] : '';
|
||||||
|
|
||||||
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
$expiry = \time() + Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||||
$secret = Auth::tokenGenerator();
|
$secret = Auth::tokenGenerator();
|
||||||
|
|
||||||
$user->setAttribute('tokens', new Document([
|
$session = new Document([
|
||||||
'$collection' => Database::SYSTEM_COLLECTION_TOKENS,
|
'$collection' => Database::SYSTEM_COLLECTION_TOKENS,
|
||||||
'$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]],
|
'$permissions' => ['read' => ['user:'.$user->getId()], 'write' => ['user:'.$user->getId()]],
|
||||||
'type' => Auth::TOKEN_TYPE_LOGIN,
|
'type' => Auth::TOKEN_TYPE_LOGIN,
|
||||||
|
@ -551,7 +555,34 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
'expire' => $expiry,
|
'expire' => $expiry,
|
||||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||||
'ip' => $request->getIP(),
|
'ip' => $request->getIP(),
|
||||||
]), Document::SET_TYPE_APPEND);
|
|
||||||
|
'osCode' => $osCode,
|
||||||
|
'osName' => $osName,
|
||||||
|
'osVersion' => $osVersion,
|
||||||
|
'clientType' => $clientType,
|
||||||
|
'clientCode' => $clientCode,
|
||||||
|
'clientName' => $clientName,
|
||||||
|
'clientVersion' => $clientVersion,
|
||||||
|
'clientEngine' => $clientEngine,
|
||||||
|
'clientEngineVersion' => $clientEngineVersion,
|
||||||
|
'deviceName' => $dd->getDeviceName(),
|
||||||
|
'deviceBrand' => $dd->getBrandName(),
|
||||||
|
'deviceModel' => $dd->getModel(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$record = $geodb->get($request->getIP());
|
||||||
|
|
||||||
|
if($record) {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', \strtolower($record['country']['iso_code']))
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$session
|
||||||
|
->setAttribute('countryCode', '--')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->setAttribute('tokens', $session, Document::SET_TYPE_APPEND);
|
||||||
|
|
||||||
Authorization::setRole('user:'.$userId);
|
Authorization::setRole('user:'.$userId);
|
||||||
|
|
||||||
|
@ -594,7 +625,7 @@ App::patch('/v1/teams/:teamId/memberships/:inviteId/status')
|
||||||
'email' => $user->getAttribute('email'),
|
'email' => $user->getAttribute('email'),
|
||||||
'name' => $user->getAttribute('name'),
|
'name' => $user->getAttribute('name'),
|
||||||
])), Response::MODEL_MEMBERSHIP);
|
])), Response::MODEL_MEMBERSHIP);
|
||||||
}, ['request', 'response', 'user', 'projectDB', 'audits']);
|
}, ['request', 'response', 'user', 'projectDB', 'geodb', 'audits']);
|
||||||
|
|
||||||
App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
App::delete('/v1/teams/:teamId/memberships/:inviteId')
|
||||||
->desc('Delete Team Membership')
|
->desc('Delete Team Membership')
|
||||||
|
|
|
@ -9,10 +9,10 @@ use Utopia\Validator\Text;
|
||||||
use Utopia\Validator\Range;
|
use Utopia\Validator\Range;
|
||||||
use Utopia\Audit\Audit;
|
use Utopia\Audit\Audit;
|
||||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||||
use Utopia\Config\Config;
|
|
||||||
use Appwrite\Auth\Auth;
|
use Appwrite\Auth\Auth;
|
||||||
use Appwrite\Auth\Validator\Password;
|
use Appwrite\Auth\Validator\Password;
|
||||||
use Appwrite\Database\Database;
|
use Appwrite\Database\Database;
|
||||||
|
use Appwrite\Database\Document;
|
||||||
use Appwrite\Database\Exception\Duplicate;
|
use Appwrite\Database\Exception\Duplicate;
|
||||||
use Appwrite\Database\Validator\UID;
|
use Appwrite\Database\Validator\UID;
|
||||||
use Appwrite\Utopia\Response;
|
use Appwrite\Utopia\Response;
|
||||||
|
@ -21,6 +21,7 @@ use DeviceDetector\DeviceDetector;
|
||||||
App::post('/v1/users')
|
App::post('/v1/users')
|
||||||
->desc('Create User')
|
->desc('Create User')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
|
->label('event', 'users.create')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'users')
|
->label('sdk.namespace', 'users')
|
||||||
|
@ -65,27 +66,8 @@ App::post('/v1/users')
|
||||||
throw new Exception('Account already exists', 409);
|
throw new Exception('Account already exists', 409);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oauth2Keys = [];
|
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||||
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
foreach (Config::getParam('providers') as $key => $provider) {
|
|
||||||
if (!$provider['enabled']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
$response
|
|
||||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
|
||||||
->json(\array_merge($user->getArrayCopy(\array_merge([
|
|
||||||
'$id',
|
|
||||||
'status',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'emailVerification',
|
|
||||||
'name',
|
|
||||||
], $oauth2Keys)), ['roles' => []]));
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/users')
|
App::get('/v1/users')
|
||||||
|
@ -116,32 +98,10 @@ App::get('/v1/users')
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$oauth2Keys = [];
|
$response->dynamic(new Document([
|
||||||
|
'sum' => $projectDB->getSum(),
|
||||||
foreach (Config::getParam('providers') as $key => $provider) {
|
'users' => $results
|
||||||
if (!$provider['enabled']) {
|
]), Response::MODEL_USER_LIST);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
$results = \array_map(function ($value) use ($oauth2Keys) { /* @var $value \Database\Document */
|
|
||||||
return $value->getArrayCopy(\array_merge(
|
|
||||||
[
|
|
||||||
'$id',
|
|
||||||
'status',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'emailVerification',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
));
|
|
||||||
}, $results);
|
|
||||||
|
|
||||||
$response->json(['sum' => $projectDB->getSum(), 'users' => $results]);
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/users/:userId')
|
App::get('/v1/users/:userId')
|
||||||
|
@ -163,28 +123,7 @@ App::get('/v1/users/:userId')
|
||||||
throw new Exception('User not found', 404);
|
throw new Exception('User not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oauth2Keys = [];
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
|
|
||||||
foreach (Config::getParam('providers') as $key => $provider) {
|
|
||||||
if (!$provider['enabled']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->json(\array_merge($user->getArrayCopy(\array_merge(
|
|
||||||
[
|
|
||||||
'$id',
|
|
||||||
'status',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'emailVerification',
|
|
||||||
'name',
|
|
||||||
],
|
|
||||||
$oauth2Keys
|
|
||||||
)), ['roles' => []]));
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::get('/v1/users/:userId/prefs')
|
App::get('/v1/users/:userId/prefs')
|
||||||
|
@ -208,13 +147,6 @@ App::get('/v1/users/:userId/prefs')
|
||||||
|
|
||||||
$prefs = $user->getAttribute('prefs', '');
|
$prefs = $user->getAttribute('prefs', '');
|
||||||
|
|
||||||
try {
|
|
||||||
$prefs = \json_decode($prefs, true);
|
|
||||||
$prefs = ($prefs) ? $prefs : [];
|
|
||||||
} catch (\Exception $error) {
|
|
||||||
throw new Exception('Failed to parse prefs', 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->json($prefs);
|
$response->json($prefs);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
|
@ -227,11 +159,10 @@ App::get('/v1/users/:userId/sessions')
|
||||||
->label('sdk.method', 'getSessions')
|
->label('sdk.method', 'getSessions')
|
||||||
->label('sdk.description', '/docs/references/users/get-user-sessions.md')
|
->label('sdk.description', '/docs/references/users/get-user-sessions.md')
|
||||||
->param('userId', '', new UID(), 'User unique ID.')
|
->param('userId', '', new UID(), 'User unique ID.')
|
||||||
->action(function ($userId, $response, $projectDB, $locale, $geodb) {
|
->action(function ($userId, $response, $projectDB, $locale) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
/** @var Utopia\Locale\Locale $locale */
|
/** @var Utopia\Locale\Locale $locale */
|
||||||
/** @var MaxMind\Db\Reader $geodb */
|
|
||||||
|
|
||||||
$user = $projectDB->getDocument($userId);
|
$user = $projectDB->getDocument($userId);
|
||||||
|
|
||||||
|
@ -241,7 +172,6 @@ App::get('/v1/users/:userId/sessions')
|
||||||
|
|
||||||
$tokens = $user->getAttribute('tokens', []);
|
$tokens = $user->getAttribute('tokens', []);
|
||||||
$sessions = [];
|
$sessions = [];
|
||||||
$index = 0;
|
|
||||||
$countries = $locale->getText('countries');
|
$countries = $locale->getText('countries');
|
||||||
|
|
||||||
foreach ($tokens as $token) { /* @var $token Document */
|
foreach ($tokens as $token) { /* @var $token Document */
|
||||||
|
@ -249,46 +179,19 @@ App::get('/v1/users/:userId/sessions')
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$userAgent = (!empty($token->getAttribute('userAgent'))) ? $token->getAttribute('userAgent') : 'UNKNOWN';
|
$token->setAttribute('countryName', (isset($countries[$token->getAttribute('contryCode')]))
|
||||||
|
? $countries[$token->getAttribute('contryCode')]
|
||||||
|
: $locale->getText('locale.country.unknown'));
|
||||||
|
$token->setAttribute('current', false);
|
||||||
|
|
||||||
$dd = new DeviceDetector($userAgent);
|
$sessions[] = $token;
|
||||||
|
|
||||||
// OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
|
|
||||||
// $dd->skipBotDetection();
|
|
||||||
|
|
||||||
$dd->parse();
|
|
||||||
|
|
||||||
$sessions[$index] = [
|
|
||||||
'$id' => $token->getId(),
|
|
||||||
'OS' => $dd->getOs(),
|
|
||||||
'client' => $dd->getClient(),
|
|
||||||
'device' => $dd->getDevice(),
|
|
||||||
'brand' => $dd->getBrand(),
|
|
||||||
'model' => $dd->getModel(),
|
|
||||||
'ip' => $token->getAttribute('ip', ''),
|
|
||||||
'geo' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$record = $geodb->get($token->getAttribute('ip', ''));
|
|
||||||
|
|
||||||
if ($record) {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = \strtolower($record['country']['iso_code']);
|
|
||||||
$sessions[$index]['geo']['country'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
|
||||||
} else {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = '--';
|
|
||||||
$sessions[$index]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$sessions[$index]['geo']['isoCode'] = '--';
|
|
||||||
$sessions[$index]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
|
||||||
|
|
||||||
++$index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($sessions);
|
$response->dynamic(new Document([
|
||||||
}, ['response', 'projectDB', 'locale', 'geodb']);
|
'sum' => count($sessions),
|
||||||
|
'sessions' => $sessions
|
||||||
|
]), Response::MODEL_SESSION_LIST);
|
||||||
|
}, ['response', 'projectDB', 'locale']);
|
||||||
|
|
||||||
App::get('/v1/users/:userId/logs')
|
App::get('/v1/users/:userId/logs')
|
||||||
->desc('Get User Logs')
|
->desc('Get User Logs')
|
||||||
|
@ -349,40 +252,56 @@ App::get('/v1/users/:userId/logs')
|
||||||
|
|
||||||
$dd->parse();
|
$dd->parse();
|
||||||
|
|
||||||
$output[$i] = [
|
$os = $dd->getOs();
|
||||||
|
$osCode = (isset($os['short_name'])) ? $os['short_name'] : '';
|
||||||
|
$osName = (isset($os['name'])) ? $os['name'] : '';
|
||||||
|
$osVersion = (isset($os['version'])) ? $os['version'] : '';
|
||||||
|
|
||||||
|
$client = $dd->getClient();
|
||||||
|
$clientType = (isset($client['type'])) ? $client['type'] : '';
|
||||||
|
$clientCode = (isset($client['short_name'])) ? $client['short_name'] : '';
|
||||||
|
$clientName = (isset($client['name'])) ? $client['name'] : '';
|
||||||
|
$clientVersion = (isset($client['version'])) ? $client['version'] : '';
|
||||||
|
$clientEngine = (isset($client['engine'])) ? $client['engine'] : '';
|
||||||
|
$clientEngineVersion = (isset($client['engine_version'])) ? $client['engine_version'] : '';
|
||||||
|
|
||||||
|
$output[$i] = new Document([
|
||||||
'event' => $log['event'],
|
'event' => $log['event'],
|
||||||
'ip' => $log['ip'],
|
'ip' => $log['ip'],
|
||||||
'time' => \strtotime($log['time']),
|
'time' => \strtotime($log['time']),
|
||||||
'OS' => $dd->getOs(),
|
|
||||||
'client' => $dd->getClient(),
|
|
||||||
'device' => $dd->getDevice(),
|
|
||||||
'brand' => $dd->getBrand(),
|
|
||||||
'model' => $dd->getModel(),
|
|
||||||
'geo' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
'osCode' => $osCode,
|
||||||
$record = $geodb->get($log['ip']);
|
'osName' => $osName,
|
||||||
|
'osVersion' => $osVersion,
|
||||||
|
'clientType' => $clientType,
|
||||||
|
'clientCode' => $clientCode,
|
||||||
|
'clientName' => $clientName,
|
||||||
|
'clientVersion' => $clientVersion,
|
||||||
|
'clientEngine' => $clientEngine,
|
||||||
|
'clientEngineVersion' => $clientEngineVersion,
|
||||||
|
'deviceName' => $dd->getDeviceName(),
|
||||||
|
'deviceBrand' => $dd->getBrandName(),
|
||||||
|
'deviceModel' => $dd->getModel(),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($record) {
|
$record = $geodb->get($log['ip']);
|
||||||
$output[$i]['geo']['isoCode'] = \strtolower($record['country']['iso_code']);
|
|
||||||
$output[$i]['geo']['country'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
if ($record) {
|
||||||
} else {
|
$output[$i]['countryCode'] = (isset($countries[$record['country']['iso_code']])) ? \strtolower($record['country']['iso_code']) : '--';
|
||||||
$output[$i]['geo']['isoCode'] = '--';
|
$output[$i]['countryName'] = (isset($countries[$record['country']['iso_code']])) ? $countries[$record['country']['iso_code']] : $locale->getText('locale.country.unknown');
|
||||||
$output[$i]['geo']['country'] = $locale->getText('locale.country.unknown');
|
} else {
|
||||||
}
|
$output[$i]['countryCode'] = '--';
|
||||||
} catch (\Exception $e) {
|
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
|
||||||
$output[$i]['geo']['isoCode'] = '--';
|
|
||||||
$output[$i]['geo']['country'] = $locale->getText('locale.country.unknown');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json($output);
|
$response->dynamic(new Document(['logs' => $output]), Response::MODEL_LOG_LIST);
|
||||||
}, ['response', 'register', 'project', 'projectDB', 'locale', 'geodb']);
|
}, ['response', 'register', 'project', 'projectDB', 'locale', 'geodb']);
|
||||||
|
|
||||||
App::patch('/v1/users/:userId/status')
|
App::patch('/v1/users/:userId/status')
|
||||||
->desc('Update User Status')
|
->desc('Update User Status')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
|
->label('event', 'users.update.status')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'users')
|
->label('sdk.namespace', 'users')
|
||||||
|
@ -407,27 +326,8 @@ App::patch('/v1/users/:userId/status')
|
||||||
if (false === $user) {
|
if (false === $user) {
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oauth2Keys = [];
|
|
||||||
|
|
||||||
foreach (Config::getParam('providers') as $key => $provider) {
|
$response->dynamic($user, Response::MODEL_USER);
|
||||||
if (!$provider['enabled']) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key);
|
|
||||||
$oauth2Keys[] = 'oauth2'.\ucfirst($key).'AccessToken';
|
|
||||||
}
|
|
||||||
|
|
||||||
$response
|
|
||||||
->json(\array_merge($user->getArrayCopy(\array_merge([
|
|
||||||
'$id',
|
|
||||||
'status',
|
|
||||||
'email',
|
|
||||||
'registration',
|
|
||||||
'emailVerification',
|
|
||||||
'name',
|
|
||||||
], $oauth2Keys)), ['roles' => []]));
|
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::patch('/v1/users/:userId/prefs')
|
App::patch('/v1/users/:userId/prefs')
|
||||||
|
@ -450,32 +350,21 @@ App::patch('/v1/users/:userId/prefs')
|
||||||
throw new Exception('User not found', 404);
|
throw new Exception('User not found', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$old = \json_decode($user->getAttribute('prefs', '{}'), true);
|
|
||||||
$old = ($old) ? $old : [];
|
|
||||||
|
|
||||||
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
$user = $projectDB->updateDocument(\array_merge($user->getArrayCopy(), [
|
||||||
'prefs' => \json_encode(\array_merge($old, $prefs)),
|
'prefs' => $prefs,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
if (false === $user) {
|
if (false === $user) {
|
||||||
throw new Exception('Failed saving user to DB', 500);
|
throw new Exception('Failed saving user to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefs = $user->getAttribute('prefs', '');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$prefs = \json_decode($prefs, true);
|
|
||||||
$prefs = ($prefs) ? $prefs : [];
|
|
||||||
} catch (\Exception $error) {
|
|
||||||
throw new Exception('Failed to parse prefs', 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->json($prefs);
|
$response->json($prefs);
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB']);
|
||||||
|
|
||||||
App::delete('/v1/users/:userId/sessions/:sessionId')
|
App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||||
->desc('Delete User Session')
|
->desc('Delete User Session')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
|
->label('event', 'users.sessions.delete')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'users')
|
->label('sdk.namespace', 'users')
|
||||||
|
@ -484,9 +373,10 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||||
->label('abuse-limit', 100)
|
->label('abuse-limit', 100)
|
||||||
->param('userId', '', new UID(), 'User unique ID.')
|
->param('userId', '', new UID(), 'User unique ID.')
|
||||||
->param('sessionId', null, new UID(), 'User unique session ID.')
|
->param('sessionId', null, new UID(), 'User unique session ID.')
|
||||||
->action(function ($userId, $sessionId, $response, $projectDB) {
|
->action(function ($userId, $sessionId, $response, $projectDB, $webhooks) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var Appwrite\Event\Event $webhooks */
|
||||||
|
|
||||||
$user = $projectDB->getDocument($userId);
|
$user = $projectDB->getDocument($userId);
|
||||||
|
|
||||||
|
@ -501,15 +391,20 @@ App::delete('/v1/users/:userId/sessions/:sessionId')
|
||||||
if (!$projectDB->deleteDocument($token->getId())) {
|
if (!$projectDB->deleteDocument($token->getId())) {
|
||||||
throw new Exception('Failed to remove token from DB', 500);
|
throw new Exception('Failed to remove token from DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$webhooks
|
||||||
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json(array('result' => 'success'));
|
$response->noContent();
|
||||||
}, ['response', 'projectDB']);
|
}, ['response', 'projectDB', 'webhooks']);
|
||||||
|
|
||||||
App::delete('/v1/users/:userId/sessions')
|
App::delete('/v1/users/:userId/sessions')
|
||||||
->desc('Delete User Sessions')
|
->desc('Delete User Sessions')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
|
->label('event', 'users.sessions.delete')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'users')
|
->label('sdk.namespace', 'users')
|
||||||
|
@ -517,9 +412,10 @@ App::delete('/v1/users/:userId/sessions')
|
||||||
->label('sdk.description', '/docs/references/users/delete-user-sessions.md')
|
->label('sdk.description', '/docs/references/users/delete-user-sessions.md')
|
||||||
->label('abuse-limit', 100)
|
->label('abuse-limit', 100)
|
||||||
->param('userId', '', new UID(), 'User unique ID.')
|
->param('userId', '', new UID(), 'User unique ID.')
|
||||||
->action(function ($userId, $response, $projectDB) {
|
->action(function ($userId, $response, $projectDB, $webhooks) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var Appwrite\Event\Event $webhooks */
|
||||||
|
|
||||||
$user = $projectDB->getDocument($userId);
|
$user = $projectDB->getDocument($userId);
|
||||||
|
|
||||||
|
@ -535,12 +431,17 @@ App::delete('/v1/users/:userId/sessions')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->json(array('result' => 'success'));
|
$webhooks
|
||||||
}, ['response', 'projectDB']);
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
|
;
|
||||||
|
|
||||||
|
$response->noContent();
|
||||||
|
}, ['response', 'projectDB', 'webhooks']);
|
||||||
|
|
||||||
App::delete('/v1/users/:userId')
|
App::delete('/v1/users/:userId')
|
||||||
->desc('Delete User')
|
->desc('Delete User')
|
||||||
->groups(['api', 'users'])
|
->groups(['api', 'users'])
|
||||||
|
->label('event', 'users.delete')
|
||||||
->label('scope', 'users.write')
|
->label('scope', 'users.write')
|
||||||
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
->label('sdk.platform', [APP_PLATFORM_SERVER])
|
||||||
->label('sdk.namespace', 'users')
|
->label('sdk.namespace', 'users')
|
||||||
|
@ -548,9 +449,10 @@ App::delete('/v1/users/:userId')
|
||||||
->label('sdk.description', '/docs/references/users/delete-user.md')
|
->label('sdk.description', '/docs/references/users/delete-user.md')
|
||||||
->label('abuse-limit', 100)
|
->label('abuse-limit', 100)
|
||||||
->param('userId', '', function () {return new UID();}, 'User unique ID.')
|
->param('userId', '', function () {return new UID();}, 'User unique ID.')
|
||||||
->action(function ($userId, $response, $projectDB, $deletes) {
|
->action(function ($userId, $response, $projectDB, $webhooks, $deletes) {
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Database $projectDB */
|
/** @var Appwrite\Database\Database $projectDB */
|
||||||
|
/** @var Appwrite\Event\Event $webhooks */
|
||||||
/** @var Appwrite\Event\Event $deletes */
|
/** @var Appwrite\Event\Event $deletes */
|
||||||
|
|
||||||
$user = $projectDB->getDocument($userId);
|
$user = $projectDB->getDocument($userId);
|
||||||
|
@ -578,7 +480,13 @@ App::delete('/v1/users/:userId')
|
||||||
throw new Exception('Failed saving reserved id to DB', 500);
|
throw new Exception('Failed saving reserved id to DB', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$deletes->setParam('document', $user);
|
$deletes
|
||||||
|
->setParam('document', $user)
|
||||||
|
;
|
||||||
|
|
||||||
|
$webhooks
|
||||||
|
->setParam('payload', $response->output($user, Response::MODEL_USER))
|
||||||
|
;
|
||||||
|
|
||||||
$response->noContent();
|
$response->noContent();
|
||||||
}, ['response', 'projectDB', 'deletes']);
|
}, ['response', 'projectDB', 'webhooks', 'deletes']);
|
||||||
|
|
|
@ -22,7 +22,7 @@ Config::setParam('domainVerification', false);
|
||||||
Config::setParam('cookieDomain', 'localhost');
|
Config::setParam('cookieDomain', 'localhost');
|
||||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||||
|
|
||||||
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $webhooks, $audits, $usage, $clients) {
|
App::init(function ($utopia, $request, $response, $console, $project, $user, $locale, $webhooks, $audits, $usage, $deletes, $clients) {
|
||||||
/** @var Utopia\Swoole\Request $request */
|
/** @var Utopia\Swoole\Request $request */
|
||||||
/** @var Appwrite\Utopia\Response $response */
|
/** @var Appwrite\Utopia\Response $response */
|
||||||
/** @var Appwrite\Database\Document $console */
|
/** @var Appwrite\Database\Document $console */
|
||||||
|
@ -32,6 +32,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
/** @var Appwrite\Event\Event $webhooks */
|
/** @var Appwrite\Event\Event $webhooks */
|
||||||
/** @var Appwrite\Event\Event $audits */
|
/** @var Appwrite\Event\Event $audits */
|
||||||
/** @var Appwrite\Event\Event $usage */
|
/** @var Appwrite\Event\Event $usage */
|
||||||
|
/** @var Appwrite\Event\Event $deletes */
|
||||||
/** @var bool $mode */
|
/** @var bool $mode */
|
||||||
/** @var array $clients */
|
/** @var array $clients */
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
if ($user->getId()) {
|
if ($user->getId()) {
|
||||||
Authorization::setRole('user:'.$user->getId());
|
Authorization::setRole('user:'.$user->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
Authorization::setRole('role:'.$role);
|
Authorization::setRole('role:'.$role);
|
||||||
|
|
||||||
\array_map(function ($node) {
|
\array_map(function ($node) {
|
||||||
|
@ -223,7 +224,7 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
*/
|
*/
|
||||||
$webhooks
|
$webhooks
|
||||||
->setParam('projectId', $project->getId())
|
->setParam('projectId', $project->getId())
|
||||||
->setParam('event', $route->getLabel('webhook', ''))
|
->setParam('event', $route->getLabel('event', ''))
|
||||||
->setParam('payload', [])
|
->setParam('payload', [])
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -246,7 +247,11 @@ App::init(function ($utopia, $request, $response, $console, $project, $user, $lo
|
||||||
->setParam('networkResponseSize', 0)
|
->setParam('networkResponseSize', 0)
|
||||||
->setParam('storage', 0)
|
->setParam('storage', 0)
|
||||||
;
|
;
|
||||||
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'webhooks', 'audits', 'usage', 'clients']);
|
|
||||||
|
$deletes
|
||||||
|
->setParam('projectId', $project->getId())
|
||||||
|
;
|
||||||
|
}, ['utopia', 'request', 'response', 'console', 'project', 'user', 'locale', 'webhooks', 'audits', 'usage', 'deletes', 'clients']);
|
||||||
|
|
||||||
App::shutdown(function ($utopia, $request, $response, $project, $webhooks, $audits, $usage, $deletes, $mode) {
|
App::shutdown(function ($utopia, $request, $response, $project, $webhooks, $audits, $usage, $deletes, $mode) {
|
||||||
/** @var Utopia\App $utopia */
|
/** @var Utopia\App $utopia */
|
||||||
|
@ -260,6 +265,10 @@ App::shutdown(function ($utopia, $request, $response, $project, $webhooks, $audi
|
||||||
/** @var bool $mode */
|
/** @var bool $mode */
|
||||||
|
|
||||||
if (!empty($webhooks->getParam('event'))) {
|
if (!empty($webhooks->getParam('event'))) {
|
||||||
|
if(empty($webhooks->getParam('payload'))) {
|
||||||
|
$webhooks->setParam('payload', $response->getPayload());
|
||||||
|
}
|
||||||
|
|
||||||
$webhooks->trigger();
|
$webhooks->trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@
|
||||||
data-name="sessions"
|
data-name="sessions"
|
||||||
data-event="load,account.deleteRemoteSession">
|
data-event="load,account.deleteRemoteSession">
|
||||||
|
|
||||||
<ul data-ls-loop="sessions" data-ls-as="session" class="list">
|
<ul data-ls-loop="sessions.sessions" data-ls-as="session" class="list">
|
||||||
<li class="clear">
|
<li class="clear">
|
||||||
<span data-ls-if="true != {{session.current}}">
|
<span data-ls-if="true != {{session.current}}">
|
||||||
<!-- From remote session (-logout event) -->
|
<!-- From remote session (-logout event) -->
|
||||||
|
@ -236,17 +236,18 @@
|
||||||
</form>
|
</form>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.client.short_name|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.client.name}},alt={{session.client.name}}" class="avatar trans pull-start margin-end" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar trans pull-start margin-end" />
|
||||||
|
|
||||||
<span data-ls-if="({{session.client.name}})" data-ls-bind="{{session.client.name}}"></span> <span data-ls-if="(!{{session.client.name}})">Unknown</span> <span data-ls-bind="{{session.client.version}}"></span> on <span data-ls-bind="{{session.model}}"></span> <span data-ls-if="(!{{session.OS.name}})">Unknown</span> <span data-ls-if="({{session.OS.name}})" data-ls-bind="{{session.OS.name}}"></span> <span data-ls-bind="{{session.OS.version}}"></span>
|
<span data-ls-if="(!{{log.clientName}})">Unknown</span>
|
||||||
|
<span data-ls-if="({{log.clientName}})" data-ls-bind="{{session.clientName}}"></span> <span data-ls-bind="{{session.clientVersion}}"></span> on <span data-ls-bind="{{session.deviceModel}}"></span> <span data-ls-bind="{{session.osName}}"></span> <span data-ls-bind="{{session.osVersion}}"></span>
|
||||||
|
|
||||||
<span data-ls-if="true == {{session.current}}">
|
<span data-ls-if="true == {{session.current}}">
|
||||||
<span class="tag green">Current Session</span>
|
<span class="tag green">Current Session</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="margin-top-small">
|
<div class="margin-top-small">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
||||||
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.geo.country}}"></small>
|
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.countryName}}"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -289,17 +290,18 @@
|
||||||
<th width="90">IP</th>
|
<th width="90">IP</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-ls-loop="securityLogs" data-ls-as="log">
|
<tbody data-ls-loop="securityLogs.logs" data-ls-as="log">
|
||||||
<tr>
|
<tr>
|
||||||
<td data-title="Date: "><span data-ls-bind="{{log.time|dateTime}}"></span></td>
|
<td data-title="Date: "><span data-ls-bind="{{log.time|dateTime}}"></span></td>
|
||||||
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
|
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
|
||||||
<td data-title="Client: ">
|
<td data-title="Client: ">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xxs inline margin-end-small" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.clientCode|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.clientName}},alt={{log.clientName}}" class="avatar xxs inline margin-end-small" />
|
||||||
<span data-ls-bind="{{log.client.name}} {{log.client.version}} on {{log.model}} {{log.OS.name}} {{log.OS.version}}"></span>
|
<span data-ls-if="(!{{log.clientName}})">Unknown</span>
|
||||||
|
<span data-ls-if="({{log.clientName}})" data-ls-bind="{{log.clientName}} {{log.clientVersion}} on {{log.model}} {{log.osName}} {{log.osVersion}}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="Location: ">
|
<td data-title="Location: ">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/flags/{{log.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
|
||||||
<span data-ls-bind="{{log.geo.country}}"></span>
|
<span data-ls-bind="{{log.geo.countryName}}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
|
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -3,12 +3,11 @@ $fileLimit = $this->getParam('fileLimit', 0);
|
||||||
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
$fileLimitHuman = $this->getParam('fileLimitHuman', 0);
|
||||||
$events = array_keys($this->getParam('events', []));
|
$events = array_keys($this->getParam('events', []));
|
||||||
$timeout = $this->getParam('timeout', 900);
|
$timeout = $this->getParam('timeout', 900);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div
|
<div
|
||||||
data-service="functions.get"
|
data-service="functions.get"
|
||||||
data-name="project-function"
|
data-name="project-function"
|
||||||
data-event="load,functions.update,functions.createTag,functions.updateTag"
|
data-event="load,functions.update,functions.createTag,functions.updateTag,functions.deleteTag"
|
||||||
data-param-function-id="{{router.params.id}}"
|
data-param-function-id="{{router.params.id}}"
|
||||||
data-success="trigger"
|
data-success="trigger"
|
||||||
data-success-param-trigger-events="functions.get">
|
data-success-param-trigger-events="functions.get">
|
||||||
|
@ -64,7 +63,7 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
data-failure="alert"
|
data-failure="alert"
|
||||||
data-failure-param-alert-text="Failed to execute function"
|
data-failure-param-alert-text="Failed to execute function"
|
||||||
data-failure-param-alert-classname="error">
|
data-failure-param-alert-classname="error">
|
||||||
<button style="vertical-align: top;">Execute Now</button> <a data-ls-attrs="href=/console/functions/function/usage?id={{router.params.id}}&project={{router.params.project}}" class="button reverse" style="vertical-align: top;">View Logs</a>
|
<button style="vertical-align: top;">Execute Now</button> <a data-ls-attrs="href=/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}" class="button reverse" style="vertical-align: top;">View Logs</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,7 +112,7 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
<b data-ls-bind="{{tag.$id}}"></b>
|
<b data-ls-bind="{{tag.$id}}"></b>
|
||||||
<span class="text-fade" data-ls-bind="{{tag.command}}"></span>
|
<span class="text-fade" data-ls-bind="{{tag.command}}"></span>
|
||||||
<div class="text-size-small margin-top-small clear">
|
<div class="text-size-small margin-top-small clear">
|
||||||
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} | {{tag.codeSize|humanFileSize}}"></span>
|
<span class="pull-start" data-ls-bind="Created {{tag.dateCreated|timeSince}} | {{tag.size|humanFileSize}}"></span>
|
||||||
|
|
||||||
<form data-ls-if="{{tag.$id}} !== {{project-function.tag}}" name="functions.deleteTag" class="pull-start"
|
<form data-ls-if="{{tag.$id}} !== {{project-function.tag}}" name="functions.deleteTag" class="pull-start"
|
||||||
data-analytics-event="submit"
|
data-analytics-event="submit"
|
||||||
|
@ -241,23 +240,89 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li data-state="/console/functions/function/usage?id={{router.params.id}}&project={{router.params.project}}">
|
<li data-state="/console/functions/function/monitors?id={{router.params.id}}&project={{router.params.project}}">
|
||||||
<h2>Usage</h2>
|
|
||||||
|
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '90d'"
|
||||||
|
data-service="functions.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-function-id="{{router.params.id}}"
|
||||||
|
data-param-range="90d">
|
||||||
|
<button class="tick">90d</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div class="box margin-bottom-small">
|
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
|
||||||
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
|
||||||
<div class="chart margin-bottom-no">
|
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '30d'"
|
||||||
<div class="content" data-forms-chart="Requests=usage.requests.data,Network=usage.network.data" data-height="140"></div>
|
data-service="functions.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-function-id="{{router.params.id}}">
|
||||||
|
<button class="tick">30d</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
|
||||||
|
|
||||||
|
<form class="pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} !== '24h'"
|
||||||
|
data-service="functions.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-function-id="{{router.params.id}}"
|
||||||
|
data-param-range="24h">
|
||||||
|
<button class="tick">24h</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button class="tick pull-end margin-start-small margin-top-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
|
||||||
|
|
||||||
|
<h2>Monitors</h2>
|
||||||
|
|
||||||
|
<div
|
||||||
|
data-service="functions.getUsage"
|
||||||
|
data-event="load"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-function-id="{{router.params.id}}">
|
||||||
|
<div class="box margin-bottom-small">
|
||||||
|
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||||
|
<div class="chart margin-bottom-no">
|
||||||
|
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Executions=usage.executions.data" data-height="140" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ul class="chart-notes margin-bottom-large">
|
||||||
|
<li>Executions <span data-ls-bind="({{usage.executions.total}})"></span></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="box margin-bottom-small">
|
||||||
|
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||||
|
<div class="chart margin-bottom-no">
|
||||||
|
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="CPU Time (seconds)=usage.compute.data" data-colors="orange" data-height="140" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="chart-notes margin-bottom-large">
|
||||||
|
<li class="orange">CPU Time <span data-ls-bind="({{usage.compute.total|seconds2hum}})"></span></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="box margin-bottom-small">
|
||||||
|
<div class="margin-start-negative-small margin-end-negative-small margin-top-negative-small margin-bottom-negative-small">
|
||||||
|
<div class="chart margin-bottom-no">
|
||||||
|
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Failures=usage.failures.data" data-colors="red" data-height="140" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="chart-notes margin-bottom-large">
|
||||||
|
<li class="red">Errors <span data-ls-bind="({{usage.failures.total}})"></span></li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</li>
|
||||||
|
<li data-state="/console/functions/function/logs?id={{router.params.id}}&project={{router.params.project}}">
|
||||||
|
|
||||||
<ul class="chart-notes margin-bottom-large">
|
<div class="text-fade text-size-small pull-end margin-top" data-ls-bind="{{project-function-executions.sum}} executions found"></div>
|
||||||
<li>Invocations</li>
|
|
||||||
<li>CPU Time</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Logs <span class="text-fade text-size-small pull-end margin-top-small" data-ls-bind="{{project-function-executions.sum}} executions found"></span></h3>
|
<h2>Logs</h2>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-service="functions.listExecutions"
|
data-service="functions.listExecutions"
|
||||||
|
@ -277,9 +342,10 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="30"></th>
|
<th width="30"></th>
|
||||||
|
<th width="160">Created</th>
|
||||||
<th width="150">Status</th>
|
<th width="150">Status</th>
|
||||||
<th width="170">Date</th>
|
<th width="120">Trigger</th>
|
||||||
<th width="100">Runtime</th>
|
<th width="80">Runtime</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -291,35 +357,42 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
<i class="dot info" data-ls-if="{{execution.status}} === 'processing'"></i>
|
<i class="dot info" data-ls-if="{{execution.status}} === 'processing'"></i>
|
||||||
<i class="dot success" data-ls-if="{{execution.status}} === 'completed'"></i>
|
<i class="dot success" data-ls-if="{{execution.status}} === 'completed'"></i>
|
||||||
</td>
|
</td>
|
||||||
|
<td data-title="Date: ">
|
||||||
|
<span data-ls-bind="{{execution.dateCreated|dateTime}}"></span>
|
||||||
|
</td>
|
||||||
<td data-title="Status: ">
|
<td data-title="Status: ">
|
||||||
<span data-ls-bind="{{execution.status}}"></span>
|
<span data-ls-bind="{{execution.status}}"></span>
|
||||||
<span class="text-fade text-size-small" data-ls-if="{{execution.exitCode}} !== 0" data-ls-bind=" exit code: {{execution.exitCode}}"></span>
|
<span class="text-fade text-size-small" data-ls-if="{{execution.exitCode}} !== 0" data-ls-bind=" exit code: {{execution.exitCode}}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="Date: ">
|
<td data-title="Trigger: ">
|
||||||
<span data-ls-bind="{{execution.dateCreated|dateTime}}"></span>
|
<span data-ls-bind="{{execution.trigger}}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="Runtime: ">
|
<td data-title="Runtime: ">
|
||||||
<span data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-ls-bind="{{execution.time|seconds2hum}}"></span>
|
<span data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-ls-bind="{{execution.time|seconds2hum}}"></span>
|
||||||
<span data-ls-if="{{execution.status}} === 'waiting' || {{execution.status}} === 'processing'">-</span>
|
<span data-ls-if="{{execution.status}} === 'waiting' || {{execution.status}} === 'processing'">-</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td data-title="">
|
||||||
<div data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-title="">
|
<div data-ls-if="{{execution.status}} === 'completed' || {{execution.status}} === 'failed'" data-title="">
|
||||||
|
|
||||||
<button class="desktops-only pull-end link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
<button class="desktops-only pull-end link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
||||||
<button class="desktops-only pull-end link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
<button class="desktops-only pull-end link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
||||||
|
|
||||||
<button class="phones-only tablets-only link margin-start text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
<button class="phones-only-inline tablets-only-inline link margin-end-small" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
||||||
<button class="phones-only tablets-only link margin-start" data-ls-ui-trigger="execution-stdout-{{execution.$id}}">Output</button>
|
<button class="phones-only-inline tablets-only-inline link text-danger" data-ls-ui-trigger="execution-stderr-{{execution.$id}}">Errors</button>
|
||||||
|
|
||||||
<div data-ui-modal class="modal width-large box close" data-button-alias="none" data-open-event="execution-stdout-{{execution.$id}}">
|
<div data-ui-modal class="modal width-large box close" data-button-alias="none" data-open-event="execution-stdout-{{execution.$id}}">
|
||||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||||
|
|
||||||
<h1>STDOUT</h1>
|
<h1>STDOUT</h1>
|
||||||
|
|
||||||
<div class="margin-bottom">
|
<div class="margin-bottom ide" data-ls-if="({{execution.stdout.length}})">
|
||||||
<input type="hidden" data-ls-bind="{{execution.stdout}}" data-forms-code />
|
<pre data-ls-bind="{{execution.stdout}}"></pre>
|
||||||
|
<!-- <input type="hidden" data-ls-bind="{{execution.stdout}}" data-forms-code="bash" /> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="margin-bottom" data-ls-if="(!{{execution.stdout.length}})">
|
||||||
|
<p>No output was logged.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-ui-modal class="modal width-large box close" data-button-alias="none" data-open-event="execution-stderr-{{execution.$id}}">
|
<div data-ui-modal class="modal width-large box close" data-button-alias="none" data-open-event="execution-stderr-{{execution.$id}}">
|
||||||
|
@ -327,8 +400,13 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
|
|
||||||
<h1>STDERR</h1>
|
<h1>STDERR</h1>
|
||||||
|
|
||||||
<div class="margin-bottom">
|
<div class="margin-bottom ide" data-ls-if="({{execution.stderr.length}})">
|
||||||
<input type="hidden" data-ls-bind="{{execution.stderr}}" data-forms-code />
|
<pre data-ls-bind="{{execution.stderr}}"></pre>
|
||||||
|
<!-- <input type="hidden" data-ls-bind="{{execution.stderr}}" data-forms-code="bash" /> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="margin-bottom" data-ls-if="(!{{execution.stderr.length}})">
|
||||||
|
<p>No errors were logged.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -412,11 +490,11 @@ $timeout = $this->getParam('timeout', 900);
|
||||||
<div class="text-size-small text-fade margin-bottom margin-top-negative-small">Max value is <?php echo $this->escape(number_format($timeout)); ?> seconds (<?php echo $this->escape((int) ($timeout / 60)); ?> minutes)</div>
|
<div class="text-size-small text-fade margin-bottom margin-top-negative-small">Max value is <?php echo $this->escape(number_format($timeout)); ?> seconds (<?php echo $this->escape((int) ($timeout / 60)); ?> minutes)</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="margin-bottom">
|
<section class="margin-bottom" data-forms-select-all>
|
||||||
<label for="events" class="margin-bottom">Events <span class="tooltip small" data-tooltip="Choose which events should trigger this function."><i class="icon-info-circled"></i></span></label>
|
<label for="events" class="margin-bottom">Events <span class="tooltip small" data-tooltip="Choose which events should trigger this function."><i class="icon-info-circled"></i></span></label>
|
||||||
<div class="row responsive thin margin-top-small">
|
<div class="row responsive thin margin-top-small">
|
||||||
<?php foreach ($events as $i => $event) : ?>
|
<?php foreach ($events as $i => $event) : ?>
|
||||||
<div class="col span-6 text-one-liner margin-bottom text-height-large" title="<?php echo $event; ?>">
|
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
|
||||||
<input type="checkbox" name="events" data-ls-bind="{{project-function.events}}" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
<input type="checkbox" name="events" data-ls-bind="{{project-function.events}}" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php if (($i + 1) % 2 === 0) : ?>
|
<?php if (($i + 1) % 2 === 0) : ?>
|
||||||
|
|
|
@ -47,8 +47,7 @@ $environments = $this->getParam('environments', []);
|
||||||
|
|
||||||
<span data-ls-bind="{{function.name}}"></span>
|
<span data-ls-bind="{{function.name}}"></span>
|
||||||
|
|
||||||
<div class="text-fade" data-ls-if="({{function.events.length}})"><span data-ls-bind="{{function.events.length}}"></span> events assigned</div>
|
<p class="text-fade margin-bottom-no" data-ls-bind="{{function.env|envName}} {{function.env|envVersion}}"></p>
|
||||||
<div class="text-fade" data-ls-if="(!{{function.events.length}})"> </div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,69 +13,105 @@ $graph = $this->getParam('graph', false);
|
||||||
<span class="title" data-ls-bind="{{console-project.name}}"> </span>
|
<span class="title" data-ls-bind="{{console-project.name}}"> </span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<ul class="margin-top-negative-small margin-bottom clear">
|
<ul class="desktops-only margin-top-negative-small margin-bottom clear">
|
||||||
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/settings?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-cog"></i> Settings</a> </li>
|
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/settings?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-cog"></i> Settings</a> </li>
|
||||||
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/keys?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-key-inv"></i> API Keys</a> </li>
|
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/keys?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-key-inv"></i> API Keys</a> </li>
|
||||||
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/webhooks?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-link"></i> Webhooks</a> </li>
|
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/webhooks?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-link"></i> Webhooks</a> </li>
|
||||||
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/tasks?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-clock"></i> Tasks</a> </li>
|
<li class="pull-start margin-end margin-bottom-small"><a data-ls-attrs="href=/console/tasks?project={{router.params.project}}" class="link-animation-enabled"><i class="icon-clock"></i> Tasks</a> </li>
|
||||||
<!-- <li class="pull-end margin-start margin-bottom-small text-size-small margin-top-tiny"><a data-ls-attrs="href=/console/tasks?project={{router.params.project}}">May 2020 <i class="icon-down-dir"></i></a></li> -->
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div class="margin-bottom phones-only"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="zone xl margin-top-negative-xxl">
|
<div class="zone xxl margin-top-negative-xxxl">
|
||||||
<div class="box margin-bottom dashboard">
|
<div class="clear margin-bottom-small margin-top-negative">
|
||||||
<div
|
<div class="pull-end">
|
||||||
data-service="projects.getUsage"
|
|
||||||
data-event="load"
|
|
||||||
data-name="usage"
|
|
||||||
data-param-project-id="{{router.params.project}}"
|
|
||||||
data-param-range="last30">
|
|
||||||
|
|
||||||
<?php if (!$graph) : ?>
|
<form class="margin-start-small inline" data-ls-if="{{usage.range}} !== '24h'"
|
||||||
|
data-service="projects.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-project-id="{{router.params.project}}"
|
||||||
|
data-param-range="24h">
|
||||||
|
<button class="tick">24h</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button class="tick margin-start-small" data-ls-if="{{usage.range}} === '24h'" disabled>24h</button>
|
||||||
|
|
||||||
|
<form class="margin-start-small inline" data-ls-if="{{usage.range}} !== '30d'"
|
||||||
|
data-service="projects.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-project-id="{{router.params.project}}">
|
||||||
|
<button class="tick">30d</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button class="tick margin-start-small" data-ls-if="{{usage.range}} === '30d'" disabled>30d</button>
|
||||||
|
|
||||||
|
<form class="margin-start-small inline" data-ls-if="{{usage.range}} !== '90d'"
|
||||||
|
data-service="projects.getUsage"
|
||||||
|
data-event="submit"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-project-id="{{router.params.project}}"
|
||||||
|
data-param-range="90d">
|
||||||
|
<button class="tick">90d</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<button class="tick margin-start-small" data-ls-if="{{usage.range}} === '90d'" disabled>90d</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-service="projects.getUsage"
|
||||||
|
data-event="load"
|
||||||
|
data-name="usage"
|
||||||
|
data-param-project-id="{{router.params.project}}"
|
||||||
|
data-param-range="30d">
|
||||||
|
|
||||||
|
<?php if (!$graph) : ?>
|
||||||
|
<div class="box dashboard">
|
||||||
<div class="row responsive">
|
<div class="row responsive">
|
||||||
<div class="col span-9">
|
<div class="col span-9">
|
||||||
<div class="chart pull-end">
|
<div class="chart pull-end">
|
||||||
<div class="content" data-forms-chart="Requests=usage.requests.data"></div>
|
<input type="hidden" data-ls-bind="{{usage}}" data-forms-chart="Requests=usage.requests.data" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chart-metric">
|
<div class="chart-metric">
|
||||||
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.requests.total|statsTotal}}">N/A</span></div>
|
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.requests.total|statsTotal}}">N/A</span></div>
|
||||||
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests last 30 days"><i class="icon-info-circled"></i></span></div>
|
<div class="metric margin-bottom-small">Requests <span class="tooltip" data-tooltip="Total number of API requests last 30 days"><i class="icon-info-circled"></i></span></div>
|
||||||
<div class="range">Last 30 days</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-3">
|
<div class="col span-3">
|
||||||
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span></div>
|
<div class="value margin-bottom-small"><span class="sum" data-ls-bind="{{usage.network.total|humanFileSize}}" data-default="0">0</span></div>
|
||||||
<div class="metric margin-bottom-small">Bandwidth</div>
|
<div class="metric margin-bottom-small">Bandwidth</div>
|
||||||
<div class="range">Last 30 days</div>
|
|
||||||
<!-- <div class="margin-top dev-feature">
|
<!-- <div class="margin-top-large value small">
|
||||||
<a href="">Full Usage Report <i class="icon-right-open"></i></a>
|
<b class="text-size-small sum small" data-ls-bind="{{usage.functions.total|statsTotal}}" data-default="0"></b>
|
||||||
|
<br />
|
||||||
|
<b>Func. Executions</b>
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<hr />
|
<div class="box dashboard">
|
||||||
<?php endif; ?>
|
<div class="row responsive">
|
||||||
|
<div class="col span-3">
|
||||||
<div>
|
<div class="value"><span class="sum" data-ls-bind="{{usage.documents.total|statsTotal}}" data-default="0">0</span></div>
|
||||||
<div class="row responsive">
|
<div class="margin-top-small"><b class="text-size-small unit">Documents</b></div>
|
||||||
<div class="col span-3">
|
</div>
|
||||||
<div class="value"><span class="sum" data-ls-bind="{{usage.documents.total|statsTotal}}" data-default="0">0</span></div>
|
<div class="col span-3">
|
||||||
<div class="margin-top-small"><b class="text-size-small unit">Documents</b></div>
|
<div class="value"><span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span></div>
|
||||||
</div>
|
<div class="margin-top-small"><b class="text-size-small unit">Storage</b></div>
|
||||||
<div class="col span-3">
|
</div>
|
||||||
<div class="value"><span class="sum" data-ls-bind="{{usage.storage.total|humanFileSize}}" data-default="0">0</span></div>
|
<div class="col span-3">
|
||||||
<div class="margin-top-small"><b class="text-size-small unit">Storage</b></div>
|
<div class="value"><span class="sum" data-ls-bind="{{usage.users.total}}" data-default="0">0</span></div>
|
||||||
</div>
|
<div class="margin-top-small"><b class="text-size-small unit">Users</b></div>
|
||||||
<div class="col span-3">
|
</div>
|
||||||
<div class="value"><span class="sum" data-ls-bind="{{usage.users.total}}" data-default="0">0</span></div>
|
<div class="col span-3">
|
||||||
<div class="margin-top-small"><b class="text-size-small unit">Users</b></div>
|
<div class="value"><span class="sum" data-ls-bind="{{usage.tasks.total}}" data-default="0">0</span></div>
|
||||||
</div>
|
<div class="margin-top-small"><b class="text-size-small unit">Tasks</b></div>
|
||||||
<div class="col span-3">
|
|
||||||
<div class="value"><span class="sum" data-ls-bind="{{usage.tasks.total}}" data-default="0">0</span></div>
|
|
||||||
<div class="margin-top-small"><b class="text-size-small unit">Tasks</b></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -122,22 +158,22 @@ $graph = $this->getParam('graph', false);
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="pull-start margin-end avatar-container">
|
<div class="pull-start margin-end avatar-container">
|
||||||
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar" loading="lazy" width="60" height="60" />
|
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Platform Logo" class="avatar" loading="lazy" width="60" height="60" />
|
||||||
|
|
||||||
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
|
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
|
||||||
<img src="" data-ls-attrs="src=/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xs" loading="lazy" width="30" height="30" />
|
<img src="" data-ls-attrs="src=/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
|
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
|
||||||
<img src="" data-ls-attrs="src=/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xs" loading="lazy" width="30" height="30" />
|
<img src="" data-ls-attrs="src=/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Logo" class="avatar xs" loading="lazy" width="30" height="30" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span data-ls-bind="{{platform.name}}"></span>
|
<span class="text-one-liner" data-ls-bind="{{platform.name}}"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="margin-bottom-no"><small data-ls-bind="{{platform.hostname}}{{platform.key}}"></small></p>
|
<p class="margin-bottom-no"><small data-ls-bind="{{platform.hostname}}{{platform.key}}"></small></p>
|
||||||
|
|
||||||
<div class="phones-only-inline tablets-only-inline margin-top-tiny">
|
<div class="phones-only-inline tablets-only-inline margin-top-small">
|
||||||
<button class="link" data-ls-ui-trigger="platform-update-{{platform.$id}}">Update</button>
|
<button class="link" data-ls-ui-trigger="platform-update-{{platform.$id}}">Update</button>
|
||||||
<button class="link danger" data-ls-ui-trigger="platform-delete-{{platform.$id}}">Delete</button>
|
<button class="link danger" data-ls-ui-trigger="platform-delete-{{platform.$id}}">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,14 +18,14 @@ $scopes = $this->getParam('scopes', []);
|
||||||
data-success="trigger"
|
data-success="trigger"
|
||||||
data-success-param-trigger-events="projects.listKeys">
|
data-success-param-trigger-events="projects.listKeys">
|
||||||
|
|
||||||
<div data-ls-if="0 == {{console-keys.length}} || undefined == {{console-keys.length}}" class="box margin-top margin-bottom">
|
<div data-ls-if="0 == {{console-keys.sum}} || undefined == {{console-keys.sum}}" class="box margin-top margin-bottom">
|
||||||
<h3 class="margin-bottom-small text-bold">No API Keys Found</h3>
|
<h3 class="margin-bottom-small text-bold">No API Keys Found</h3>
|
||||||
|
|
||||||
<p class="margin-bottom-no">You haven't created any API keys for your project yet.</p>
|
<p class="margin-bottom-no">You haven't created any API keys for your project yet.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box margin-bottom" data-ls-if="0 != {{console-keys.length}}">
|
<div class="box margin-bottom" data-ls-if="0 != {{console-keys.sum}}">
|
||||||
<ul data-ls-loop="console-keys" data-ls-as="key" class="list">
|
<ul data-ls-loop="console-keys.keys" data-ls-as="key" class="list">
|
||||||
<li class="clear">
|
<li class="clear">
|
||||||
<div data-ui-modal class="modal box close" data-button-alias="none" data-open-event="key-update-{{key.$id}}">
|
<div data-ui-modal class="modal box close" data-button-alias="none" data-open-event="key-update-{{key.$id}}">
|
||||||
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
|
||||||
|
@ -52,19 +52,21 @@ $scopes = $this->getParam('scopes', []);
|
||||||
<label data-ls-attrs="for=name-{{key.$id}}">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different API keys."><i class="icon-question"></i></span></label>
|
<label data-ls-attrs="for=name-{{key.$id}}">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different API keys."><i class="icon-question"></i></span></label>
|
||||||
<input type="text" class="full-width" data-ls-attrs="id=name-{{key.$id}}" name="name" required autocomplete="off" data-ls-bind="{{key.name}}" maxlength="128" />
|
<input type="text" class="full-width" data-ls-attrs="id=name-{{key.$id}}" name="name" required autocomplete="off" data-ls-bind="{{key.name}}" maxlength="128" />
|
||||||
|
|
||||||
<label data-ls-attrs="for=scopes-{{key.$id}}">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
<section data-forms-select-all>
|
||||||
<div class="row responsive thin">
|
<label data-ls-attrs="for=scopes-{{key.$id}}">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||||
<?php foreach ($scopes as $i => $scope) : ?>
|
<div class="row responsive thin">
|
||||||
<div class="col span-6 text-one-liner margin-bottom text-height-large" title="<?php echo $scope; ?>">
|
<?php foreach ($scopes as $i => $scope) : ?>
|
||||||
<input type="checkbox" name="scopes" data-ls-bind="{{key.scopes}}" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $scope; ?>">
|
||||||
</div>
|
<input type="checkbox" name="scopes" data-ls-bind="{{key.scopes}}" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
||||||
<?php if (($i + 1) % 2 === 0) : ?>
|
</div>
|
||||||
</div>
|
<?php if (($i + 1) % 2 === 0) : ?>
|
||||||
<div class="row responsive thin">
|
</div>
|
||||||
<?php endif; ?>
|
<div class="row responsive thin">
|
||||||
|
<?php endif; ?>
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<hr class="margin-top-no" />
|
<hr class="margin-top-no" />
|
||||||
|
|
||||||
|
@ -147,19 +149,21 @@ $scopes = $this->getParam('scopes', []);
|
||||||
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different API keys."><i class="icon-question"></i></span></label>
|
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different API keys."><i class="icon-question"></i></span></label>
|
||||||
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" maxlength="128" />
|
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" maxlength="128" />
|
||||||
|
|
||||||
<label for="scopes">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
<section data-forms-select-all>
|
||||||
<div class="row responsive thin">
|
<label for="scopes">Scopes (<a data-ls-attrs="href={{env.HOME}}/docs/keys" target="_blank" rel="noopener">Learn more</a>)</label>
|
||||||
<?php foreach ($scopes as $i => $scope) : ?>
|
<div class="row responsive thin">
|
||||||
<div class="col span-6 text-one-liner margin-bottom text-height-large" title="<?php echo $scope; ?>">
|
<?php foreach ($scopes as $i => $scope) : ?>
|
||||||
<input type="checkbox" name="scopes" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $scope; ?>">
|
||||||
</div>
|
<input type="checkbox" name="scopes" value="<?php echo $scope; ?>" /> <?php echo $scope; ?>
|
||||||
<?php if (($i + 1) % 2 === 0) : ?>
|
</div>
|
||||||
</div>
|
<?php if (($i + 1) % 2 === 0) : ?>
|
||||||
<div class="row responsive thin">
|
</div>
|
||||||
<?php endif; ?>
|
<div class="row responsive thin">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<hr class="margin-top-no" />
|
<hr class="margin-top-no" />
|
||||||
|
|
||||||
|
|
|
@ -218,13 +218,13 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
||||||
data-success="trigger"
|
data-success="trigger"
|
||||||
data-success-param-trigger-events="projects.listDomains">
|
data-success-param-trigger-events="projects.listDomains">
|
||||||
|
|
||||||
<div data-ls-if="0 == {{console-domains.length}} || undefined == {{console-domains.length}}" class="box margin-top margin-bottom">
|
<div data-ls-if="0 == {{console-domains.sum}} || undefined == {{console-domains.sum}}" class="box margin-top margin-bottom">
|
||||||
<h3 class="margin-bottom-small text-bold">No Custom Domains Added</h3>
|
<h3 class="margin-bottom-small text-bold">No Custom Domains Added</h3>
|
||||||
|
|
||||||
<p class="margin-bottom-no">You haven't created any custom domains for your project yet.</p>
|
<p class="margin-bottom-no">You haven't created any custom domains for your project yet.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box margin-bottom" data-ls-if="0 != {{console-domains.length}}">
|
<div class="box margin-bottom" data-ls-if="0 != {{console-domains.sum}}">
|
||||||
<table class="vertical">
|
<table class="vertical">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -235,7 +235,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false);
|
||||||
<th width="40"></th>
|
<th width="40"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-ls-loop="console-domains" data-ls-as="domain">
|
<tbody data-ls-loop="console-domains.domains" data-ls-as="domain">
|
||||||
<tr>
|
<tr>
|
||||||
<td data-title="Status">
|
<td data-title="Status">
|
||||||
<span class="text-size-small text-danger" data-ls-if="true !== {{domain.verification}}"><i class="icon-cancel-circled"></i> Unverified </span>
|
<span class="text-size-small text-danger" data-ls-if="true !== {{domain.verification}}"><i class="icon-cancel-circled"></i> Unverified </span>
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
data-success="trigger"
|
data-success="trigger"
|
||||||
data-success-param-trigger-events="projects.listTasks">
|
data-success-param-trigger-events="projects.listTasks">
|
||||||
|
|
||||||
<div data-ls-if="0 === {{console-tasks.length}} || undefined === {{console-tasks.length}}" class="box margin-top margin-bottom">
|
<div data-ls-if="0 === {{console-tasks.sum}} || undefined === {{console-tasks.sum}}" class="box margin-top margin-bottom">
|
||||||
<h3 class="margin-bottom-small text-bold">No Tasks Found</h3>
|
<h3 class="margin-bottom-small text-bold">No Tasks Found</h3>
|
||||||
|
|
||||||
<p class="margin-bottom-no">You haven't created any tasks for your project yet.</p>
|
<p class="margin-bottom-no">You haven't created any tasks for your project yet.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box y-scroll margin-bottom" data-ls-if="0 != {{console-tasks.length}}">
|
<div class="box y-scroll margin-bottom" data-ls-if="0 != {{console-tasks.sum}}">
|
||||||
<table class="full vertical">
|
<table class="full vertical">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<th width="140"></th>
|
<th width="140"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-ls-loop="console-tasks" data-ls-as="task" class="list">
|
<tbody data-ls-loop="console-tasks.tasks" data-ls-as="task" class="list">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="margin-bottom-tiny text-one-liner">
|
<div class="margin-bottom-tiny text-one-liner">
|
||||||
|
|
|
@ -183,13 +183,13 @@
|
||||||
data-param-user-id="{{router.params.id}}"
|
data-param-user-id="{{router.params.id}}"
|
||||||
data-event="load,users.update">
|
data-event="load,users.update">
|
||||||
|
|
||||||
<div data-ls-if="{{sessions.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
|
<div data-ls-if="{{sessions.sessions.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
|
||||||
No sessions available.
|
No sessions available.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-ls-if="{{sessions.length}} !== 0" style="display: none">
|
<div data-ls-if="{{sessions.sessions.length}} !== 0" style="display: none">
|
||||||
<div class="box margin-bottom">
|
<div class="box margin-bottom">
|
||||||
<ul data-ls-loop="sessions" data-ls-as="session" class="list">
|
<ul data-ls-loop="sessions.sessions" data-ls-as="session" class="list">
|
||||||
<li class="clear">
|
<li class="clear">
|
||||||
<form class="pull-end"
|
<form class="pull-end"
|
||||||
data-analytics-event="submit"
|
data-analytics-event="submit"
|
||||||
|
@ -209,13 +209,13 @@
|
||||||
<button class="danger">Logout</button>
|
<button class="danger">Logout</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.client.short_name|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.client.name}},alt={{session.client.name}}" class="avatar trans pull-start margin-end" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar trans pull-start margin-end" />
|
||||||
|
|
||||||
<span data-ls-if="({{session.client.name}})" data-ls-bind="{{session.client.name}}"></span> <span data-ls-if="(!{{session.client.name}})">Unknown</span> <span data-ls-bind="{{session.client.version}}"></span> on <span data-ls-bind="{{session.model}}"></span> <span data-ls-if="(!{{session.OS.name}})">Unknown</span> <span data-ls-if="({{session.OS.name}})" data-ls-bind="{{session.OS.name}}"></span> <span data-ls-bind="{{session.OS.version}}"></span>
|
<span data-ls-bind="{{session.clientName}}"></span> <span data-ls-bind="{{session.clientVersion}}"></span> on <span data-ls-bind="{{session.deviceModel}}"></span> <span data-ls-bind="{{session.osName}}"></span> <span data-ls-bind="{{session.osVersion}}"></span>
|
||||||
|
|
||||||
<div class="margin-top-small">
|
<div class="margin-top-small">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
|
||||||
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.geo.country}}"></small>
|
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.countryName}}"></small>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -264,18 +264,18 @@
|
||||||
<th width="90">IP</th>
|
<th width="90">IP</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-ls-loop="logs" data-ls-as="log">
|
<tbody data-ls-loop="logs.logs" data-ls-as="log">
|
||||||
<tr>
|
<tr>
|
||||||
<td data-title="Date: "><span data-ls-bind="{{log.time|dateTime}}"></span></td>
|
<td data-title="Date: "><span data-ls-bind="{{log.time|dateTime}}"></span></td>
|
||||||
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
|
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
|
||||||
<td data-title="Client: ">
|
<td data-title="Client: ">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="({{log.client.short_name}})" data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xxs inline margin-end-small" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="({{log.clientCode}})" data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.clientCode|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.clientName}},alt={{log.clientName}}" class="avatar xxs inline margin-end-small" />
|
||||||
<span data-ls-if="({{log.client.name}})" data-ls-bind="{{log.client.name}} {{log.client.version}} on {{log.model}} {{log.OS.name}} {{log.OS.version}}"></span>
|
<span data-ls-if="({{log.clientName}})" data-ls-bind="{{log.clientName}} {{log.clientVersion}} on {{log.model}} {{log.osName}} {{log.osVersion}}"></span>
|
||||||
<div data-ls-if="(!{{log.client.name}})" class="text-align-center text-fade">Unknown</div>
|
<div data-ls-if="(!{{log.clientName}})" class="text-align-center text-fade">Unknown</div>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="Location: ">
|
<td data-title="Location: ">
|
||||||
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
|
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{log.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{log.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
|
||||||
<span data-ls-bind="{{log.geo.country}}"></span>
|
<span data-ls-bind="{{log.countryName}}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
|
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -21,14 +21,14 @@ $events = array_keys($this->getParam('events', []));
|
||||||
data-success="trigger"
|
data-success="trigger"
|
||||||
data-success-param-trigger-events="projects.listWebhooks">
|
data-success-param-trigger-events="projects.listWebhooks">
|
||||||
|
|
||||||
<div data-ls-if="0 == {{console-webhooks.length}} || undefined == {{console-webhooks.length}}" class="box margin-top margin-bottom">
|
<div data-ls-if="0 == {{console-webhooks.sum}} || undefined == {{console-webhooks.sum}}" class="box margin-top margin-bottom">
|
||||||
<h3 class="margin-bottom-small text-bold">No Webhooks Found</h3>
|
<h3 class="margin-bottom-small text-bold">No Webhooks Found</h3>
|
||||||
|
|
||||||
<p class="margin-bottom-no">You haven't created any webhooks for your project yet.</p>
|
<p class="margin-bottom-no">You haven't created any webhooks for your project yet.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box margin-bottom" data-ls-if="0 != {{console-webhooks.length}}">
|
<div class="box margin-bottom" data-ls-if="0 != {{console-webhooks.sum}}">
|
||||||
<ul data-ls-loop="console-webhooks" data-ls-as="webhook" class="list">
|
<ul data-ls-loop="console-webhooks.webhooks" data-ls-as="webhook" class="list">
|
||||||
<li class="clear">
|
<li class="clear">
|
||||||
|
|
||||||
<div data-ui-modal class="modal close sticky-footer" data-button-text="Update" data-button-class="pull-end">
|
<div data-ui-modal class="modal close sticky-footer" data-button-text="Update" data-button-class="pull-end">
|
||||||
|
@ -56,19 +56,21 @@ $events = array_keys($this->getParam('events', []));
|
||||||
<label data-ls-attrs="for=name-{{webhook.$id}}">Name</label>
|
<label data-ls-attrs="for=name-{{webhook.$id}}">Name</label>
|
||||||
<input type="text" class="full-width" data-ls-attrs="id=name-{{webhook.$id}}" name="name" required autocomplete="off" data-ls-bind="{{webhook.name}}" maxlength="128" />
|
<input type="text" class="full-width" data-ls-attrs="id=name-{{webhook.$id}}" name="name" required autocomplete="off" data-ls-bind="{{webhook.name}}" maxlength="128" />
|
||||||
|
|
||||||
<label data-ls-attrs="for=events-{{webhook.$id}}">Events</label>
|
<section data-forms-select-all>
|
||||||
<div class="row responsive thin">
|
<label data-ls-attrs="for=events-{{webhook.$id}}">Events</label>
|
||||||
<?php foreach ($events as $i => $event) : ?>
|
<div class="row responsive thin">
|
||||||
<div class="col span-6 text-one-liner margin-bottom text-height-large" title="<?php echo $event; ?>">
|
<?php foreach ($events as $i => $event) : ?>
|
||||||
<input type="checkbox" name="events" data-ls-bind="{{webhook.events}}" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
|
||||||
</div>
|
<input type="checkbox" name="events" data-ls-bind="{{webhook.events}}" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
||||||
<?php if (($i + 1) % 2 === 0) : ?>
|
</div>
|
||||||
</div>
|
<?php if (($i + 1) % 2 === 0) : ?>
|
||||||
<div class="row responsive thin">
|
</div>
|
||||||
<?php endif; ?>
|
<div class="row responsive thin">
|
||||||
|
<?php endif; ?>
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
|
<label data-ls-attrs="for=url-{{webhook.$id}}">POST URL</label>
|
||||||
<input type="url" class="full-width" data-ls-attrs="id=url-{{webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{webhook.url}}" />
|
<input type="url" class="full-width" data-ls-attrs="id=url-{{webhook.$id}}" name="url" required autocomplete="off" placeholder="https://example.com/callback" data-ls-bind="{{webhook.url}}" />
|
||||||
|
@ -170,19 +172,21 @@ $events = array_keys($this->getParam('events', []));
|
||||||
<label for="name">Name</label>
|
<label for="name">Name</label>
|
||||||
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" maxlength="128" />
|
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" maxlength="128" />
|
||||||
|
|
||||||
<label for="events">Events</label>
|
<section data-forms-select-all>
|
||||||
<div class="row responsive thin">
|
<label for="events">Events</label>
|
||||||
<?php foreach ($events as $i => $event) : ?>
|
<div class="row responsive thin">
|
||||||
<div class="col span-6 text-one-liner margin-bottom text-height-large" title="<?php echo $event; ?>">
|
<?php foreach ($events as $i => $event) : ?>
|
||||||
<input type="checkbox" name="events" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
<div class="col span-6 text-one-liner margin-bottom text-height-large text-size-small" title="<?php echo $event; ?>">
|
||||||
</div>
|
<input type="checkbox" name="events" value="<?php echo $event; ?>" /> <?php echo $event; ?>
|
||||||
<?php if (($i + 1) % 2 === 0) : ?>
|
</div>
|
||||||
</div>
|
<?php if (($i + 1) % 2 === 0) : ?>
|
||||||
<div class="row responsive thin">
|
</div>
|
||||||
<?php endif; ?>
|
<div class="row responsive thin">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<label for="url">POST URL</label>
|
<label for="url">POST URL</label>
|
||||||
<input type="url" class="full-width" id="url" name="url" required autocomplete="off" placeholder="https://example.com/callback" />
|
<input type="url" class="full-width" id="url" name="url" required autocomplete="off" placeholder="https://example.com/callback" />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="zone large padding margin-top" id="message" style="display: none">
|
<div class="zone large padding margin-top" id="message" style="display: none">
|
||||||
<h1 class="margin-bottom">Missing Redirect URL</h1>
|
<h1 class="margin-bottom">Missing Redirect URL</h1>
|
||||||
<p>Your OAuth login flow is missing a redirect URL. Please check the
|
<p>Your OAuth login flow is missing a proper redirect URL. Please check the
|
||||||
<a href="https://<?php echo APP_DOMAIN; ?>/docs/client/account?sdk=web#createOAuth2Session">OAuth docs</a>
|
<a href="https://<?php echo APP_DOMAIN; ?>/docs/client/account?sdk=web#createOAuth2Session">OAuth docs</a>
|
||||||
and send request for new session with a valid callback URL.</p>
|
and send request for new session with a valid callback URL.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -55,6 +55,7 @@ const configApp = {
|
||||||
'public/scripts/views/forms/pell.js',
|
'public/scripts/views/forms/pell.js',
|
||||||
'public/scripts/views/forms/remove.js',
|
'public/scripts/views/forms/remove.js',
|
||||||
'public/scripts/views/forms/run.js',
|
'public/scripts/views/forms/run.js',
|
||||||
|
'public/scripts/views/forms/select-all.js',
|
||||||
'public/scripts/views/forms/switch.js',
|
'public/scripts/views/forms/switch.js',
|
||||||
'public/scripts/views/forms/tags.js',
|
'public/scripts/views/forms/tags.js',
|
||||||
'public/scripts/views/forms/text-count.js',
|
'public/scripts/views/forms/text-count.js',
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,14 @@ window.ls.router
|
||||||
template: "/auth/join?version=" + APP_ENV.CACHEBUSTER,
|
template: "/auth/join?version=" + APP_ENV.CACHEBUSTER,
|
||||||
scope: "home"
|
scope: "home"
|
||||||
})
|
})
|
||||||
|
.add("/auth/oauth2/success", {
|
||||||
|
template: "/auth/oauth2/success?version=" + APP_ENV.CACHEBUSTER,
|
||||||
|
scope: "home"
|
||||||
|
})
|
||||||
|
.add("/auth/oauth2/failure", {
|
||||||
|
template: "/auth/oauth2/failure?version=" + APP_ENV.CACHEBUSTER,
|
||||||
|
scope: "home"
|
||||||
|
})
|
||||||
.add("/console", {
|
.add("/console", {
|
||||||
template: "/console?version=" + APP_ENV.CACHEBUSTER,
|
template: "/console?version=" + APP_ENV.CACHEBUSTER,
|
||||||
scope: "console"
|
scope: "console"
|
||||||
|
|
|
@ -4,87 +4,110 @@
|
||||||
window.ls.container.get("view").add({
|
window.ls.container.get("view").add({
|
||||||
selector: "data-forms-chart",
|
selector: "data-forms-chart",
|
||||||
controller: function(element, container, date, document) {
|
controller: function(element, container, date, document) {
|
||||||
|
let wrapper = document.createElement("div");
|
||||||
let child = document.createElement("canvas");
|
let child = document.createElement("canvas");
|
||||||
let sources = element.getAttribute('data-forms-chart');
|
let sources = element.getAttribute('data-forms-chart');
|
||||||
let width = element.getAttribute('data-width') || 500;
|
let width = element.getAttribute('data-width') || 500;
|
||||||
let height = element.getAttribute('data-height') || 175;
|
let height = element.getAttribute('data-height') || 175;
|
||||||
let colors = ['#29b5d9' /* blue */, '#4eb55b' /* green */, '#fba233', /* orange */,];
|
let colors = (element.getAttribute('data-colors') || 'blue,green,orange,red').split(',');
|
||||||
|
let themes = {'blue': '#29b5d9', 'green': '#4eb55b', 'orange': '#fba233', 'red': '#dc3232',};
|
||||||
|
let range = {'24h': 'H:i', '7d': 'd F Y', '30d': 'd F Y', '90d': 'd F Y'}
|
||||||
|
|
||||||
|
element.parentNode.insertBefore(wrapper, element.nextSibling);
|
||||||
|
|
||||||
|
wrapper.classList.add('content');
|
||||||
|
|
||||||
child.width = width;
|
child.width = width;
|
||||||
child.height = height;
|
child.height = height;
|
||||||
|
|
||||||
let config = {
|
|
||||||
type: "line",
|
|
||||||
data: {
|
|
||||||
labels: [],
|
|
||||||
datasets: []
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
title: {
|
|
||||||
display: false,
|
|
||||||
text: "Stats"
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false
|
|
||||||
},
|
|
||||||
tooltips: {
|
|
||||||
mode: "index",
|
|
||||||
intersect: false,
|
|
||||||
caretPadding: 0
|
|
||||||
},
|
|
||||||
hover: {
|
|
||||||
mode: "nearest",
|
|
||||||
intersect: true
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
xAxes: [
|
|
||||||
{
|
|
||||||
display: false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
yAxes: [
|
|
||||||
{
|
|
||||||
display: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sources = sources.split(',');
|
sources = sources.split(',');
|
||||||
|
|
||||||
for (let i = 0; i < sources.length; i++) {
|
wrapper.appendChild(child);
|
||||||
let label = sources[i].substring(0, sources[i].indexOf('='));
|
|
||||||
let path = sources[i].substring(sources[i].indexOf('=') + 1);
|
|
||||||
let data = container.path(path);
|
|
||||||
|
|
||||||
config.data.labels[i] = label;
|
let chart = null;
|
||||||
config.data.datasets[i] = {};
|
|
||||||
config.data.datasets[i].label = label;
|
|
||||||
config.data.datasets[i].borderColor = colors[i];
|
|
||||||
config.data.datasets[i].backgroundColor = colors[i] + '36';
|
|
||||||
config.data.datasets[i].borderWidth = 2;
|
|
||||||
config.data.datasets[i].data = [0, 0, 0, 0, 0, 0, 0];
|
|
||||||
config.data.datasets[i].fill = true;
|
|
||||||
|
|
||||||
if(!data) {
|
let check = function() {
|
||||||
return;
|
|
||||||
|
let config = {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: []
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
title: {
|
||||||
|
display: false,
|
||||||
|
text: "Stats"
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
mode: "index",
|
||||||
|
intersect: false,
|
||||||
|
caretPadding: 0
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
mode: "nearest",
|
||||||
|
intersect: true
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let i = 0; i < sources.length; i++) {
|
||||||
|
let label = sources[i].substring(0, sources[i].indexOf('='));
|
||||||
|
let path = sources[i].substring(sources[i].indexOf('=') + 1);
|
||||||
|
let data = container.path(path);
|
||||||
|
let value = JSON.parse(element.value);
|
||||||
|
|
||||||
|
config.data.labels[i] = label;
|
||||||
|
config.data.datasets[i] = {};
|
||||||
|
config.data.datasets[i].label = label;
|
||||||
|
config.data.datasets[i].borderColor = themes[colors[i]];
|
||||||
|
config.data.datasets[i].backgroundColor = themes[colors[i]] + '36';
|
||||||
|
config.data.datasets[i].borderWidth = 2;
|
||||||
|
config.data.datasets[i].data = [0, 0, 0, 0, 0, 0, 0];
|
||||||
|
config.data.datasets[i].fill = true;
|
||||||
|
|
||||||
|
if(!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dateFormat = (value.range && range[value.range]) ? range[value.range] : 'd F Y';
|
||||||
|
|
||||||
|
for (let x = 0; x < data.length; x++) {
|
||||||
|
config.data.datasets[i].data[x] = data[x].value;
|
||||||
|
config.data.labels[x] = date.format(dateFormat, data[x].date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let x = 0; x < data.length; x++) {
|
if(chart) {
|
||||||
config.data.datasets[i].data[x] = data[x].value;
|
chart.destroy();
|
||||||
config.data.labels[x] = date.format("d F Y", data[x].date);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
chart = new Chart(child.getContext("2d"), config);
|
||||||
|
|
||||||
|
wrapper.dataset["canvas"] = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
element.innerHTML = "";
|
check();
|
||||||
|
|
||||||
element.appendChild(child);
|
element.addEventListener('change', check);
|
||||||
|
|
||||||
container.set("chart", new Chart(child.getContext("2d"), config), true);
|
|
||||||
|
|
||||||
element.dataset["canvas"] = true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})(window);
|
})(window);
|
||||||
|
|
51
public/scripts/views/forms/select-all.js
Normal file
51
public/scripts/views/forms/select-all.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
(function(window) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
window.ls.container.get("view").add({
|
||||||
|
selector: "data-forms-select-all",
|
||||||
|
controller: function(element) {
|
||||||
|
let select = document.createElement("button");
|
||||||
|
let unselect = document.createElement("button");
|
||||||
|
|
||||||
|
select.textContent = 'Select All';
|
||||||
|
unselect.textContent = 'Unselect All';
|
||||||
|
|
||||||
|
select.classList.add('link');
|
||||||
|
select.classList.add('margin-top-tiny');
|
||||||
|
select.classList.add('margin-start-small');
|
||||||
|
select.classList.add('text-size-small');
|
||||||
|
select.classList.add('pull-end');
|
||||||
|
unselect.classList.add('link');
|
||||||
|
unselect.classList.add('margin-top-tiny');
|
||||||
|
unselect.classList.add('margin-start-small');
|
||||||
|
unselect.classList.add('text-size-small');
|
||||||
|
unselect.classList.add('pull-end');
|
||||||
|
|
||||||
|
// select.disabled = true;
|
||||||
|
// unselect.disabled = true;
|
||||||
|
|
||||||
|
select.type = 'button';
|
||||||
|
unselect.type = 'button';
|
||||||
|
|
||||||
|
element.parentNode.insertBefore(select, element);
|
||||||
|
element.parentNode.insertBefore(unselect, element);
|
||||||
|
|
||||||
|
select.addEventListener('click', function () {
|
||||||
|
let checkboxes = document.querySelectorAll("input[type='checkbox']");
|
||||||
|
|
||||||
|
for(var i = 0; i < checkboxes.length; i++) {
|
||||||
|
checkboxes[i].checked = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
unselect.addEventListener('click', function () {
|
||||||
|
let checkboxes = document.querySelectorAll("input[type='checkbox']");
|
||||||
|
|
||||||
|
for(var i = 0; i < checkboxes.length; i++) {
|
||||||
|
checkboxes[i].checked = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(window);
|
|
@ -4,10 +4,10 @@
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
right: 0;
|
.func-end(0);
|
||||||
left: 0;
|
.func-start(0);
|
||||||
color: var(--config-color-normal);
|
color: var(--config-color-normal);
|
||||||
z-index: 1002;
|
z-index: 4;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
bottom: 15px;
|
bottom: 15px;
|
||||||
max-width: 560px;
|
max-width: 560px;
|
||||||
|
@ -34,42 +34,66 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
border-bottom: dotted 1px var(--config-color-normal);
|
||||||
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 22px;
|
line-height: 20px;
|
||||||
top: 8px;
|
top: 9px;
|
||||||
.func-start(8px);
|
.func-start(9px);
|
||||||
|
color: var(--config-color-background-dark);
|
||||||
|
background: var(--config-color-normal);
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.error {
|
&.error {
|
||||||
color: #ffffff;
|
color: #ffffff!important;
|
||||||
background: var(--config-color-danger);
|
background: var(--config-color-danger)!important;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #ffffff;
|
color: #ffffff!important;
|
||||||
border-bottom: dotted 1px #ffffff;
|
border-bottom: dotted 1px #ffffff!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--config-color-danger);
|
||||||
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
color: #ffffff;
|
color: #ffffff!important;
|
||||||
background: var(--config-color-success);
|
background: var(--config-color-success)!important;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border-bottom: dotted 1px #ffffff;
|
border-bottom: dotted 1px #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--config-color-success);
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.warning {
|
&.warning {
|
||||||
color: #ffffff;
|
color: var(--config-color-normal)!important;
|
||||||
background: var(--config-color-success);
|
background: var(--config-color-warning)!important;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
color: var(--config-color-normal)!important;
|
||||||
|
border-bottom: dotted 1px var(--config-color-normal)!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border-bottom: dotted 1px #ffffff;
|
background: var(--config-color-normal)!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +115,12 @@
|
||||||
a {
|
a {
|
||||||
color: var(--config-color-focus);
|
color: var(--config-color-focus);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
border-bottom: dotted 1px var(--config-color-focus);
|
border-bottom: dotted 1px var(--config-color-focus)!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--config-color-focus-fade)!important;
|
||||||
|
background: var(--config-color-focus)!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +129,7 @@
|
||||||
top: auto;
|
top: auto;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
.func-start(0);
|
||||||
|
|
||||||
li {
|
li {
|
||||||
margin: 5px 0 0 0;
|
margin: 5px 0 0 0;
|
||||||
|
@ -110,4 +140,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-nav {
|
||||||
|
.alerts {
|
||||||
|
ul {
|
||||||
|
.func-start(220px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media @phones, @tablets {
|
||||||
|
ul {
|
||||||
|
.func-start(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -11,8 +11,8 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: #0c0c0c;
|
background: #0c0c0c;
|
||||||
opacity: 0.5;
|
opacity: 0.75;
|
||||||
z-index: 4;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,12 @@ input:-moz-placeholder {
|
||||||
text-align: @config-start;
|
text-align: @config-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
&.inline {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input, textarea {
|
input, textarea {
|
||||||
background: var(--config-color-background-input);
|
background: var(--config-color-background-input);
|
||||||
}
|
}
|
||||||
|
@ -98,6 +104,22 @@ button,
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.tick {
|
||||||
|
background: var(--config-color-fade-light);
|
||||||
|
color: var(--config-color-dark);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 0 10px;
|
||||||
|
line-height: 30px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background: var(--config-color-dark);
|
||||||
|
color: var(--config-color-fade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.round {
|
&.round {
|
||||||
width: 52px;
|
width: 52px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
|
@ -143,6 +143,10 @@
|
||||||
margin-top: -100px!important;
|
margin-top: -100px!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.margin-top-negative-xxxl {
|
||||||
|
margin-top: -150px!important;
|
||||||
|
}
|
||||||
|
|
||||||
.margin-bottom-xxl {
|
.margin-bottom-xxl {
|
||||||
margin-bottom: 140px!important;
|
margin-bottom: 140px!important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,10 +408,10 @@
|
||||||
|
|
||||||
.dashboard {
|
.dashboard {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-height: 95px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
@ -422,7 +422,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: 20px -20px;
|
margin: 20px -25px;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: var(--config-console-background);
|
background: var(--config-console-background);
|
||||||
|
|
||||||
|
@ -452,7 +452,6 @@
|
||||||
display: block;
|
display: block;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
background: var(--config-console-background);
|
background: var(--config-console-background);
|
||||||
height: ~"calc(100% + 110px)";
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -20px;
|
top: -20px;
|
||||||
bottom: -20px;
|
bottom: -20px;
|
||||||
|
@ -473,11 +472,20 @@
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
line-height: 45px;
|
line-height: 45px;
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
line-height: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
.sum {
|
.sum {
|
||||||
font-size: 45px;
|
font-size: 45px;
|
||||||
line-height: 45px;
|
line-height: 45px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
font-size: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,7 +586,7 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(1) {
|
&:nth-child(1), &.blue {
|
||||||
color: #29b5d9;
|
color: #29b5d9;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
@ -586,7 +594,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2), &.green {
|
||||||
color: #4eb55b;
|
color: #4eb55b;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
@ -594,13 +602,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(3) {
|
&:nth-child(3), &.orange {
|
||||||
color: #ec9323;
|
color: #ec9323;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
background: #ec9323;
|
background: #ec9323;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:nth-child(4), &.red {
|
||||||
|
color: #dc3232;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
background: #dc3232;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ abstract class Scope extends TestCase
|
||||||
protected function getLastEmail():array
|
protected function getLastEmail():array
|
||||||
{
|
{
|
||||||
sleep(10);
|
sleep(10);
|
||||||
|
|
||||||
$emails = json_decode(file_get_contents('http://maildev/email'), true);
|
$emails = json_decode(file_get_contents('http://maildev/email'), true);
|
||||||
|
|
||||||
if ($emails && is_array($emails)) {
|
if ($emails && is_array($emails)) {
|
||||||
|
@ -43,6 +44,16 @@ abstract class Scope extends TestCase
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getLastRequest():array
|
||||||
|
{
|
||||||
|
sleep(10);
|
||||||
|
|
||||||
|
$resquest = json_decode(file_get_contents('http://request-catcher:5000/__last_request__'), true);
|
||||||
|
$resquest['data'] = json_decode($resquest['data'], true);
|
||||||
|
|
||||||
|
return $resquest;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -235,31 +235,28 @@ trait AccountBase
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertCount(1, $response['body']);
|
$this->assertCount(2, $response['body']);
|
||||||
$this->assertEquals($sessionId, $response['body'][0]['$id']);
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
$this->assertEquals($sessionId, $response['body']['sessions'][0]['$id']);
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['OS']);
|
$this->assertEquals('Windows', $response['body']['sessions'][0]['osName']);
|
||||||
$this->assertEquals('Windows', $response['body'][0]['OS']['name']);
|
$this->assertEquals('WIN', $response['body']['sessions'][0]['osCode']);
|
||||||
$this->assertEquals('WIN', $response['body'][0]['OS']['short_name']);
|
$this->assertEquals('10', $response['body']['sessions'][0]['osVersion']);
|
||||||
$this->assertEquals('10', $response['body'][0]['OS']['version']);
|
|
||||||
$this->assertEquals('x64', $response['body'][0]['OS']['platform']);
|
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['client']);
|
$this->assertEquals('browser', $response['body']['sessions'][0]['clientType']);
|
||||||
$this->assertEquals('browser', $response['body'][0]['client']['type']);
|
$this->assertEquals('Chrome', $response['body']['sessions'][0]['clientName']);
|
||||||
$this->assertEquals('Chrome', $response['body'][0]['client']['name']);
|
$this->assertEquals('CH', $response['body']['sessions'][0]['clientCode']);
|
||||||
$this->assertEquals('CH', $response['body'][0]['client']['short_name']); // FIXME (v1) key name should be camelcase
|
$this->assertEquals('70.0', $response['body']['sessions'][0]['clientVersion']);
|
||||||
$this->assertEquals('70.0', $response['body'][0]['client']['version']);
|
$this->assertEquals('Blink', $response['body']['sessions'][0]['clientEngine']);
|
||||||
$this->assertEquals('Blink', $response['body'][0]['client']['engine']);
|
$this->assertEquals('desktop', $response['body']['sessions'][0]['deviceName']);
|
||||||
$this->assertEquals(0, $response['body'][0]['device']);
|
$this->assertEquals('', $response['body']['sessions'][0]['deviceBrand']);
|
||||||
$this->assertEquals('', $response['body'][0]['brand']);
|
$this->assertEquals('', $response['body']['sessions'][0]['deviceModel']);
|
||||||
$this->assertEquals('', $response['body'][0]['model']);
|
$this->assertEquals($response['body']['sessions'][0]['ip'], filter_var($response['body']['sessions'][0]['ip'], FILTER_VALIDATE_IP));
|
||||||
$this->assertEquals($response['body'][0]['ip'], filter_var($response['body'][0]['ip'], FILTER_VALIDATE_IP));
|
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['geo']);
|
$this->assertEquals('--', $response['body']['sessions'][0]['countryCode']);
|
||||||
$this->assertEquals('--', $response['body'][0]['geo']['isoCode']);
|
$this->assertEquals('Unknown', $response['body']['sessions'][0]['countryName']);
|
||||||
$this->assertEquals('Unknown', $response['body'][0]['geo']['country']);
|
|
||||||
|
|
||||||
$this->assertEquals(true, $response['body'][0]['current']);
|
$this->assertEquals(true, $response['body']['sessions'][0]['current']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -294,59 +291,53 @@ trait AccountBase
|
||||||
]));
|
]));
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']['logs']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']['logs']);
|
||||||
$this->assertCount(2, $response['body']);
|
$this->assertCount(2, $response['body']['logs']);
|
||||||
|
|
||||||
$this->assertEquals('account.sessions.create', $response['body'][0]['event']);
|
$this->assertEquals('account.sessions.create', $response['body']['logs'][0]['event']);
|
||||||
$this->assertEquals($response['body'][0]['ip'], filter_var($response['body'][0]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP));
|
||||||
$this->assertIsNumeric($response['body'][0]['time']);
|
$this->assertIsNumeric($response['body']['logs'][0]['time']);
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['OS']);
|
$this->assertEquals('Windows', $response['body']['logs'][0]['osName']);
|
||||||
$this->assertEquals('Windows', $response['body'][0]['OS']['name']);
|
$this->assertEquals('WIN', $response['body']['logs'][0]['osCode']);
|
||||||
$this->assertEquals('WIN', $response['body'][0]['OS']['short_name']);
|
$this->assertEquals('10', $response['body']['logs'][0]['osVersion']);
|
||||||
$this->assertEquals('10', $response['body'][0]['OS']['version']);
|
|
||||||
$this->assertEquals('x64', $response['body'][0]['OS']['platform']);
|
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['client']);
|
$this->assertEquals('browser', $response['body']['logs'][0]['clientType']);
|
||||||
$this->assertEquals('browser', $response['body'][0]['client']['type']);
|
$this->assertEquals('Chrome', $response['body']['logs'][0]['clientName']);
|
||||||
$this->assertEquals('Chrome', $response['body'][0]['client']['name']);
|
$this->assertEquals('CH', $response['body']['logs'][0]['clientCode']); // FIXME (v1) key name should be camelcase
|
||||||
$this->assertEquals('CH', $response['body'][0]['client']['short_name']); // FIXME (v1) key name should be camelcase
|
$this->assertEquals('70.0', $response['body']['logs'][0]['clientVersion']);
|
||||||
$this->assertEquals('70.0', $response['body'][0]['client']['version']);
|
$this->assertEquals('Blink', $response['body']['logs'][0]['clientEngine']);
|
||||||
$this->assertEquals('Blink', $response['body'][0]['client']['engine']);
|
|
||||||
$this->assertEquals(0, $response['body'][0]['device']);
|
$this->assertEquals('desktop', $response['body']['logs'][0]['deviceName']);
|
||||||
$this->assertEquals('', $response['body'][0]['brand']);
|
$this->assertEquals('', $response['body']['logs'][0]['deviceBrand']);
|
||||||
$this->assertEquals('', $response['body'][0]['model']);
|
$this->assertEquals('', $response['body']['logs'][0]['deviceModel']);
|
||||||
$this->assertEquals($response['body'][0]['ip'], filter_var($response['body'][0]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][0]['ip'], filter_var($response['body']['logs'][0]['ip'], FILTER_VALIDATE_IP));
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][0]['geo']);
|
$this->assertEquals('--', $response['body']['logs'][0]['countryCode']);
|
||||||
$this->assertEquals('--', $response['body'][0]['geo']['isoCode']);
|
$this->assertEquals('Unknown', $response['body']['logs'][0]['countryName']);
|
||||||
$this->assertEquals('Unknown', $response['body'][0]['geo']['country']);
|
|
||||||
|
|
||||||
$this->assertEquals('account.create', $response['body'][1]['event']);
|
$this->assertEquals('account.create', $response['body']['logs'][1]['event']);
|
||||||
$this->assertEquals($response['body'][1]['ip'], filter_var($response['body'][0]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP));
|
||||||
$this->assertIsNumeric($response['body'][1]['time']);
|
$this->assertIsNumeric($response['body']['logs'][1]['time']);
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][1]['OS']);
|
$this->assertEquals('Windows', $response['body']['logs'][1]['osName']);
|
||||||
$this->assertEquals('Windows', $response['body'][1]['OS']['name']);
|
$this->assertEquals('WIN', $response['body']['logs'][1]['osCode']);
|
||||||
$this->assertEquals('WIN', $response['body'][1]['OS']['short_name']);
|
$this->assertEquals('10', $response['body']['logs'][1]['osVersion']);
|
||||||
$this->assertEquals('10', $response['body'][1]['OS']['version']);
|
|
||||||
$this->assertEquals('x64', $response['body'][1]['OS']['platform']);
|
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][1]['client']);
|
$this->assertEquals('browser', $response['body']['logs'][1]['clientType']);
|
||||||
$this->assertEquals('browser', $response['body'][1]['client']['type']);
|
$this->assertEquals('Chrome', $response['body']['logs'][1]['clientName']);
|
||||||
$this->assertEquals('Chrome', $response['body'][1]['client']['name']);
|
$this->assertEquals('CH', $response['body']['logs'][1]['clientCode']); // FIXME (v1) key name should be camelcase
|
||||||
$this->assertEquals('CH', $response['body'][1]['client']['short_name']); // FIXME (v1) key name should be camelcase
|
$this->assertEquals('70.0', $response['body']['logs'][1]['clientVersion']);
|
||||||
$this->assertEquals('70.0', $response['body'][1]['client']['version']);
|
$this->assertEquals('Blink', $response['body']['logs'][1]['clientEngine']);
|
||||||
$this->assertEquals('Blink', $response['body'][1]['client']['engine']);
|
|
||||||
$this->assertEquals(0, $response['body'][1]['device']);
|
$this->assertEquals('desktop', $response['body']['logs'][1]['deviceName']);
|
||||||
$this->assertEquals('', $response['body'][1]['brand']);
|
$this->assertEquals('', $response['body']['logs'][1]['deviceBrand']);
|
||||||
$this->assertEquals('', $response['body'][1]['model']);
|
$this->assertEquals('', $response['body']['logs'][1]['deviceModel']);
|
||||||
$this->assertEquals($response['body'][1]['ip'], filter_var($response['body'][0]['ip'], FILTER_VALIDATE_IP));
|
$this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP));
|
||||||
|
|
||||||
$this->assertIsArray($response['body'][1]['geo']);
|
$this->assertEquals('--', $response['body']['logs'][1]['countryCode']);
|
||||||
$this->assertEquals('--', $response['body'][1]['geo']['isoCode']);
|
$this->assertEquals('Unknown', $response['body']['logs'][1]['countryName']);
|
||||||
$this->assertEquals('Unknown', $response['body'][1]['geo']['country']);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -573,8 +564,8 @@ trait AccountBase
|
||||||
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
|
'cookie' => 'a_session_'.$this->getProject()['$id'].'=' . $session,
|
||||||
]), [
|
]), [
|
||||||
'prefs' => [
|
'prefs' => [
|
||||||
'key1' => 'value1',
|
'prefKey1' => 'prefValue1',
|
||||||
'key2' => 'value2',
|
'prefKey2' => 'prefValue2',
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -582,8 +573,8 @@ trait AccountBase
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertNotEmpty($response['body']);
|
$this->assertNotEmpty($response['body']);
|
||||||
$this->assertEquals('value1', $response['body']['key1']);
|
$this->assertEquals('prefValue1', $response['body']['prefKey1']);
|
||||||
$this->assertEquals('value2', $response['body']['key2']);
|
$this->assertEquals('prefValue2', $response['body']['prefKey2']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
|
|
@ -24,9 +24,9 @@ class FunctionsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'name' => 'Test',
|
'name' => 'Test',
|
||||||
'vars' => [
|
'vars' => [
|
||||||
'key1' => 'value1',
|
'funcKey1' => 'funcValue1',
|
||||||
'key2' => 'value2',
|
'funcKey2' => 'funcValue2',
|
||||||
'key3' => 'value3',
|
'funcKey3' => 'funcValue3',
|
||||||
],
|
],
|
||||||
'events' => [
|
'events' => [
|
||||||
'account.create',
|
'account.create',
|
||||||
|
|
|
@ -24,11 +24,11 @@ class FunctionsConsoleServerTest extends Scope
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'name' => 'Test',
|
'name' => 'Test',
|
||||||
'env' => 'node-14',
|
'env' => 'php-7.4',
|
||||||
'vars' => [
|
'vars' => [
|
||||||
'key1' => 'value1',
|
'funcKey1' => 'funcValue1',
|
||||||
'key2' => 'value2',
|
'funcKey2' => 'funcValue2',
|
||||||
'key3' => 'value3',
|
'funcKey3' => 'funcValue3',
|
||||||
],
|
],
|
||||||
'events' => [
|
'events' => [
|
||||||
'account.create',
|
'account.create',
|
||||||
|
@ -43,14 +43,14 @@ class FunctionsConsoleServerTest extends Scope
|
||||||
$this->assertEquals(201, $response1['headers']['status-code']);
|
$this->assertEquals(201, $response1['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response1['body']['$id']);
|
$this->assertNotEmpty($response1['body']['$id']);
|
||||||
$this->assertEquals('Test', $response1['body']['name']);
|
$this->assertEquals('Test', $response1['body']['name']);
|
||||||
$this->assertEquals('node-14', $response1['body']['env']);
|
$this->assertEquals('php-7.4', $response1['body']['env']);
|
||||||
$this->assertIsInt($response1['body']['dateCreated']);
|
$this->assertIsInt($response1['body']['dateCreated']);
|
||||||
$this->assertIsInt($response1['body']['dateUpdated']);
|
$this->assertIsInt($response1['body']['dateUpdated']);
|
||||||
$this->assertEquals('', $response1['body']['tag']);
|
$this->assertEquals('', $response1['body']['tag']);
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'key1' => 'value1',
|
'funcKey1' => 'funcValue1',
|
||||||
'key2' => 'value2',
|
'funcKey2' => 'funcValue2',
|
||||||
'key3' => 'value3',
|
'funcKey3' => 'funcValue3',
|
||||||
], $response1['body']['vars']);
|
], $response1['body']['vars']);
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'account.create',
|
'account.create',
|
||||||
|
@ -192,8 +192,7 @@ class FunctionsConsoleServerTest extends Scope
|
||||||
$this->assertNotEmpty($tag['body']['$id']);
|
$this->assertNotEmpty($tag['body']['$id']);
|
||||||
$this->assertIsInt($tag['body']['dateCreated']);
|
$this->assertIsInt($tag['body']['dateCreated']);
|
||||||
$this->assertEquals('php function.php', $tag['body']['command']);
|
$this->assertEquals('php function.php', $tag['body']['command']);
|
||||||
$this->assertStringStartsWith('/storage/functions/app-', $tag['body']['codePath']);
|
$this->assertEquals(751, $tag['body']['size']);
|
||||||
$this->assertEquals(751, $tag['body']['codeSize']);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -265,7 +264,7 @@ class FunctionsConsoleServerTest extends Scope
|
||||||
], $this->getHeaders()));
|
], $this->getHeaders()));
|
||||||
|
|
||||||
$this->assertEquals(200, $function['headers']['status-code']);
|
$this->assertEquals(200, $function['headers']['status-code']);
|
||||||
$this->assertEquals(751, $function['body']['codeSize']);
|
$this->assertEquals(751, $function['body']['size']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -308,7 +307,32 @@ class FunctionsConsoleServerTest extends Scope
|
||||||
$this->assertEquals('', $execution['body']['stdout']);
|
$this->assertEquals('', $execution['body']['stdout']);
|
||||||
$this->assertEquals('', $execution['body']['stderr']);
|
$this->assertEquals('', $execution['body']['stderr']);
|
||||||
$this->assertEquals(0, $execution['body']['time']);
|
$this->assertEquals(0, $execution['body']['time']);
|
||||||
|
|
||||||
|
// sleep(75);
|
||||||
|
|
||||||
|
// $execution = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$executionId, array_merge([
|
||||||
|
// 'content-type' => 'application/json',
|
||||||
|
// 'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
// ], $this->getHeaders()));
|
||||||
|
|
||||||
|
// $this->assertNotEmpty($execution['body']['$id']);
|
||||||
|
// $this->assertNotEmpty($execution['body']['functionId']);
|
||||||
|
// $this->assertIsInt($execution['body']['dateCreated']);
|
||||||
|
// $this->assertEquals($data['functionId'], $execution['body']['functionId']);
|
||||||
|
// $this->assertEquals('completed', $execution['body']['status']);
|
||||||
|
// $this->assertEquals(0, $execution['body']['exitCode']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_ID', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_NAME', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_TAG', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_TRIGGER', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_ENV_NAME', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('APPWRITE_FUNCTION_ENV_VERSION', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString('Hello World', $execution['body']['stdout']);
|
||||||
|
// $this->assertStringContainsString($execution['body']['functionId'], $execution['body']['stdout']);
|
||||||
|
// $this->assertEquals('', $execution['body']['stderr']);
|
||||||
|
// $this->assertGreaterThan(0.100, $execution['body']['time']);
|
||||||
|
// $this->assertLessThan(0.500, $execution['body']['time']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Tests\E2E\Services\Locale;
|
namespace Tests\E2E\Services\Locale;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Tests\E2E\Client;
|
use Tests\E2E\Client;
|
||||||
|
|
||||||
trait LocaleBase
|
trait LocaleBase
|
||||||
|
@ -44,8 +45,9 @@ trait LocaleBase
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertCount(194, $response['body']);
|
$this->assertEquals(194, $response['body']['sum']);
|
||||||
$this->assertEquals($response['body']['US'], 'United States');
|
$this->assertEquals($response['body']['countries'][0]['name'], 'Afghanistan');
|
||||||
|
$this->assertEquals($response['body']['countries'][0]['code'], 'AF');
|
||||||
|
|
||||||
// Test locale code change to ES
|
// Test locale code change to ES
|
||||||
|
|
||||||
|
@ -57,8 +59,9 @@ trait LocaleBase
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertCount(194, $response['body']);
|
$this->assertEquals(194, $response['body']['sum']);
|
||||||
$this->assertEquals($response['body']['US'], 'Estados Unidos');
|
$this->assertEquals($response['body']['countries'][0]['name'], 'Afganistán');
|
||||||
|
$this->assertEquals($response['body']['countries'][0]['code'], 'AF');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -78,9 +81,10 @@ trait LocaleBase
|
||||||
], $this->getHeaders()));
|
], $this->getHeaders()));
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertEquals(27, $response['body']['sum']);
|
||||||
$this->assertCount(27, $response['body']);
|
$this->assertIsArray($response['body']['countries']);
|
||||||
$this->assertEquals($response['body']['DE'], 'Germany');
|
$this->assertEquals($response['body']['countries'][0]['name'], 'Austria');
|
||||||
|
$this->assertEquals($response['body']['countries'][0]['code'], 'AT');
|
||||||
|
|
||||||
// Test locale code change to ES
|
// Test locale code change to ES
|
||||||
|
|
||||||
|
@ -91,9 +95,11 @@ trait LocaleBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertEquals(27, $response['body']['sum']);
|
||||||
$this->assertCount(27, $response['body']);
|
$this->assertIsArray($response['body']['countries']);
|
||||||
$this->assertEquals($response['body']['DE'], 'Alemania');
|
$this->assertEquals($response['body']['countries'][0]['name'], 'Austria');
|
||||||
|
$this->assertEquals($response['body']['countries'][0]['code'], 'AT');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -114,9 +120,11 @@ trait LocaleBase
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertCount(194, $response['body']);
|
$this->assertEquals(194, $response['body']['sum']);
|
||||||
$this->assertEquals($response['body']['US'], '+1');
|
$this->assertIsArray($response['body']['phones']);
|
||||||
$this->assertEquals($response['body']['IL'], '+972');
|
$this->assertEquals($response['body']['phones'][0]['code'], '+1');
|
||||||
|
$this->assertEquals($response['body']['phones'][0]['countryName'], 'United States');
|
||||||
|
$this->assertEquals($response['body']['phones'][0]['countryCode'], 'US');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -136,9 +144,10 @@ trait LocaleBase
|
||||||
], $this->getHeaders()));
|
], $this->getHeaders()));
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertEquals(7, $response['body']['sum']);
|
||||||
$this->assertCount(7, $response['body']);
|
$this->assertIsArray($response['body']['continents']);
|
||||||
$this->assertEquals($response['body']['NA'], 'North America');
|
$this->assertEquals($response['body']['continents'][0]['code'], 'AF');
|
||||||
|
$this->assertEquals($response['body']['continents'][0]['name'], 'Africa');
|
||||||
|
|
||||||
// Test locale code change to ES
|
// Test locale code change to ES
|
||||||
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', [
|
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', [
|
||||||
|
@ -148,9 +157,10 @@ trait LocaleBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertEquals(7, $response['body']['sum']);
|
||||||
$this->assertCount(7, $response['body']);
|
$this->assertIsArray($response['body']['continents']);
|
||||||
$this->assertEquals($response['body']['NA'], 'América del Norte');
|
$this->assertEquals($response['body']['continents'][0]['code'], 'NA');
|
||||||
|
$this->assertEquals($response['body']['continents'][0]['name'], 'América del Norte');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,9 +182,9 @@ trait LocaleBase
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertCount(117, $response['body']);
|
$this->assertEquals(117, $response['body']['sum']);
|
||||||
$this->assertEquals($response['body'][0]['symbol'], '$');
|
$this->assertEquals($response['body']['currencies'][0]['symbol'], '$');
|
||||||
$this->assertEquals($response['body'][0]['name'], 'US Dollar');
|
$this->assertEquals($response['body']['currencies'][0]['name'], 'US Dollar');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -195,15 +205,15 @@ trait LocaleBase
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertIsArray($response['body']);
|
$this->assertIsArray($response['body']);
|
||||||
$this->assertCount(185, $response['body']);
|
$this->assertEquals(185, $response['body']['sum']);
|
||||||
|
|
||||||
$this->assertEquals($response['body'][0]['code'], 'aa');
|
$this->assertEquals($response['body']['languages'][0]['code'], 'aa');
|
||||||
$this->assertEquals($response['body'][0]['name'], 'Afar');
|
$this->assertEquals($response['body']['languages'][0]['name'], 'Afar');
|
||||||
$this->assertEquals($response['body'][0]['nativeName'], 'Afar');
|
$this->assertEquals($response['body']['languages'][0]['nativeName'], 'Afar');
|
||||||
|
|
||||||
$this->assertEquals($response['body'][184]['code'], 'zu');
|
$this->assertEquals($response['body']['languages'][184]['code'], 'zu');
|
||||||
$this->assertEquals($response['body'][184]['name'], 'Zulu');
|
$this->assertEquals($response['body']['languages'][184]['name'], 'Zulu');
|
||||||
$this->assertEquals($response['body'][184]['nativeName'], 'isiZulu');
|
$this->assertEquals($response['body']['languages'][184]['nativeName'], 'isiZulu');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -228,16 +238,20 @@ trait LocaleBase
|
||||||
'x-appwrite-locale' => $lang,
|
'x-appwrite-locale' => $lang,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($response['body'] as $i => $code) {
|
if(!\is_array($response['body']['countries'])) {
|
||||||
$this->assertArrayHasKey($i, $defaultCountries, $i . ' country should be removed from ' . $lang);
|
throw new Exception('Failed to itterate locale: '.$lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_keys($defaultCountries) as $i => $code) {
|
foreach ($response['body']['countries'] as $i => $code) {
|
||||||
$this->assertArrayHasKey($code, $response['body'], $code . ' country is missing from ' . $lang . ' (total: ' . count($response['body']) . ')');
|
$this->assertArrayHasKey($code['code'], $defaultCountries, $code['code'] . ' country should be removed from ' . $lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// foreach (array_keys($defaultCountries) as $i => $code) {
|
||||||
|
// $this->assertArrayHasKey($code, $response['body']['countries'], $code . ' country is missing from ' . $lang . ' (total: ' . count($response['body']['countries']) . ')');
|
||||||
|
// }
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertCount(194, $response['body']);
|
$this->assertEquals(194, $response['body']['sum']);
|
||||||
|
|
||||||
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', [
|
$response = $this->client->call(Client::METHOD_GET, '/locale/continents', [
|
||||||
'content-type' => 'application/json',
|
'content-type' => 'application/json',
|
||||||
|
@ -245,16 +259,16 @@ trait LocaleBase
|
||||||
'x-appwrite-locale' => $lang,
|
'x-appwrite-locale' => $lang,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($response['body'] as $i => $code) {
|
foreach ($response['body']['continents'] as $i => $code) {
|
||||||
$this->assertArrayHasKey($i, $defaultContinents, $i . ' continent should be removed from ' . $lang);
|
$this->assertArrayHasKey($code['code'], $defaultContinents, $code['code'] . ' continent should be removed from ' . $lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_keys($defaultContinents) as $i => $code) {
|
// foreach (array_keys($defaultContinents) as $i => $code) {
|
||||||
$this->assertArrayHasKey($code, $response['body'], $code . ' continent is missing from ' . $lang . ' (total: ' . count($response['body']) . ')');
|
// $this->assertArrayHasKey($code, $response['body']['continents'], $code . ' continent is missing from ' . $lang . ' (total: ' . count($response['body']['continents']) . ')');
|
||||||
}
|
// }
|
||||||
|
|
||||||
$this->assertEquals($response['headers']['status-code'], 200);
|
$this->assertEquals($response['headers']['status-code'], 200);
|
||||||
$this->assertCount(7, $response['body']);
|
$this->assertEquals(7, $response['body']['sum']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -366,7 +366,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), []);
|
], $this->getHeaders()), []);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertCount(1, $response['body']);
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -589,7 +589,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), []);
|
], $this->getHeaders()), []);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertCount(1, $response['body']);
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -867,7 +867,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), []);
|
], $this->getHeaders()), []);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertCount(1, $response['body']);
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -1235,7 +1235,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), []);
|
], $this->getHeaders()), []);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertCount(3, $response['body']);
|
$this->assertEquals(3, $response['body']['sum']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -1478,7 +1478,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
|
|
||||||
$this->assertEquals(201, $response['headers']['status-code']);
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertIsInt($response['body']['updated']);
|
// $this->assertIsInt($response['body']['updated']);
|
||||||
$this->assertEquals('sub.example.com', $response['body']['domain']);
|
$this->assertEquals('sub.example.com', $response['body']['domain']);
|
||||||
$this->assertEquals('com', $response['body']['tld']);
|
$this->assertEquals('com', $response['body']['tld']);
|
||||||
$this->assertEquals('example.com', $response['body']['registerable']);
|
$this->assertEquals('example.com', $response['body']['registerable']);
|
||||||
|
@ -1514,7 +1514,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
], $this->getHeaders()), []);
|
], $this->getHeaders()), []);
|
||||||
|
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertCount(1, $response['body']);
|
$this->assertEquals(1, $response['body']['sum']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
@ -1539,7 +1539,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||||
$this->assertEquals(200, $response['headers']['status-code']);
|
$this->assertEquals(200, $response['headers']['status-code']);
|
||||||
$this->assertNotEmpty($response['body']['$id']);
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
$this->assertEquals($domainId, $response['body']['$id']);
|
$this->assertEquals($domainId, $response['body']['$id']);
|
||||||
$this->assertIsInt($response['body']['updated']);
|
// $this->assertIsInt($response['body']['updated']);
|
||||||
$this->assertEquals('sub.example.com', $response['body']['domain']);
|
$this->assertEquals('sub.example.com', $response['body']['domain']);
|
||||||
$this->assertEquals('com', $response['body']['tld']);
|
$this->assertEquals('com', $response['body']['tld']);
|
||||||
$this->assertEquals('example.com', $response['body']['registerable']);
|
$this->assertEquals('example.com', $response['body']['registerable']);
|
||||||
|
|
|
@ -24,17 +24,10 @@ trait StorageBase
|
||||||
|
|
||||||
$this->assertEquals($file['headers']['status-code'], 201);
|
$this->assertEquals($file['headers']['status-code'], 201);
|
||||||
$this->assertNotEmpty($file['body']['$id']);
|
$this->assertNotEmpty($file['body']['$id']);
|
||||||
$this->assertEquals('files', $file['body']['$collection']);
|
|
||||||
$this->assertIsInt($file['body']['dateCreated']);
|
$this->assertIsInt($file['body']['dateCreated']);
|
||||||
$this->assertEquals('logo.png', $file['body']['name']);
|
$this->assertEquals('logo.png', $file['body']['name']);
|
||||||
$this->assertEquals('image/png', $file['body']['mimeType']);
|
$this->assertEquals('image/png', $file['body']['mimeType']);
|
||||||
$this->assertEquals(47218, $file['body']['sizeOriginal']);
|
$this->assertEquals(47218, $file['body']['sizeOriginal']);
|
||||||
$this->assertEquals(54944, $file['body']['sizeActual']);
|
|
||||||
$this->assertEquals('gzip', $file['body']['algorithm']);
|
|
||||||
$this->assertEquals('1', $file['body']['fileOpenSSLVersion']);
|
|
||||||
$this->assertEquals('aes-128-gcm', $file['body']['fileOpenSSLCipher']);
|
|
||||||
$this->assertNotEmpty($file['body']['fileOpenSSLTag']);
|
|
||||||
$this->assertNotEmpty($file['body']['fileOpenSSLIV']);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
|
|
@ -137,14 +137,14 @@ trait UsersBase
|
||||||
'x-appwrite-project' => $this->getProject()['$id'],
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
], $this->getHeaders()), [
|
], $this->getHeaders()), [
|
||||||
'prefs' => [
|
'prefs' => [
|
||||||
'key1' => 'value1',
|
'funcKey1' => 'funcValue1',
|
||||||
'key2' => 'value2',
|
'funcKey2' => 'funcValue2',
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($user['headers']['status-code'], 200);
|
$this->assertEquals($user['headers']['status-code'], 200);
|
||||||
$this->assertEquals($user['body']['key1'], 'value1');
|
$this->assertEquals($user['body']['funcKey1'], 'funcValue1');
|
||||||
$this->assertEquals($user['body']['key2'], 'value2');
|
$this->assertEquals($user['body']['funcKey2'], 'funcValue2');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for FAILURE
|
* Test for FAILURE
|
||||||
|
|
152
tests/e2e/Services/Workers/WebhooksTest.php
Normal file
152
tests/e2e/Services/Workers/WebhooksTest.php
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\E2E\Services\Workers;
|
||||||
|
|
||||||
|
use Tests\E2E\Client;
|
||||||
|
use Tests\E2E\Scopes\ProjectConsole;
|
||||||
|
use Tests\E2E\Scopes\ProjectCustom;
|
||||||
|
use Tests\E2E\Scopes\Scope;
|
||||||
|
use Tests\E2E\Scopes\SideClient;
|
||||||
|
use Tests\E2E\Scopes\SideServer;
|
||||||
|
|
||||||
|
class WebhooksTest extends Scope
|
||||||
|
{
|
||||||
|
use ProjectConsole;
|
||||||
|
use SideClient;
|
||||||
|
|
||||||
|
public function testCreateProject(): array
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test for SUCCESS
|
||||||
|
*/
|
||||||
|
$team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'name' => 'Project Test',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(201, $team['headers']['status-code']);
|
||||||
|
$this->assertEquals('Project Test', $team['body']['name']);
|
||||||
|
$this->assertNotEmpty($team['body']['$id']);
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'name' => 'Project Test',
|
||||||
|
'teamId' => $team['body']['$id'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
|
$this->assertEquals('Project Test', $response['body']['name']);
|
||||||
|
$this->assertEquals($team['body']['$id'], $response['body']['teamId']);
|
||||||
|
$this->assertArrayHasKey('platforms', $response['body']);
|
||||||
|
$this->assertArrayHasKey('webhooks', $response['body']);
|
||||||
|
$this->assertArrayHasKey('keys', $response['body']);
|
||||||
|
$this->assertArrayHasKey('tasks', $response['body']);
|
||||||
|
|
||||||
|
$projectId = $response['body']['$id'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for FAILURE
|
||||||
|
*/
|
||||||
|
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'name' => '',
|
||||||
|
'teamId' => $team['body']['$id'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(400, $response['headers']['status-code']);
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'name' => 'Project Test',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(400, $response['headers']['status-code']);
|
||||||
|
|
||||||
|
return ['projectId' => $projectId];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCreateProject
|
||||||
|
*/
|
||||||
|
public function testCreateWebhook($data): array
|
||||||
|
{
|
||||||
|
$id = (isset($data['projectId'])) ? $data['projectId'] : '';
|
||||||
|
|
||||||
|
$response = $this->client->call(Client::METHOD_POST, '/projects/'.$id.'/webhooks', array_merge([
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $this->getProject()['$id'],
|
||||||
|
], $this->getHeaders()), [
|
||||||
|
'name' => 'Webhook Worker Test',
|
||||||
|
'events' => ['account.create', 'account.update.email'],
|
||||||
|
'url' => 'http://request-catcher:5000/webhook',
|
||||||
|
'security' => true,
|
||||||
|
'httpUser' => 'username',
|
||||||
|
'httpPass' => 'password',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(201, $response['headers']['status-code']);
|
||||||
|
$this->assertNotEmpty($response['body']['$id']);
|
||||||
|
$this->assertContains('account.create', $response['body']['events']);
|
||||||
|
$this->assertContains('account.update.email', $response['body']['events']);
|
||||||
|
$this->assertCount(2, $response['body']['events']);
|
||||||
|
$this->assertEquals('http://request-catcher:5000/webhook', $response['body']['url']);
|
||||||
|
$this->assertIsBool($response['body']['security']);
|
||||||
|
$this->assertEquals(true, $response['body']['security']);
|
||||||
|
$this->assertEquals('username', $response['body']['httpUser']);
|
||||||
|
|
||||||
|
$data = array_merge($data, ['webhookId' => $response['body']['$id']]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for FAILURE
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testCreateWebhook
|
||||||
|
*/
|
||||||
|
public function testCreateAccount($data)
|
||||||
|
{
|
||||||
|
$projectId = (isset($data['projectId'])) ? $data['projectId'] : '';
|
||||||
|
$email = uniqid().'webhook.user@localhost.test';
|
||||||
|
$password = 'password';
|
||||||
|
$name = 'User Name';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for SUCCESS
|
||||||
|
*/
|
||||||
|
$response = $this->client->call(Client::METHOD_POST, '/account', array_merge([
|
||||||
|
'origin' => 'http://localhost',
|
||||||
|
'content-type' => 'application/json',
|
||||||
|
'x-appwrite-project' => $projectId,
|
||||||
|
]), [
|
||||||
|
'email' => $email,
|
||||||
|
'password' => $password,
|
||||||
|
'name' => $name,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals($response['headers']['status-code'], 201);
|
||||||
|
|
||||||
|
$webhook = $this->getLastRequest();
|
||||||
|
|
||||||
|
$this->assertNotEmpty($webhook['data']);
|
||||||
|
$this->assertNotEmpty($webhook['data']['$id']);
|
||||||
|
$this->assertIsNumeric($webhook['data']['status']);
|
||||||
|
$this->assertIsNumeric($webhook['data']['registration']);
|
||||||
|
$this->assertEquals($webhook['data']['email'], $email);
|
||||||
|
$this->assertEquals($webhook['data']['name'], $name);
|
||||||
|
$this->assertIsBool($webhook['data']['emailVerification']);
|
||||||
|
$this->assertIsArray($webhook['data']['prefs']);
|
||||||
|
$this->assertIsArray($webhook['data']['roles']);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue