From cfb5806b170bb05907a0f0c4ee510a54cdbde80c Mon Sep 17 00:00:00 2001 From: Eldad Fux Date: Sun, 15 Dec 2019 20:56:44 +0200 Subject: [PATCH] Removed project query --- app/controllers/admin/keys.php | 57 ++++++--------------------- app/controllers/admin/platforms.php | 61 ++++++----------------------- app/controllers/admin/projects.php | 13 ------ app/controllers/admin/tasks.php | 57 ++++++--------------------- app/controllers/admin/webhooks.php | 57 ++++++--------------------- 5 files changed, 45 insertions(+), 200 deletions(-) diff --git a/app/controllers/admin/keys.php b/app/controllers/admin/keys.php index f8f6f0c2ad..354ffc845c 100644 --- a/app/controllers/admin/keys.php +++ b/app/controllers/admin/keys.php @@ -1,6 +1,6 @@ get('/v1/projects/:projectId/keys') +$utopia->get('/v1/keys') ->desc('List Keys') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listKeys') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->action( - function ($projectId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function () use ($response, $consoleDB, $project) { $response->json($project->getAttribute('keys', [])); //FIXME make sure array objects return correctly } ); -$utopia->get('/v1/projects/:projectId/keys/:keyId') +$utopia->get('/v1/keys/:keyId') ->desc('Get Key') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'getKey') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') ->action( - function ($projectId, $keyId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($keyId) use ($response, $consoleDB, $project) { $key = $project->search('$uid', $keyId, $project->getAttribute('keys', [])); if (empty($key) && $key instanceof Document) { @@ -69,22 +55,15 @@ $utopia->get('/v1/projects/:projectId/keys/:keyId') } ); -$utopia->post('/v1/projects/:projectId/keys') +$utopia->post('/v1/keys') ->desc('Create Key') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'createKey') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('name', null, function () { return new Text(256); }, 'Key name') ->param('scopes', null, function () use ($scopes) { return new ArrayList(new WhiteList($scopes)); }, 'Key scopes list') ->action( - function ($projectId, $name, $scopes) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($name, $scopes) use ($response, $consoleDB, $project) { $key = $consoleDB->createDocument([ '$collection' => Database::SYSTEM_COLLECTION_KEYS, '$permissions' => [ @@ -115,23 +94,16 @@ $utopia->post('/v1/projects/:projectId/keys') } ); -$utopia->put('/v1/projects/:projectId/keys/:keyId') +$utopia->put('/v1/keys/:keyId') ->desc('Update Key') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'updateKey') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') ->param('name', null, function () { return new Text(256); }, 'Key name') ->param('scopes', null, function () use ($scopes) { return new ArrayList(new WhiteList($scopes)); }, 'Key scopes list') ->action( - function ($projectId, $keyId, $name, $scopes) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($keyId, $name, $scopes) use ($response, $consoleDB, $project) { $key = $project->search('$uid', $keyId, $project->getAttribute('keys', [])); if (empty($key) && $key instanceof Document) { @@ -151,21 +123,14 @@ $utopia->put('/v1/projects/:projectId/keys/:keyId') } ); -$utopia->delete('/v1/projects/:projectId/keys/:keyId') +$utopia->delete('/v1/keys/:keyId') ->desc('Delete Key') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'deleteKey') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('keyId', null, function () { return new UID(); }, 'Key unique ID.') ->action( - function ($projectId, $keyId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($keyId) use ($response, $consoleDB, $project) { $key = $project->search('$uid', $keyId, $project->getAttribute('keys', [])); if (empty($key) && $key instanceof Document) { diff --git a/app/controllers/admin/platforms.php b/app/controllers/admin/platforms.php index dfdc239f10..5f358731bd 100644 --- a/app/controllers/admin/platforms.php +++ b/app/controllers/admin/platforms.php @@ -1,6 +1,6 @@ get('/v1/projects/:projectId/platforms') +$utopia->get('/v1/platforms') ->desc('List Platforms') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listPlatforms') - ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->action( - function ($projectId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - - $platforms = $project->getAttribute('platforms', []); - - $response->json($platforms); + function () use ($request, $response, $consoleDB, $project) { + $response->json($project->getAttribute('platforms', [])); } ); -$utopia->get('/v1/projects/:projectId/platforms/:platformId') +$utopia->get('/v1/platforms/:platformId') ->desc('Get Platform') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'getPlatform') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('platformId', null, function () { return new UID(); }, 'Platform unique ID.') ->action( - function ($projectId, $platformId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($platformId) use ($request, $response, $consoleDB, $project) { $platform = $project->search('$uid', $platformId, $project->getAttribute('platforms', [])); if (empty($platform) && $platform instanceof Document) { @@ -58,25 +42,18 @@ $utopia->get('/v1/projects/:projectId/platforms/:platformId') } ); -$utopia->post('/v1/projects/:projectId/platforms') +$utopia->post('/v1/platforms') ->desc('Create Platform') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'createPlatform') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('type', null, function () { return new WhiteList(['web', 'ios', 'android', 'unity']); }, 'Platform name') ->param('name', null, function () { return new Text(256); }, 'Platform name') ->param('key', '', function () { return new Text(256); }, 'Package name for android or bundle ID for iOS', true) ->param('store', '', function () { return new Text(256); }, 'App store or Google Play store ID', true) ->param('url', '', function () { return new URL(); }, 'Platform client URL', true) ->action( - function ($projectId, $type, $name, $key, $store, $url) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($type, $name, $key, $store, $url) use ($response, $consoleDB, $project) { $platform = $consoleDB->createDocument([ '$collection' => Database::SYSTEM_COLLECTION_PLATFORMS, '$permissions' => [ @@ -111,25 +88,18 @@ $utopia->post('/v1/projects/:projectId/platforms') } ); -$utopia->put('/v1/projects/:projectId/platforms/:platformId') +$utopia->put('/v1/platforms/:platformId') ->desc('Update Platform') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'updatePlatform') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('platformId', null, function () { return new UID(); }, 'Platform unique ID.') ->param('name', null, function () { return new Text(256); }, 'Platform name') ->param('key', '', function () { return new Text(256); }, 'Package name for android or bundle ID for iOS', true) ->param('store', '', function () { return new Text(256); }, 'App store or Google Play store ID', true) ->param('url', '', function () { return new URL(); }, 'Platform client URL', true) ->action( - function ($projectId, $platformId, $name, $key, $store, $url) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($platformId, $name, $key, $store, $url) use ($response, $consoleDB, $project) { $platform = $project->search('$uid', $platformId, $project->getAttribute('platforms', [])); if (empty($platform) && $platform instanceof Document) { @@ -152,21 +122,14 @@ $utopia->put('/v1/projects/:projectId/platforms/:platformId') } ); -$utopia->delete('/v1/projects/:projectId/platforms/:platformId') +$utopia->delete('/v1/platforms/:platformId') ->desc('Delete Platform') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'deletePlatform') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('platformId', null, function () { return new UID(); }, 'Platform unique ID.') ->action( - function ($projectId, $platformId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($platformId) use ($response, $consoleDB, $project) { $platform = $project->search('$uid', $platformId, $project->getAttribute('platforms', [])); if (empty($platform) && $platform instanceof Document) { diff --git a/app/controllers/admin/projects.php b/app/controllers/admin/projects.php index 98828c8a0f..cbb4bda649 100644 --- a/app/controllers/admin/projects.php +++ b/app/controllers/admin/projects.php @@ -15,19 +15,6 @@ use OpenSSL\OpenSSL; include_once '../shared/api.php'; -$scopes = [ // TODO sync with console UI list - 'users.read', - 'users.write', - 'teams.read', - 'teams.write', - 'collections.read', - 'collections.write', - 'documents.read', - 'documents.write', - 'files.read', - 'files.write', -]; - $utopia->get('/v1/projects') ->desc('List Projects') ->label('scope', 'projects.read') diff --git a/app/controllers/admin/tasks.php b/app/controllers/admin/tasks.php index 6ba47ac02f..33c4afb745 100644 --- a/app/controllers/admin/tasks.php +++ b/app/controllers/admin/tasks.php @@ -1,6 +1,6 @@ get('/v1/projects/:projectId/tasks') +$utopia->get('/v1/tasks') ->desc('List Tasks') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listTasks') - ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->action( - function ($projectId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function () use ($request, $response, $consoleDB, $project) { $tasks = $project->getAttribute('tasks', []); foreach ($tasks as $task) { /* @var $task Document */ @@ -50,21 +43,14 @@ $utopia->get('/v1/projects/:projectId/tasks') } ); -$utopia->get('/v1/projects/:projectId/tasks/:taskId') +$utopia->get('/v1/tasks/:taskId') ->desc('Get Task') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'getTask') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('taskId', null, function () { return new UID(); }, 'Task unique ID.') ->action( - function ($projectId, $taskId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($taskId) use ($request, $response, $consoleDB, $project) { $task = $project->search('$uid', $taskId, $project->getAttribute('tasks', [])); if (empty($task) && $task instanceof Document) { @@ -82,12 +68,11 @@ $utopia->get('/v1/projects/:projectId/tasks/:taskId') } ); -$utopia->post('/v1/projects/:projectId/tasks') +$utopia->post('/v1/tasks') ->desc('Create Task') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'createTask') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('name', null, function () { return new Text(256); }, 'Task name') ->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status') ->param('schedule', null, function () { return new Cron(); }, 'Task schedule syntax') @@ -98,13 +83,7 @@ $utopia->post('/v1/projects/:projectId/tasks') ->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user', true) ->param('httpPass', '', function () { return new Text(256); }, 'Task HTTP password', true) ->action( - function ($projectId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB, $project) { $cron = CronExpression::factory($schedule); $next = ($status == 'play') ? $cron->getNextRunDate()->format('U') : null; @@ -164,12 +143,11 @@ $utopia->post('/v1/projects/:projectId/tasks') } ); -$utopia->put('/v1/projects/:projectId/tasks/:taskId') +$utopia->put('/v1/tasks/:taskId') ->desc('Update Task') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'updateTask') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('taskId', null, function () { return new UID(); }, 'Task unique ID.') ->param('name', null, function () { return new Text(256); }, 'Task name') ->param('status', null, function () { return new WhiteList(['play', 'pause']); }, 'Task status') @@ -181,13 +159,7 @@ $utopia->put('/v1/projects/:projectId/tasks/:taskId') ->param('httpUser', '', function () { return new Text(256); }, 'Task HTTP user', true) ->param('httpPass', '', function () { return new Text(256); }, 'Task HTTP password', true) ->action( - function ($projectId, $taskId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($taskId, $name, $status, $schedule, $security, $httpMethod, $httpUrl, $httpHeaders, $httpUser, $httpPass) use ($request, $response, $consoleDB, $project) { $task = $project->search('$uid', $taskId, $project->getAttribute('tasks', [])); if (empty($task) && $task instanceof Document) { @@ -234,21 +206,14 @@ $utopia->put('/v1/projects/:projectId/tasks/:taskId') } ); -$utopia->delete('/v1/projects/:projectId/tasks/:taskId') +$utopia->delete('/v1/tasks/:taskId') ->desc('Delete Task') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'deleteTask') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('taskId', null, function () { return new UID(); }, 'Task unique ID.') ->action( - function ($projectId, $taskId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($taskId) use ($response, $consoleDB, $project) { $task = $project->search('$uid', $taskId, $project->getAttribute('tasks', [])); if (empty($task) && $task instanceof Document) { diff --git a/app/controllers/admin/webhooks.php b/app/controllers/admin/webhooks.php index bf3d26c248..15df68220a 100644 --- a/app/controllers/admin/webhooks.php +++ b/app/controllers/admin/webhooks.php @@ -1,6 +1,6 @@ get('/v1/projects/:projectId/webhooks') +$utopia->get('/v1/webhooks') ->desc('List Webhooks') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'listWebhooks') - ->param('projectId', '', function () { return new UID(); }, 'Project unique ID.') ->action( - function ($projectId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function () use ($request, $response, $consoleDB, $project) { $webhooks = $project->getAttribute('webhooks', []); foreach ($webhooks as $webhook) { /* @var $webhook Document */ @@ -47,21 +40,14 @@ $utopia->get('/v1/projects/:projectId/webhooks') } ); -$utopia->get('/v1/projects/:projectId/webhooks/:webhookId') +$utopia->get('/v1/webhooks/:webhookId') ->desc('Get Webhook') ->label('scope', 'projects.read') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'getWebhook') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('webhookId', null, function () { return new UID(); }, 'Webhook unique ID.') ->action( - function ($projectId, $webhookId) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($webhookId) use ($request, $response, $consoleDB, $project) { $webhook = $project->search('$uid', $webhookId, $project->getAttribute('webhooks', [])); if (empty($webhook) && $webhook instanceof Document) { @@ -79,12 +65,11 @@ $utopia->get('/v1/projects/:projectId/webhooks/:webhookId') } ); -$utopia->post('/v1/projects/:projectId/webhooks') +$utopia->post('/v1/webhooks') ->desc('Create Webhook') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'createWebhook') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('name', null, function () { return new Text(256); }, 'Webhook name') ->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list') ->param('url', null, function () { return new Text(2000); }, 'Webhook URL') @@ -92,13 +77,7 @@ $utopia->post('/v1/projects/:projectId/webhooks') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user', true) ->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password', true) ->action( - function ($projectId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB, $project) { $key = $request->getServer('_APP_OPENSSL_KEY_V1'); $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); $tag = null; @@ -143,12 +122,11 @@ $utopia->post('/v1/projects/:projectId/webhooks') } ); -$utopia->put('/v1/projects/:projectId/webhooks/:webhookId') +$utopia->put('/v1/webhooks/:webhookId') ->desc('Update Webhook') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'updateWebhook') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('webhookId', null, function () { return new UID(); }, 'Webhook unique ID.') ->param('name', null, function () { return new Text(256); }, 'Webhook name') ->param('events', null, function () { return new ArrayList(new Text(256)); }, 'Webhook events list') @@ -157,13 +135,7 @@ $utopia->put('/v1/projects/:projectId/webhooks/:webhookId') ->param('httpUser', '', function () { return new Text(256); }, 'Webhook HTTP user', true) ->param('httpPass', '', function () { return new Text(256); }, 'Webhook HTTP password', true) ->action( - function ($projectId, $webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($webhookId, $name, $events, $url, $security, $httpUser, $httpPass) use ($request, $response, $consoleDB, $project) { $key = $request->getServer('_APP_OPENSSL_KEY_V1'); $iv = OpenSSL::randomPseudoBytes(OpenSSL::cipherIVLength(OpenSSL::CIPHER_AES_128_GCM)); $tag = null; @@ -198,21 +170,14 @@ $utopia->put('/v1/projects/:projectId/webhooks/:webhookId') } ); -$utopia->delete('/v1/projects/:projectId/webhooks/:webhookId') +$utopia->delete('/v1/webhooks/:webhookId') ->desc('Delete Webhook') ->label('scope', 'projects.write') ->label('sdk.namespace', 'projects') ->label('sdk.method', 'deleteWebhook') - ->param('projectId', null, function () { return new UID(); }, 'Project unique ID.') ->param('webhookId', null, function () { return new UID(); }, 'Webhook unique ID.') ->action( - function ($projectId, $webhookId) use ($response, $consoleDB) { - $project = $consoleDB->getDocument($projectId); - - if (empty($project->getUid()) || Database::SYSTEM_COLLECTION_PROJECTS != $project->getCollection()) { - throw new Exception('Project not found', 404); - } - + function ($webhookId) use ($response, $consoleDB, $project) { $webhook = $project->search('$uid', $webhookId, $project->getAttribute('webhooks', [])); if (empty($webhook) && $webhook instanceof Document) {