mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 16:38:32 +00:00
Merge pull request #1246 from lohanidamodar/feat-audit-abuse
feat-audit-abuse
This commit is contained in:
commit
00136969d2
9 changed files with 211 additions and 200 deletions
|
|
@ -18,10 +18,8 @@ use Utopia\Validator\Text;
|
|||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Ahc\Jwt\JWT;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\UID;
|
||||
|
|
@ -833,22 +831,19 @@ App::get('/v1/account/logs')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_LOG_LIST)
|
||||
->inject('response')
|
||||
->inject('register')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function ($response, $register, $project, $user, $locale, $geodb) {
|
||||
->inject('dbForInternal')
|
||||
->action(function ($response, $user, $locale, $geodb, $dbForInternal) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
/** @var Utopia\Database\Document $user */
|
||||
/** @var Utopia\Locale\Locale $locale */
|
||||
/** @var MaxMind\Db\Reader $geodb */
|
||||
/** @var Utopia\Database\Database $dbForInternal */
|
||||
|
||||
$adapter = new AuditAdapter($register->get('db'));
|
||||
$adapter->setNamespace('app_'.$project->getId());
|
||||
|
||||
$audit = new Audit($adapter);
|
||||
$audit = new Audit($dbForInternal);
|
||||
$countries = $locale->getText('countries');
|
||||
|
||||
$logs = $audit->getLogsByUserAndActions($user->getId(), [
|
||||
|
|
@ -1629,4 +1624,4 @@ App::put('/v1/account/verification')
|
|||
;
|
||||
|
||||
$response->dynamic2($verification, Response::MODEL_TOKEN);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,25 +1,27 @@
|
|||
<?php
|
||||
|
||||
use Utopia\App;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Domains\Domain;
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Task\Validator\Cron;
|
||||
use Appwrite\Network\Validator\CNAME;
|
||||
use Appwrite\Network\Validator\Domain as DomainValidator;
|
||||
use Appwrite\Network\Validator\URL;
|
||||
use Appwrite\Task\Validator\Cron;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Cron\CronExpression;
|
||||
use Utopia\App;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\ArrayList;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Validator\Integer;
|
||||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
|
||||
App::post('/v1/projects')
|
||||
->desc('Create Project')
|
||||
|
|
@ -62,8 +64,8 @@ App::post('/v1/projects')
|
|||
|
||||
$project = $dbForConsole->createDocument('projects', new Document([
|
||||
'$collection' => 'projects',
|
||||
'$read' => ['team:'.$teamId],
|
||||
'$write' => ['team:'.$teamId.'/owner', 'team:'.$teamId.'/developer'],
|
||||
'$read' => ['team:' . $teamId],
|
||||
'$write' => ['team:' . $teamId . '/owner', 'team:' . $teamId . '/developer'],
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'logo' => $logo,
|
||||
|
|
@ -89,11 +91,17 @@ App::post('/v1/projects')
|
|||
|
||||
$collections = Config::getParam('collections2', []); /** @var array $collections */
|
||||
|
||||
$dbForInternal->setNamespace('project_'.$project->getId().'_internal');
|
||||
$dbForInternal->setNamespace('project_' . $project->getId() . '_internal');
|
||||
$dbForInternal->create();
|
||||
$dbForExternal->setNamespace('project_'.$project->getId().'_external');
|
||||
$dbForExternal->setNamespace('project_' . $project->getId() . '_external');
|
||||
$dbForExternal->create();
|
||||
|
||||
$audit = new Audit($dbForInternal);
|
||||
$audit->setup();
|
||||
|
||||
$adapter = new TimeLimit("", 0, 1, $dbForInternal);
|
||||
$adapter->setup();
|
||||
|
||||
foreach ($collections as $key => $collection) {
|
||||
$dbForInternal->createCollection($key);
|
||||
|
||||
|
|
@ -210,7 +218,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
throw new Exception('Project not found', 404);
|
||||
}
|
||||
|
||||
if(App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
|
||||
if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') {
|
||||
|
||||
$period = [
|
||||
'24h' => [
|
||||
|
|
@ -234,44 +242,44 @@ App::get('/v1/projects/:projectId/usage')
|
|||
'group' => '1d',
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
$client = $register->get('influxdb');
|
||||
|
||||
|
||||
$requests = [];
|
||||
$network = [];
|
||||
$functions = [];
|
||||
|
||||
|
||||
if ($client) {
|
||||
$start = $period[$range]['start']->format(DateTime::RFC3339);
|
||||
$end = $period[$range]['end']->format(DateTime::RFC3339);
|
||||
$database = $client->selectDB('telegraf');
|
||||
|
||||
|
||||
// Requests
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_requests_all" WHERE time > \'' . $start . '\' AND time < \'' . $end . '\' AND "metric_type"=\'counter\' AND "project"=\'' . $project->getId() . '\' GROUP BY time(' . $period[$range]['group'] . ') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
|
||||
foreach ($points as $point) {
|
||||
$requests[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// Network
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \''.$start.'\' AND time < \''.$end.'\' AND "metric_type"=\'counter\' AND "project"=\''.$project->getId().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$result = $database->query('SELECT sum(value) AS "value" FROM "appwrite_usage_network_all" WHERE time > \'' . $start . '\' AND time < \'' . $end . '\' AND "metric_type"=\'counter\' AND "project"=\'' . $project->getId() . '\' GROUP BY time(' . $period[$range]['group'] . ') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
|
||||
foreach ($points as $point) {
|
||||
$network[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
'date' => \strtotime($point['time']),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// Functions
|
||||
$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().'\' GROUP BY time('.$period[$range]['group'].') FILL(null)');
|
||||
$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() . '\' GROUP BY time(' . $period[$range]['group'] . ') FILL(null)');
|
||||
$points = $result->getPoints();
|
||||
|
||||
|
||||
foreach ($points as $point) {
|
||||
$functions[] = [
|
||||
'value' => (!empty($point['value'])) ? $point['value'] : 0,
|
||||
|
|
@ -285,14 +293,13 @@ App::get('/v1/projects/:projectId/usage')
|
|||
$functions = [];
|
||||
}
|
||||
|
||||
|
||||
// Users
|
||||
|
||||
$projectDB->getCollection([
|
||||
'limit' => 0,
|
||||
'offset' => 0,
|
||||
'filters' => [
|
||||
'$collection=users'
|
||||
'$collection=users',
|
||||
],
|
||||
]);
|
||||
|
||||
|
|
@ -317,7 +324,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
'limit' => 0,
|
||||
'offset' => 0,
|
||||
'filters' => [
|
||||
'$collection='.$collection['$id'],
|
||||
'$collection=' . $collection['$id'],
|
||||
],
|
||||
]);
|
||||
|
||||
|
|
@ -373,7 +380,7 @@ App::get('/v1/projects/:projectId/usage')
|
|||
'$collection=files',
|
||||
],
|
||||
]
|
||||
) +
|
||||
) +
|
||||
$projectDB->getCount(
|
||||
[
|
||||
'attribute' => 'size',
|
||||
|
|
@ -420,16 +427,16 @@ App::patch('/v1/projects/:projectId')
|
|||
}
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('description', $description)
|
||||
->setAttribute('logo', $logo)
|
||||
->setAttribute('url', $url)
|
||||
->setAttribute('legalName', $legalName)
|
||||
->setAttribute('legalCountry', $legalCountry)
|
||||
->setAttribute('legalState', $legalState)
|
||||
->setAttribute('legalCity', $legalCity)
|
||||
->setAttribute('legalAddress', $legalAddress)
|
||||
->setAttribute('legalTaxId', $legalTaxId)
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('description', $description)
|
||||
->setAttribute('logo', $logo)
|
||||
->setAttribute('url', $url)
|
||||
->setAttribute('legalName', $legalName)
|
||||
->setAttribute('legalCountry', $legalCountry)
|
||||
->setAttribute('legalState', $legalState)
|
||||
->setAttribute('legalCity', $legalCity)
|
||||
->setAttribute('legalAddress', $legalAddress)
|
||||
->setAttribute('legalTaxId', $legalTaxId)
|
||||
);
|
||||
|
||||
$response->dynamic2($project, Response::MODEL_PROJECT);
|
||||
|
|
@ -462,8 +469,8 @@ App::patch('/v1/projects/:projectId/oauth2')
|
|||
}
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('usersOauth2'.\ucfirst($provider).'Appid', $appId)
|
||||
->setAttribute('usersOauth2'.\ucfirst($provider).'Secret', $secret)
|
||||
->setAttribute('usersOauth2' . \ucfirst($provider) . 'Appid', $appId)
|
||||
->setAttribute('usersOauth2' . \ucfirst($provider) . 'Secret', $secret)
|
||||
);
|
||||
|
||||
$response->dynamic2($project, Response::MODEL_PROJECT);
|
||||
|
|
@ -494,7 +501,7 @@ App::patch('/v1/projects/:projectId/auth/limit')
|
|||
}
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('usersAuthLimit', $limit)
|
||||
->setAttribute('usersAuthLimit', $limit)
|
||||
);
|
||||
|
||||
$response->dynamic2($project, Response::MODEL_PROJECT);
|
||||
|
|
@ -511,7 +518,7 @@ App::patch('/v1/projects/:projectId/auth/:method')
|
|||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_PROJECT)
|
||||
->param('projectId', '', new UID(), 'Project unique ID.')
|
||||
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: '.implode(',', \array_keys(Config::getParam('auth'))), false)
|
||||
->param('method', '', new WhiteList(\array_keys(Config::getParam('auth')), true), 'Auth Method. Possible values: ' . implode(',', \array_keys(Config::getParam('auth'))), false)
|
||||
->param('status', false, new Boolean(true), 'Set the status of this auth method.')
|
||||
->inject('response')
|
||||
->inject('dbForConsole')
|
||||
|
|
@ -529,7 +536,7 @@ App::patch('/v1/projects/:projectId/auth/:method')
|
|||
}
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute($authKey, $status)
|
||||
->setAttribute($authKey, $status)
|
||||
);
|
||||
|
||||
$response->dynamic2($project, Response::MODEL_PROJECT);
|
||||
|
|
@ -570,7 +577,7 @@ App::delete('/v1/projects/:projectId')
|
|||
->setParam('type', DELETE_TYPE_DOCUMENT)
|
||||
->setParam('document', $project)
|
||||
;
|
||||
|
||||
|
||||
if (!$dbForConsole->deleteDocument('teams', $project->getAttribute('teamId', null))) {
|
||||
throw new Exception('Failed to remove project team from DB', 500);
|
||||
}
|
||||
|
|
@ -626,7 +633,7 @@ App::post('/v1/projects/:projectId/webhooks')
|
|||
]);
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('webhooks', $webhook, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('webhooks', $webhook, Document::SET_TYPE_APPEND)
|
||||
);
|
||||
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
|
|
@ -736,16 +743,16 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
}
|
||||
|
||||
$project->findAndReplace('$id', $webhook->getId(), $webhook
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('events', $events)
|
||||
->setAttribute('url', $url)
|
||||
->setAttribute('security', $security)
|
||||
->setAttribute('httpUser', $httpUser)
|
||||
->setAttribute('httpPass', $httpPass)
|
||||
, 'webhooks');
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('events', $events)
|
||||
->setAttribute('url', $url)
|
||||
->setAttribute('security', $security)
|
||||
->setAttribute('httpUser', $httpUser)
|
||||
->setAttribute('httpPass', $httpPass)
|
||||
, 'webhooks');
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
|
||||
$response->dynamic2($webhook, Response::MODEL_WEBHOOK);
|
||||
});
|
||||
|
||||
|
|
@ -816,7 +823,7 @@ App::post('/v1/projects/:projectId/keys')
|
|||
]);
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('keys', $key, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('keys', $key, Document::SET_TYPE_APPEND)
|
||||
);
|
||||
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
|
|
@ -839,7 +846,7 @@ App::get('/v1/projects/:projectId/keys')
|
|||
->action(function ($projectId, $response, $dbForConsole) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Utopia\Database\Database $dbForConsole */
|
||||
|
||||
|
||||
$project = $dbForConsole->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
|
|
@ -917,12 +924,12 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
|||
}
|
||||
|
||||
$project->findAndReplace('$id', $key->getId(), $key
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('scopes', $scopes)
|
||||
, 'keys');
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('scopes', $scopes)
|
||||
, 'keys');
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
|
||||
$response->dynamic2($key, Response::MODEL_KEY);
|
||||
});
|
||||
|
||||
|
|
@ -1015,7 +1022,7 @@ App::post('/v1/projects/:projectId/tasks')
|
|||
]);
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('tasks', $task, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('tasks', $task, Document::SET_TYPE_APPEND)
|
||||
);
|
||||
|
||||
if ($next) {
|
||||
|
|
@ -1135,18 +1142,18 @@ App::put('/v1/projects/:projectId/tasks/:taskId')
|
|||
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
|
||||
|
||||
$project->findAndReplace('$id', $task->getId(), $task
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('status', $status)
|
||||
->setAttribute('schedule', $schedule)
|
||||
->setAttribute('updated', \time())
|
||||
->setAttribute('next', $next)
|
||||
->setAttribute('security', $security)
|
||||
->setAttribute('httpMethod', $httpMethod)
|
||||
->setAttribute('httpUrl', $httpUrl)
|
||||
->setAttribute('httpHeaders', $httpHeaders)
|
||||
->setAttribute('httpUser', $httpUser)
|
||||
->setAttribute('httpPass', $httpPass)
|
||||
, 'tasks');
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('status', $status)
|
||||
->setAttribute('schedule', $schedule)
|
||||
->setAttribute('updated', \time())
|
||||
->setAttribute('next', $next)
|
||||
->setAttribute('security', $security)
|
||||
->setAttribute('httpMethod', $httpMethod)
|
||||
->setAttribute('httpUrl', $httpUrl)
|
||||
->setAttribute('httpHeaders', $httpHeaders)
|
||||
->setAttribute('httpUser', $httpUser)
|
||||
->setAttribute('httpPass', $httpPass)
|
||||
, 'tasks');
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
|
|
@ -1231,13 +1238,13 @@ App::post('/v1/projects/:projectId/platforms')
|
|||
]);
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('platforms', $platform, Document::SET_TYPE_APPEND)
|
||||
);
|
||||
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
$response->dynamic2($platform, Response::MODEL_PLATFORM);
|
||||
});
|
||||
|
||||
|
||||
App::get('/v1/projects/:projectId/platforms')
|
||||
->desc('List Platforms')
|
||||
->groups(['api', 'projects'])
|
||||
|
|
@ -1345,12 +1352,12 @@ App::put('/v1/projects/:projectId/platforms/:platformId')
|
|||
;
|
||||
|
||||
$project->findAndReplace('$id', $platform->getId(), $platform
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('dateUpdated', \time())
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('store', $store)
|
||||
->setAttribute('hostname', $hostname)
|
||||
, 'platforms');
|
||||
->setAttribute('name', $name)
|
||||
->setAttribute('dateUpdated', \time())
|
||||
->setAttribute('key', $key)
|
||||
->setAttribute('store', $store)
|
||||
->setAttribute('hostname', $hostname)
|
||||
, 'platforms');
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
|
|
@ -1424,7 +1431,7 @@ App::post('/v1/projects/:projectId/domains')
|
|||
$target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception('Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.', 500);
|
||||
throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500);
|
||||
}
|
||||
|
||||
$domain = new Domain($domain);
|
||||
|
|
@ -1440,7 +1447,7 @@ App::post('/v1/projects/:projectId/domains')
|
|||
]);
|
||||
|
||||
$project = $dbForConsole->updateDocument('projects', $project->getId(), $project
|
||||
->setAttribute('domains', $domain, Document::SET_TYPE_APPEND)
|
||||
->setAttribute('domains', $domain, Document::SET_TYPE_APPEND)
|
||||
);
|
||||
|
||||
$response->setStatusCode(Response::STATUS_CODE_CREATED);
|
||||
|
|
@ -1471,7 +1478,7 @@ App::get('/v1/projects/:projectId/domains')
|
|||
}
|
||||
|
||||
$domains = $project->getAttribute('domains', []);
|
||||
|
||||
|
||||
$response->dynamic2(new Document([
|
||||
'domains' => $domains,
|
||||
'sum' => count($domains),
|
||||
|
|
@ -1544,7 +1551,7 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
|||
$target = new Domain(App::getEnv('_APP_DOMAIN_TARGET', ''));
|
||||
|
||||
if (!$target->isKnown() || $target->isTest()) {
|
||||
throw new Exception('Unreachable CNAME target ('.$target->get().'), please use a domain with a public suffix.', 500);
|
||||
throw new Exception('Unreachable CNAME target (' . $target->get() . '), please use a domain with a public suffix.', 500);
|
||||
}
|
||||
|
||||
if ($domain->getAttribute('verification') === true) {
|
||||
|
|
@ -1558,8 +1565,8 @@ App::patch('/v1/projects/:projectId/domains/:domainId/verification')
|
|||
}
|
||||
|
||||
$project->findAndReplace('$id', $domain->getId(), $domain
|
||||
->setAttribute('verification', true)
|
||||
, 'domains');
|
||||
->setAttribute('verification', true)
|
||||
, 'domains');
|
||||
|
||||
$dbForConsole->updateDocument('projects', $project->getId(), $project);
|
||||
|
||||
|
|
@ -1610,4 +1617,4 @@ App::delete('/v1/projects/:projectId/domains/:domainId')
|
|||
;
|
||||
|
||||
$response->noContent();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use Utopia\Validator\Text;
|
|||
use Utopia\Validator\Range;
|
||||
use Utopia\Validator\Boolean;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Validator\UID;
|
||||
|
|
@ -214,12 +213,10 @@ App::get('/v1/users/:userId/logs')
|
|||
->label('sdk.response.model', Response::MODEL_LOG_LIST)
|
||||
->param('userId', '', new UID(), 'User unique ID.')
|
||||
->inject('response')
|
||||
->inject('register')
|
||||
->inject('project')
|
||||
->inject('dbForInternal')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function ($userId, $response, $register, $project, $dbForInternal, $locale, $geodb) {
|
||||
->action(function ($userId, $response, $dbForInternal, $locale, $geodb) {
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
/** @var Utopia\Registry\Registry $register */
|
||||
/** @var Appwrite\Database\Document $project */
|
||||
|
|
@ -233,10 +230,7 @@ App::get('/v1/users/:userId/logs')
|
|||
throw new Exception('User not found', 404);
|
||||
}
|
||||
|
||||
$adapter = new AuditAdapter($register->get('db'));
|
||||
$adapter->setNamespace('app_'.$project->getId());
|
||||
|
||||
$audit = new Audit($adapter);
|
||||
$audit = new Audit($dbForInternal);
|
||||
|
||||
$countries = $locale->getText('countries');
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use Utopia\Abuse\Adapters\TimeLimit;
|
|||
use Utopia\Storage\Device\Local;
|
||||
use Utopia\Storage\Storage;
|
||||
|
||||
App::init(function ($utopia, $request, $response, $project, $user, $register, $events, $audits, $usage, $deletes) {
|
||||
App::init(function ($utopia, $request, $response, $project, $user, $register, $events, $audits, $usage, $deletes, $dbForInternal) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
|
@ -21,6 +21,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
|||
/** @var Appwrite\Event\Event $usage */
|
||||
/** @var Appwrite\Event\Event $deletes */
|
||||
/** @var Appwrite\Event\Event $functions */
|
||||
/** @var Utopia\Database\Database $dbForInternal */
|
||||
|
||||
Storage::setDevice('files', new Local(APP_STORAGE_UPLOADS.'/app-'.$project->getId()));
|
||||
Storage::setDevice('functions', new Local(APP_STORAGE_FUNCTIONS.'/app-'.$project->getId()));
|
||||
|
|
@ -31,47 +32,44 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
|||
throw new Exception('Missing or unknown project ID', 400);
|
||||
}
|
||||
|
||||
// /*
|
||||
// * Abuse Check
|
||||
// */
|
||||
// $timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), function () use ($register) {
|
||||
// return $register->get('db');
|
||||
// });
|
||||
// $timeLimit->setNamespace('app_'.$project->getId());
|
||||
// $timeLimit
|
||||
// ->setParam('{userId}', $user->getId())
|
||||
// ->setParam('{userAgent}', $request->getUserAgent(''))
|
||||
// ->setParam('{ip}', $request->getIP())
|
||||
// ->setParam('{url}', $request->getHostname().$route->getURL())
|
||||
// ;
|
||||
/*
|
||||
* Abuse Check
|
||||
*/
|
||||
$timeLimit = new TimeLimit($route->getLabel('abuse-key', 'url:{url},ip:{ip}'), $route->getLabel('abuse-limit', 0), $route->getLabel('abuse-time', 3600), $dbForInternal);
|
||||
$timeLimit
|
||||
->setParam('{userId}', $user->getId())
|
||||
->setParam('{userAgent}', $request->getUserAgent(''))
|
||||
->setParam('{ip}', $request->getIP())
|
||||
->setParam('{url}', $request->getHostname().$route->getURL())
|
||||
;
|
||||
|
||||
// //TODO make sure we get array here
|
||||
//TODO make sure we get array here
|
||||
|
||||
// foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
|
||||
// if(!empty($value)) {
|
||||
// $timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value);
|
||||
// }
|
||||
// }
|
||||
foreach ($request->getParams() as $key => $value) { // Set request params as potential abuse keys
|
||||
if(!empty($value)) {
|
||||
$timeLimit->setParam('{param-'.$key.'}', (\is_array($value)) ? \json_encode($value) : $value);
|
||||
}
|
||||
}
|
||||
|
||||
// $abuse = new Abuse($timeLimit);
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
// if ($timeLimit->limit()) {
|
||||
// $response
|
||||
// ->addHeader('X-RateLimit-Limit', $timeLimit->limit())
|
||||
// ->addHeader('X-RateLimit-Remaining', $timeLimit->remaining())
|
||||
// ->addHeader('X-RateLimit-Reset', $timeLimit->time() + $route->getLabel('abuse-time', 3600))
|
||||
// ;
|
||||
// }
|
||||
if ($timeLimit->limit()) {
|
||||
$response
|
||||
->addHeader('X-RateLimit-Limit', $timeLimit->limit())
|
||||
->addHeader('X-RateLimit-Remaining', $timeLimit->remaining())
|
||||
->addHeader('X-RateLimit-Reset', $timeLimit->time() + $route->getLabel('abuse-time', 3600))
|
||||
;
|
||||
}
|
||||
|
||||
// $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
// $isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::$roles);
|
||||
$isAppUser = Auth::isAppUser(Authorization::$roles);
|
||||
|
||||
// if (($abuse->check() // Route is rate-limited
|
||||
// && App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') // Abuse is not diabled
|
||||
// && (!$isAppUser && !$isPrivilegedUser)) // User is not an admin or API key
|
||||
// {
|
||||
// throw new Exception('Too many requests', 429);
|
||||
// }
|
||||
if (($abuse->check() // Route is rate-limited
|
||||
&& App::getEnv('_APP_OPTIONS_ABUSE', 'enabled') !== 'disabled') // Abuse is not disabled
|
||||
&& (!$isAppUser && !$isPrivilegedUser)) // User is not an admin or API key
|
||||
{
|
||||
throw new Exception('Too many requests', 429);
|
||||
}
|
||||
|
||||
/*
|
||||
* Background Jobs
|
||||
|
|
@ -111,7 +109,7 @@ App::init(function ($utopia, $request, $response, $project, $user, $register, $e
|
|||
->setParam('projectId', $project->getId())
|
||||
;
|
||||
|
||||
}, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes'], 'api');
|
||||
}, ['utopia', 'request', 'response', 'project', 'user', 'register', 'events', 'audits', 'usage', 'deletes', 'dbForInternal'], 'api');
|
||||
|
||||
|
||||
App::init(function ($utopia, $request, $response, $project, $user) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ use Utopia\App;
|
|||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Validator\Authorization as Authorization2;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Abuse\Adapters\TimeLimit;
|
||||
|
||||
// xdebug_start_trace('/tmp/trace');
|
||||
|
||||
|
|
@ -67,6 +69,12 @@ $http->on('start', function (Server $http) use ($payloadSize, $register) {
|
|||
$register->get('cache')->flushAll();
|
||||
|
||||
$dbForConsole->create();
|
||||
|
||||
$audit = new Audit($dbForConsole);
|
||||
$audit->setup();
|
||||
|
||||
$adapter = new TimeLimit("", 0, 1, $dbForConsole);
|
||||
$adapter->setup();
|
||||
|
||||
foreach ($collections as $key => $collection) {
|
||||
$dbForConsole->createCollection($key);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
use Appwrite\Resque\Worker;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Utopia\Cache\Adapter\Redis;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\CLI\Console;
|
||||
use Utopia\Database\Adapter\MariaDB;
|
||||
use Utopia\Database\Database;
|
||||
|
||||
require_once __DIR__.'/../init.php';
|
||||
|
||||
|
|
@ -31,10 +34,11 @@ class AuditsV1 extends Worker
|
|||
$data = $this->args['data'];
|
||||
$db = $register->get('db', true);
|
||||
|
||||
$adapter = new AuditAdapter($db);
|
||||
$adapter->setNamespace('app_'.$projectId);
|
||||
$cache = new Cache(new Redis($register->get('cache')));
|
||||
$dbForInternal = new Database(new MariaDB($db), $cache);
|
||||
$dbForInternal->setNamespace('project_'.$projectId.'_internal');
|
||||
|
||||
$audit = new Audit($adapter);
|
||||
$audit = new Audit($dbForInternal);
|
||||
|
||||
$audit->log($userId, $event, $resource, $userAgent, $ip, '', $data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Database\Database;
|
||||
use Utopia\Database\Database as Database2;
|
||||
use Utopia\Cache\Adapter\Redis as RedisCache;
|
||||
use Appwrite\Database\Adapter\MySQL as MySQLAdapter;
|
||||
use Appwrite\Database\Adapter\Redis as RedisAdapter;
|
||||
use Appwrite\Database\Document;
|
||||
|
|
@ -12,7 +14,8 @@ use Utopia\Abuse\Adapters\TimeLimit;
|
|||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
|
||||
use Utopia\Cache\Cache;
|
||||
use Utopia\Database\Adapter\MariaDB;
|
||||
|
||||
require_once __DIR__.'/../init.php';
|
||||
|
||||
|
|
@ -165,12 +168,9 @@ class DeletesV1 extends Worker
|
|||
throw new Exception('Failed to delete audit logs. No timestamp provided');
|
||||
}
|
||||
|
||||
$timeLimit = new TimeLimit("", 0, 1, function () use ($register) {
|
||||
return $register->get('db');
|
||||
});
|
||||
|
||||
$this->deleteForProjectIds(function($projectId) use ($timeLimit, $timestamp){
|
||||
$timeLimit->setNamespace('app_'.$projectId);
|
||||
|
||||
$this->deleteForProjectIds(function($projectId) use ($timestamp){
|
||||
$timeLimit = new TimeLimit("", 0, 1, $this->getInternalDB($projectId));
|
||||
$abuse = new Abuse($timeLimit);
|
||||
|
||||
$status = $abuse->cleanup($timestamp);
|
||||
|
|
@ -187,9 +187,7 @@ class DeletesV1 extends Worker
|
|||
throw new Exception('Failed to delete audit logs. No timestamp provided');
|
||||
}
|
||||
$this->deleteForProjectIds(function($projectId) use ($register, $timestamp){
|
||||
$adapter = new AuditAdapter($register->get('db'));
|
||||
$adapter->setNamespace('app_'.$projectId);
|
||||
$audit = new Audit($adapter);
|
||||
$audit = new Audit($this->getInternalDB($projectId));
|
||||
$status = $audit->cleanup($timestamp);
|
||||
if (!$status) {
|
||||
throw new Exception('Failed to delete Audit logs for project'.$projectId);
|
||||
|
|
@ -373,4 +371,18 @@ class DeletesV1 extends Worker
|
|||
|
||||
return $projectDB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Database2
|
||||
*/
|
||||
protected function getInternalDB($projectId): Database2
|
||||
{
|
||||
global $register;
|
||||
|
||||
$cache = new Cache(new RedisCache($register->get('cache')));
|
||||
$dbForInternal = new Database2(new MariaDB($register->get('db')), $cache);
|
||||
$dbForInternal->setNamespace('project_'.$projectId.'_internal'); // Main DB
|
||||
|
||||
return $dbForInternal;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@
|
|||
"appwrite/php-runtimes": "0.2.*",
|
||||
|
||||
"utopia-php/framework": "0.14.*",
|
||||
"utopia-php/abuse": "0.4.*",
|
||||
"utopia-php/abuse": "dev-feat-utopia-db-integration",
|
||||
"utopia-php/analytics": "0.2.*",
|
||||
"utopia-php/audit": "0.5.*",
|
||||
"utopia-php/audit": "dev-feat-utopia-db-integration",
|
||||
"utopia-php/cache": "0.4.*",
|
||||
"utopia-php/cli": "0.11.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
|
|
@ -62,6 +62,16 @@
|
|||
"adhocore/jwt": "1.1.2",
|
||||
"slickdeals/statsd": "3.0.2"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/lohanidamodar/audit"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/lohanidamodar/abuse"
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"appwrite/sdk-generator": "0.10.11",
|
||||
"swoole/ide-helper": "4.6.6",
|
||||
|
|
|
|||
55
composer.lock
generated
55
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2d21d6dff0d1764f94854a32d5312b0d",
|
||||
"content-hash": "e3617b2fd699e599dc2c1d7ed74c9f44",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -1603,21 +1603,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/abuse",
|
||||
"version": "0.4.1",
|
||||
"version": "dev-feat-utopia-db-integration",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/abuse.git",
|
||||
"reference": "8b7973aae4b02489bd22ffea45b985608f13b6d9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/8b7973aae4b02489bd22ffea45b985608f13b6d9",
|
||||
"reference": "8b7973aae4b02489bd22ffea45b985608f13b6d9",
|
||||
"shasum": ""
|
||||
"url": "https://github.com/lohanidamodar/abuse",
|
||||
"reference": "4f3349b3c1c85353708d13f7eb3c34c0762d4828"
|
||||
},
|
||||
"require": {
|
||||
"ext-pdo": "*",
|
||||
"php": ">=7.4"
|
||||
"php": ">=7.4",
|
||||
"utopia-php/database": "0.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.4",
|
||||
|
|
@ -1629,7 +1624,6 @@
|
|||
"Utopia\\Abuse\\": "src/Abuse"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
|
|
@ -1641,17 +1635,13 @@
|
|||
],
|
||||
"description": "A simple abuse library to manage application usage limits",
|
||||
"keywords": [
|
||||
"Abuse",
|
||||
"abuse",
|
||||
"framework",
|
||||
"php",
|
||||
"upf",
|
||||
"utopia"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/abuse/issues",
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.4.1"
|
||||
},
|
||||
"time": "2021-06-05T14:31:33+00:00"
|
||||
"time": "2021-06-09T09:11:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/analytics",
|
||||
|
|
@ -1710,21 +1700,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/audit",
|
||||
"version": "0.5.1",
|
||||
"version": "dev-feat-utopia-db-integration",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/audit.git",
|
||||
"reference": "154a850170a58667a15e4b65fbabb6cd0b709dd9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/154a850170a58667a15e4b65fbabb6cd0b709dd9",
|
||||
"reference": "154a850170a58667a15e4b65fbabb6cd0b709dd9",
|
||||
"shasum": ""
|
||||
"url": "https://github.com/lohanidamodar/audit",
|
||||
"reference": "b3b85524717bbf52cfe71f01474c4012bfd4323a"
|
||||
},
|
||||
"require": {
|
||||
"ext-pdo": "*",
|
||||
"php": ">=7.1"
|
||||
"php": ">=7.4",
|
||||
"utopia-php/database": "0.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3",
|
||||
|
|
@ -1736,7 +1721,6 @@
|
|||
"Utopia\\Audit\\": "src/Audit"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
|
|
@ -1748,17 +1732,13 @@
|
|||
],
|
||||
"description": "A simple audit library to manage application users logs",
|
||||
"keywords": [
|
||||
"Audit",
|
||||
"audit",
|
||||
"framework",
|
||||
"php",
|
||||
"upf",
|
||||
"utopia"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/audit/issues",
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.5.1"
|
||||
},
|
||||
"time": "2020-12-21T17:28:53+00:00"
|
||||
"time": "2021-06-09T09:10:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
|
|
@ -6190,7 +6170,10 @@
|
|||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"utopia-php/abuse": 20,
|
||||
"utopia-php/audit": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue