1
0
Fork 0
mirror of synced 2024-10-02 10:16:27 +13:00

adds log api in messaging controller

This commit is contained in:
Prateek Banga 2023-11-02 18:00:17 +05:30
parent 61d46bee5c
commit f97d1fa9e3
3 changed files with 387 additions and 5 deletions

View file

@ -1,5 +1,6 @@
<?php
use Appwrite\Detector\Detector;
use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Messaging;
@ -14,6 +15,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Subscribers;
use Appwrite\Utopia\Database\Validator\Queries\Topics;
use Appwrite\Utopia\Response;
use Utopia\App;
use Utopia\Audit\Audit;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate as DuplicateException;
@ -21,7 +23,11 @@ use Utopia\Database\Helpers\ID;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Database\Validator\Datetime as DatetimeValidator;
use Utopia\Database\Validator\Queries;
use Utopia\Database\Validator\Query\Limit;
use Utopia\Database\Validator\Query\Offset;
use Utopia\Database\Validator\UID;
use Utopia\Locale\Locale;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Boolean;
use Utopia\Validator\JSON;
@ -653,6 +659,90 @@ App::get('/v1/messaging/providers')
]), Response::MODEL_PROVIDER_LIST);
});
App::get('/v1/messaging/providers/:providerId/logs')
->desc('List provider logs')
->groups(['api', 'messaging'])
->label('scope', 'providers.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'messaging')
->label('sdk.method', 'listProviderLogs')
->label('sdk.description', '/docs/references/messaging/providers/get-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('providerId', '', new UID(), 'Provider ID.')
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
$provider = $dbForProject->getDocument('providers', $providerId);
if ($provider->isEmpty()) {
throw new Exception(Exception::PROVIDER_NOT_FOUND);
}
$queries = Query::parseQueries($queries);
$grouped = Query::groupByType($queries);
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$resource = 'provider/' . $providerId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => ID::custom($log['data']['userId']),
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::get('/v1/messaging/providers/:providerId')
->desc('Get provider')
->groups(['api', 'messaging'])
@ -1560,6 +1650,90 @@ App::get('/v1/messaging/topics')
]), Response::MODEL_TOPIC_LIST);
});
App::get('/v1/messaging/topics/:topicId/logs')
->desc('List topic logs')
->groups(['api', 'messaging'])
->label('scope', 'topics.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'messaging')
->label('sdk.method', 'listTopicLogs')
->label('sdk.description', '/docs/references/messaging/topics/get-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('topicId', '', new UID(), 'Topic ID.')
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
$topic = $dbForProject->getDocument('topics', $topicId);
if ($topic->isEmpty()) {
throw new Exception(Exception::TOPIC_NOT_FOUND);
}
$queries = Query::parseQueries($queries);
$grouped = Query::groupByType($queries);
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$resource = 'topic/' . $topicId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => ID::custom($log['data']['userId']),
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::get('/v1/messaging/topics/:topicId')
->desc('Get a topic.')
->groups(['api', 'messaging'])
@ -1792,6 +1966,90 @@ App::get('/v1/messaging/topics/:topicId/subscribers')
]), Response::MODEL_SUBSCRIBER_LIST);
});
App::get('/v1/messaging/subscribers/:subscriberId/logs')
->desc('List subscriber logs')
->groups(['api', 'messaging'])
->label('scope', 'subscribers.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'messaging')
->label('sdk.method', 'listSubscriberLogs')
->label('sdk.description', '/docs/references/messaging/subscribers/get-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('subscriberId', '', new UID(), 'Subscriber ID.')
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
$subscriber = $dbForProject->getDocument('subscribers', $subscriberId);
if ($subscriber->isEmpty()) {
throw new Exception(Exception::SUBSCRIBER_NOT_FOUND);
}
$queries = Query::parseQueries($queries);
$grouped = Query::groupByType($queries);
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$resource = 'subscriber/' . $subscriberId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => ID::custom($log['data']['userId']),
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::get('/v1/messaging/topics/:topicId/subscriber/:subscriberId')
->desc('Get a topic\'s subscriber.')
->groups(['api', 'messaging'])
@ -2141,6 +2399,90 @@ App::get('/v1/messaging/messages')
]), Response::MODEL_MESSAGE_LIST);
});
App::get('/v1/messaging/messages/:messageId/logs')
->desc('List message logs')
->groups(['api', 'messaging'])
->label('scope', 'messages.read')
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
->label('sdk.namespace', 'messaging')
->label('sdk.method', 'listMessageLogs')
->label('sdk.description', '/docs/references/messaging/messages/get-logs.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_LOG_LIST)
->param('messageId', '', new UID(), 'Message ID.')
->param('queries', [], new Queries([new Limit(), new Offset()]), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset', true)
->inject('response')
->inject('dbForProject')
->inject('locale')
->inject('geodb')
->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
$message = $dbForProject->getDocument('messages', $messageId);
if ($message->isEmpty()) {
throw new Exception(Exception::MESSAGE_NOT_FOUND);
}
$queries = Query::parseQueries($queries);
$grouped = Query::groupByType($queries);
$limit = $grouped['limit'] ?? APP_LIMIT_COUNT;
$offset = $grouped['offset'] ?? 0;
$audit = new Audit($dbForProject);
$resource = 'message/' . $messageId;
$logs = $audit->getLogsByResource($resource, $limit, $offset);
$output = [];
foreach ($logs as $i => &$log) {
$log['userAgent'] = (!empty($log['userAgent'])) ? $log['userAgent'] : 'UNKNOWN';
$detector = new Detector($log['userAgent']);
$detector->skipBotDetection(); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
$os = $detector->getOS();
$client = $detector->getClient();
$device = $detector->getDevice();
$output[$i] = new Document([
'event' => $log['event'],
'userId' => ID::custom($log['data']['userId']),
'userEmail' => $log['data']['userEmail'] ?? null,
'userName' => $log['data']['userName'] ?? null,
'mode' => $log['data']['mode'] ?? null,
'ip' => $log['ip'],
'time' => $log['time'],
'osCode' => $os['osCode'],
'osName' => $os['osName'],
'osVersion' => $os['osVersion'],
'clientType' => $client['clientType'],
'clientCode' => $client['clientCode'],
'clientName' => $client['clientName'],
'clientVersion' => $client['clientVersion'],
'clientEngine' => $client['clientEngine'],
'clientEngineVersion' => $client['clientEngineVersion'],
'deviceName' => $device['deviceName'],
'deviceBrand' => $device['deviceBrand'],
'deviceModel' => $device['deviceModel']
]);
$record = $geodb->get($log['ip']);
if ($record) {
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), false) ? \strtolower($record['country']['iso_code']) : '--';
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
} else {
$output[$i]['countryCode'] = '--';
$output[$i]['countryName'] = $locale->getText('locale.country.unknown');
}
}
$response->dynamic(new Document([
'total' => $audit->countLogsByResource($resource),
'logs' => $output,
]), Response::MODEL_LOG_LIST);
});
App::get('/v1/messaging/messages/:messageId')
->desc('Get a message')
->groups(['api', 'messaging'])

View file

@ -9,6 +9,7 @@ use Appwrite\Event\Event;
use Appwrite\Network\Validator\Email;
use Appwrite\Utopia\Database\Validator\CustomId;
use Appwrite\Utopia\Database\Validator\Queries\Identities;
use Appwrite\Utopia\Database\Validator\Queries\Targets;
use Utopia\Database\Validator\Queries;
use Appwrite\Utopia\Database\Validator\Queries\Users;
use Utopia\Database\Validator\Query\Limit;
@ -753,20 +754,38 @@ App::get('/v1/users/:userId/targets')
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_TARGET_LIST)
->param('userId', '', new UID(), 'User ID.')
->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Users::ALLOWED_ATTRIBUTES), true)
->inject('response')
->inject('dbForProject')
->action(function (string $userId, Response $response, Database $dbForProject) {
->action(function (string $userId, array $queries, Response $response, Database $dbForProject) {
$user = $dbForProject->getDocument('users', $userId);
if ($user->isEmpty()) {
throw new Exception(Exception::USER_NOT_FOUND);
}
$targets = $user->getAttribute('targets', []);
$queries = Query::parseQueries($queries);
$queries[] = Query::equal('userId', [$userId]);
// Get cursor document if there was a cursor query
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
$cursor = reset($cursor);
if ($cursor) {
$targetId = $cursor->getValue();
$cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('targets', $targetId));
if ($cursorDocument->isEmpty()) {
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Target '{$targetId}' for the 'cursor' value not found.");
}
$cursor->setValue($cursorDocument);
}
$response->dynamic(new Document([
'targets' => $targets,
'total' => \count($targets),
'targets' => $dbForProject->find('targets', $queries),
'total' => $dbForProject->count('targets', $queries, APP_LIMIT_COUNT),
]), Response::MODEL_TARGET_LIST);
});

View file

@ -0,0 +1,21 @@
<?php
namespace Appwrite\Utopia\Database\Validator\Queries;
class Targets extends Base
{
public const ALLOWED_ATTRIBUTES = [
'userId',
'providerId',
'identifier',
];
/**
* Expression constructor
*
*/
public function __construct()
{
parent::__construct('targets', self::ALLOWED_ATTRIBUTES);
}
}