mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad36bb32f2 | ||
|
|
c66d963200 | ||
|
|
53b1e1201c | ||
|
|
448dde3913 | ||
|
|
d60fac7f8d | ||
|
|
316693798e | ||
|
|
5d79dcb6f9 | ||
|
|
fe0aa823d5 | ||
|
|
ade9db7ef0 | ||
|
|
fbff7ec90e | ||
|
|
76216c3bf6 | ||
|
|
c8c4576bbc | ||
|
|
dac8766eb4 | ||
|
|
f6de256220 | ||
|
|
2f9b44930f | ||
|
|
627df0d11f | ||
|
|
fcd323baa4 | ||
|
|
0009b73b06 | ||
|
|
030e26b223 | ||
|
|
472f167b4a | ||
|
|
b4c986839e | ||
|
|
d425c9f071 | ||
|
|
e219ee2d84 | ||
|
|
e66d0216c6 | ||
|
|
9532631d90 | ||
|
|
e3e20d2923 | ||
|
|
e0c503e249 | ||
|
|
228cabab3a | ||
|
|
028c5366c2 | ||
|
|
cca0c3ae45 | ||
|
|
0b85a64dab | ||
|
|
75e8635563 | ||
|
|
6e3160c502 | ||
|
|
104ec3188f | ||
|
|
73ea15d839 | ||
|
|
c7bd5f2db5 | ||
|
|
005e196324 | ||
|
|
68bc1a4fd7 | ||
|
|
b47a4703c4 | ||
|
|
4ceff430f9 | ||
|
|
5603516d88 | ||
|
|
54f39494c0 | ||
|
|
ae4edf119f | ||
|
|
a56293e018 | ||
|
|
5ea83b8827 | ||
|
|
6fe7d92fea | ||
|
|
28b02a4ba8 | ||
|
|
f4d456fa4c | ||
|
|
687252b15b | ||
|
|
f21b1c87a6 | ||
|
|
ccbde6c470 | ||
|
|
f189c41421 | ||
|
|
b939e452a2 | ||
|
|
ebb1da8b31 |
@@ -109,4 +109,5 @@ _APP_MESSAGE_EMAIL_TEST_DSN=
|
||||
_APP_MESSAGE_PUSH_TEST_DSN=
|
||||
_APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10
|
||||
_APP_PROJECT_REGIONS=default
|
||||
_APP_GEO_SECRET=geo-secret-key
|
||||
_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000
|
||||
|
||||
@@ -825,6 +825,138 @@ $commonCollections = [
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('continentCode'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 2,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('latitude'),
|
||||
'type' => Database::VAR_FLOAT,
|
||||
'format' => '',
|
||||
'size' => 2,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('longitude'),
|
||||
'type' => Database::VAR_FLOAT,
|
||||
'format' => '',
|
||||
'size' => 2,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('timeZone'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('weatherCode'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('postalCode'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('autonomousSystemNumber'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('autonomousSystemOrganization'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('connectionType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('userType'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('organization'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('isp'),
|
||||
'type' => Database::VAR_STRING,
|
||||
'format' => '',
|
||||
'size' => 255,
|
||||
'signed' => true,
|
||||
'required' => false,
|
||||
'default' => null,
|
||||
'array' => false,
|
||||
'filters' => [],
|
||||
],
|
||||
[
|
||||
'$id' => ID::custom('osCode'),
|
||||
'type' => Database::VAR_STRING,
|
||||
|
||||
@@ -27,7 +27,6 @@ use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Identities;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit as EventAudit;
|
||||
use Utopia\Config\Config;
|
||||
@@ -146,7 +145,7 @@ function sendSessionAlert(Locale $locale, Document $user, Document $project, Doc
|
||||
};
|
||||
|
||||
|
||||
$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails) {
|
||||
$createSession = function (string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, array $geoRecord, Event $queueForEvents, Mail $queueForMails) {
|
||||
$roles = Authorization::getRoles();
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
$isAppUser = Auth::isAppUser($roles);
|
||||
@@ -168,7 +167,6 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$sessionSecret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
|
||||
|
||||
$factor = (match ($verifiedToken->getAttribute('type')) {
|
||||
@@ -190,7 +188,19 @@ $createSession = function (string $userId, string $secret, Request $request, Res
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'factors' => [$factor],
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => strtolower($geoRecord['countryCode']),
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => DateTime::addSeconds(new \DateTime(), $duration)
|
||||
],
|
||||
$detector->getOS(),
|
||||
@@ -817,11 +827,11 @@ App::post('/v1/account/sessions/email')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->inject('hooks')
|
||||
->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents, Mail $queueForMails, Hooks $hooks) {
|
||||
->action(function (string $email, string $password, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Locale $locale, array $geoRecord, Event $queueForEvents, Mail $queueForMails, Hooks $hooks) {
|
||||
$email = \strtolower($email);
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
@@ -847,7 +857,6 @@ App::post('/v1/account/sessions/email')
|
||||
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
|
||||
$session = new Document(array_merge(
|
||||
[
|
||||
@@ -860,7 +869,19 @@ App::post('/v1/account/sessions/email')
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'factors' => ['password'],
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => $geoRecord['countryCode'],
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => DateTime::addSeconds(new \DateTime(), $duration)
|
||||
],
|
||||
$detector->getOS(),
|
||||
@@ -949,9 +970,9 @@ App::post('/v1/account/sessions/anonymous')
|
||||
->inject('user')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, Reader $geodb, Event $queueForEvents) {
|
||||
->action(function (Request $request, Response $response, Locale $locale, Document $user, Document $project, Database $dbForProject, array $geoRecord, Event $queueForEvents) {
|
||||
$protocol = $request->getProtocol();
|
||||
$roles = Authorization::getRoles();
|
||||
$isPrivilegedUser = Auth::isPrivilegedUser($roles);
|
||||
@@ -1004,7 +1025,6 @@ App::post('/v1/account/sessions/anonymous')
|
||||
// Create session token
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
|
||||
|
||||
$session = new Document(array_merge(
|
||||
@@ -1017,7 +1037,19 @@ App::post('/v1/account/sessions/anonymous')
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'factors' => ['anonymous'],
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => $geoRecord['countryCode'],
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => DateTime::addSeconds(new \DateTime(), $duration)
|
||||
],
|
||||
$detector->getOS(),
|
||||
@@ -1088,7 +1120,7 @@ App::post('/v1/account/sessions/token')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action($createSession);
|
||||
@@ -1246,9 +1278,9 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
->inject('project')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, Reader $geodb, Event $queueForEvents) use ($oauthDefaultSuccess) {
|
||||
->action(function (string $provider, string $code, string $state, string $error, string $error_description, Request $request, Response $response, Document $project, Document $user, Database $dbForProject, array $geoRecord, Event $queueForEvents) use ($oauthDefaultSuccess) {
|
||||
$protocol = $request->getProtocol();
|
||||
$callback = $protocol . '://' . $request->getHostname() . '/v1/account/sessions/oauth2/callback/' . $provider . '/' . $project->getId();
|
||||
$defaultState = ['success' => $project->getAttribute('url', ''), 'failure' => ''];
|
||||
@@ -1604,7 +1636,6 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
// If the `token` param is not set, we persist the session in a cookie
|
||||
} else {
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
|
||||
|
||||
$session = new Document(array_merge([
|
||||
@@ -1620,7 +1651,19 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect')
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'factors' => [TYPE::EMAIL, 'oauth2'], // include a special oauth2 factor to bypass MFA checks
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => $geoRecord['countryCode'],
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => DateTime::addSeconds(new \DateTime(), $duration)
|
||||
], $detector->getOS(), $detector->getClient(), $detector->getDevice()));
|
||||
|
||||
@@ -2251,7 +2294,7 @@ App::put('/v1/account/sessions/magic-url')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action($createSession);
|
||||
@@ -2282,7 +2325,7 @@ App::put('/v1/account/sessions/phone')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForMails')
|
||||
->action($createSession);
|
||||
@@ -2549,9 +2592,9 @@ App::get('/v1/account/logs')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('dbForProject')
|
||||
->action(function (array $queries, Response $response, Document $user, Locale $locale, Reader $geodb, Database $dbForProject) {
|
||||
->action(function (array $queries, Response $response, Document $user, Locale $locale, array $geoRecord, Database $dbForProject) {
|
||||
|
||||
try {
|
||||
$queries = Query::parseQueries($queries);
|
||||
@@ -2582,15 +2625,8 @@ App::get('/v1/account/logs')
|
||||
$detector->getDevice()
|
||||
));
|
||||
|
||||
$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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
|
||||
@@ -14,7 +14,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Databases;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Indexes;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Config\Config;
|
||||
@@ -622,8 +621,8 @@ App::get('/v1/databases/:databaseId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $databaseId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
|
||||
$database = $dbForProject->getDocument('databases', $databaseId);
|
||||
|
||||
@@ -679,15 +678,8 @@ App::get('/v1/databases/:databaseId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCountry']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -972,8 +964,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
@@ -1031,15 +1023,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -3406,8 +3391,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $databaseId, string $collectionId, string $documentId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
|
||||
$database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId));
|
||||
|
||||
@@ -3475,15 +3460,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
|
||||
@@ -22,7 +22,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Functions;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model\Rule;
|
||||
use Executor\Executor;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\Abuse\Abuse;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
@@ -1795,8 +1794,8 @@ App::post('/v1/functions/:functionId/executions')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('geodb')
|
||||
->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForPlatform, Document $user, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $functionId, string $body, mixed $async, string $path, string $method, mixed $headers, ?string $scheduledAt, Response $response, Request $request, Document $project, Database $dbForProject, Database $dbForPlatform, Document $user, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, array $geoRecord) {
|
||||
$async = \strval($async) === 'true' || \strval($async) === '1';
|
||||
|
||||
if (!$async && !is_null($scheduledAt)) {
|
||||
@@ -1904,22 +1903,10 @@ App::post('/v1/functions/:functionId/executions')
|
||||
$headers['x-appwrite-trigger'] = 'http';
|
||||
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
|
||||
$headers['x-appwrite-user-jwt'] = $jwt ?? '';
|
||||
$headers['x-appwrite-country-code'] = '';
|
||||
$headers['x-appwrite-continent-code'] = '';
|
||||
$headers['x-appwrite-continent-eu'] = 'false';
|
||||
|
||||
$ip = $headers['x-real-ip'] ?? '';
|
||||
if (!empty($ip)) {
|
||||
$record = $geodb->get($ip);
|
||||
|
||||
if ($record) {
|
||||
$eu = Config::getParam('locale-eu');
|
||||
|
||||
$headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? '';
|
||||
$headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? '';
|
||||
$headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false';
|
||||
}
|
||||
}
|
||||
$headers['x-appwrite-country-code'] = $geoRecord['countryCode'];
|
||||
$headers['x-appwrite-continent-code'] = $geoRecord['contenentCode'];
|
||||
$eu = Config::getParam('locale-eu');
|
||||
$headers['x-appwrite-continent-eu'] = (\in_array($record['countryCode'], $eu)) ? 'true' : 'false';
|
||||
|
||||
$headersFiltered = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Document;
|
||||
@@ -21,46 +19,11 @@ App::get('/v1/locale')
|
||||
->label('sdk.response.model', Response::MODEL_LOCALE)
|
||||
->label('sdk.offline.model', '/localed')
|
||||
->label('sdk.offline.key', 'current')
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (Request $request, Response $response, Locale $locale, Reader $geodb) {
|
||||
$eu = Config::getParam('locale-eu');
|
||||
$currencies = Config::getParam('locale-currencies');
|
||||
$output = [];
|
||||
$ip = $request->getIP();
|
||||
->inject('geoRecord')
|
||||
->action(function (Response $response, array $geoRecord) {
|
||||
$time = (60 * 60 * 24 * 45); // 45 days cache
|
||||
|
||||
$output['ip'] = $ip;
|
||||
|
||||
$currency = null;
|
||||
|
||||
$record = $geodb->get($ip);
|
||||
|
||||
if ($record) {
|
||||
$output['countryCode'] = $record['country']['iso_code'];
|
||||
$output['country'] = $locale->getText('countries.' . strtolower($record['country']['iso_code']), $locale->getText('locale.country.unknown'));
|
||||
$output['continent'] = $locale->getText('continents.' . strtolower($record['continent']['code']), $locale->getText('locale.country.unknown'));
|
||||
$output['continentCode'] = $record['continent']['code'];
|
||||
$output['eu'] = (\in_array($record['country']['iso_code'], $eu)) ? true : false;
|
||||
|
||||
foreach ($currencies as $code => $element) {
|
||||
if (isset($element['locations']) && isset($element['code']) && \in_array($record['country']['iso_code'], $element['locations'])) {
|
||||
$currency = $element['code'];
|
||||
}
|
||||
}
|
||||
|
||||
$output['currency'] = $currency;
|
||||
} else {
|
||||
$output['countryCode'] = '--';
|
||||
$output['country'] = $locale->getText('locale.country.unknown');
|
||||
$output['continent'] = $locale->getText('locale.country.unknown');
|
||||
$output['continentCode'] = '--';
|
||||
$output['eu'] = false;
|
||||
$output['currency'] = $currency;
|
||||
}
|
||||
|
||||
$output = $geoRecord;
|
||||
$response
|
||||
->addHeader('Cache-Control', 'public, max-age=' . $time)
|
||||
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
|
||||
|
||||
@@ -19,7 +19,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Subscribers;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Targets;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Topics;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Database\Database;
|
||||
@@ -916,8 +915,8 @@ App::get('/v1/messaging/providers/:providerId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $providerId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
$provider = $dbForProject->getDocument('providers', $providerId);
|
||||
|
||||
if ($provider->isEmpty()) {
|
||||
@@ -971,15 +970,8 @@ App::get('/v1/messaging/providers/:providerId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -2068,8 +2060,8 @@ App::get('/v1/messaging/topics/:topicId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $topicId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
$topic = $dbForProject->getDocument('topics', $topicId);
|
||||
|
||||
if ($topic->isEmpty()) {
|
||||
@@ -2124,15 +2116,8 @@ App::get('/v1/messaging/topics/:topicId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -2447,8 +2432,8 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $subscriberId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
$subscriber = $dbForProject->getDocument('subscribers', $subscriberId);
|
||||
|
||||
if ($subscriber->isEmpty()) {
|
||||
@@ -2503,15 +2488,8 @@ App::get('/v1/messaging/subscribers/:subscriberId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -3141,8 +3119,8 @@ App::get('/v1/messaging/messages/:messageId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
$message = $dbForProject->getDocument('messages', $messageId);
|
||||
|
||||
if ($message->isEmpty()) {
|
||||
@@ -3197,15 +3175,8 @@ App::get('/v1/messaging/messages/:messageId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
|
||||
@@ -17,7 +17,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Memberships;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Teams;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Config\Config;
|
||||
@@ -1031,9 +1030,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
->inject('user')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, Reader $geodb, Event $queueForEvents) {
|
||||
->action(function (string $teamId, string $membershipId, string $userId, string $secret, Request $request, Response $response, Document $user, Database $dbForProject, Document $project, array $geoRecord, Event $queueForEvents) {
|
||||
$protocol = $request->getProtocol();
|
||||
|
||||
$membership = $dbForProject->getDocument('memberships', $membershipId);
|
||||
@@ -1085,7 +1084,6 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
Authorization::setRole(Role::user($user->getId())->toString());
|
||||
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
$authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$expire = DateTime::addSeconds(new \DateTime(), $authDuration);
|
||||
$secret = Auth::tokenGenerator();
|
||||
@@ -1104,7 +1102,19 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'ip' => $request->getIP(),
|
||||
'factors' => ['email'],
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => \strtolower($geoRecord['countryCode']),
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => DateTime::addSeconds(new \DateTime(), $authDuration)
|
||||
], $detector->getOS(), $detector->getClient(), $detector->getDevice()));
|
||||
|
||||
@@ -1242,8 +1252,8 @@ App::get('/v1/teams/:teamId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $teamId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
|
||||
$team = $dbForProject->getDocument('teams', $teamId);
|
||||
|
||||
@@ -1299,15 +1309,8 @@ App::get('/v1/teams/:teamId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
$response->dynamic(new Document([
|
||||
'total' => $audit->countLogsByResource($resource),
|
||||
|
||||
@@ -21,7 +21,6 @@ use Appwrite\Utopia\Database\Validator\Queries\Targets;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Users;
|
||||
use Appwrite\Utopia\Request;
|
||||
use Appwrite\Utopia\Response;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Audit\Audit;
|
||||
use Utopia\Config\Config;
|
||||
@@ -763,8 +762,8 @@ App::get('/v1/users/:userId/logs')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (string $userId, array $queries, Response $response, Database $dbForProject, Locale $locale, array $geoRecord) {
|
||||
|
||||
$user = $dbForProject->getDocument('users', $userId);
|
||||
|
||||
@@ -819,15 +818,8 @@ App::get('/v1/users/:userId/logs')
|
||||
'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');
|
||||
}
|
||||
$output[$i]['countryCode'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), false) ? \strtolower($geoRecord['countryCode']) : '--';
|
||||
$output[$i]['countryName'] = $locale->getText('countries.' . strtolower($geoRecord['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
@@ -1781,9 +1773,9 @@ App::post('/v1/users/:userId/sessions')
|
||||
->inject('dbForProject')
|
||||
->inject('project')
|
||||
->inject('locale')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForEvents')
|
||||
->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, Reader $geodb, Event $queueForEvents) {
|
||||
->action(function (string $userId, Request $request, Response $response, Database $dbForProject, Document $project, Locale $locale, array $geoRecord, Event $queueForEvents) {
|
||||
$user = $dbForProject->getDocument('users', $userId);
|
||||
if ($user->isEmpty()) {
|
||||
throw new Exception(Exception::USER_NOT_FOUND);
|
||||
@@ -1791,7 +1783,6 @@ App::post('/v1/users/:userId/sessions')
|
||||
|
||||
$secret = Auth::tokenGenerator(Auth::TOKEN_LENGTH_SESSION);
|
||||
$detector = new Detector($request->getUserAgent('UNKNOWN'));
|
||||
$record = $geodb->get($request->getIP());
|
||||
|
||||
$duration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG;
|
||||
$expire = DateTime::formatTz(DateTime::addSeconds(new \DateTime(), $duration));
|
||||
@@ -1806,7 +1797,19 @@ App::post('/v1/users/:userId/sessions')
|
||||
'userAgent' => $request->getUserAgent('UNKNOWN'),
|
||||
'factors' => ['server'],
|
||||
'ip' => $request->getIP(),
|
||||
'countryCode' => ($record) ? \strtolower($record['country']['iso_code']) : '--',
|
||||
'countryCode' => \strtolower($geoRecord['countryCode']),
|
||||
'continentCode' => strtolower($geoRecord['continentCode']),
|
||||
'latitude' => $geoRecord['latitude'],
|
||||
'longitude' => $geoRecord['longitude'],
|
||||
'timeZone' => $geoRecord['timeZone'],
|
||||
'weatherCode' => $geoRecord['weatherCode'],
|
||||
'postalCode' => $geoRecord['postalCode'],
|
||||
'isp' => $geoRecord['isp'],
|
||||
'autonomousSystemNumber' => $geoRecord['autonomousSystemNumber'],
|
||||
'autonomousSystemOrganization' => $geoRecord['autonomousSystemOrganization'],
|
||||
'connectionType' => $geoRecord['connectionType'],
|
||||
'userType' => $geoRecord['userType'],
|
||||
'organization' => $geoRecord['organization'],
|
||||
'expire' => $expire,
|
||||
],
|
||||
$detector->getOS(),
|
||||
|
||||
+17
-29
@@ -20,7 +20,6 @@ use Appwrite\Utopia\Response\Filters\V17 as ResponseV17;
|
||||
use Appwrite\Utopia\Response\Filters\V18 as ResponseV18;
|
||||
use Appwrite\Utopia\View;
|
||||
use Executor\Executor;
|
||||
use MaxMind\Db\Reader;
|
||||
use Swoole\Http\Request as SwooleRequest;
|
||||
use Utopia\App;
|
||||
use Utopia\CLI\Console;
|
||||
@@ -46,7 +45,7 @@ Config::setParam('domainVerification', false);
|
||||
Config::setParam('cookieDomain', 'localhost');
|
||||
Config::setParam('cookieSamesite', Response::COOKIE_SAMESITE_NONE);
|
||||
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname)
|
||||
function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, SwooleRequest $swooleRequest, Request $request, Response $response, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, array $geoRecord, callable $isResourceBlocked, string $previewHostname)
|
||||
{
|
||||
$utopia->getRoute()?->label('error', __DIR__ . '/../views/general/error.phtml');
|
||||
|
||||
@@ -206,22 +205,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw
|
||||
$headers['x-appwrite-trigger'] = 'http';
|
||||
$headers['x-appwrite-user-id'] = '';
|
||||
$headers['x-appwrite-user-jwt'] = '';
|
||||
$headers['x-appwrite-country-code'] = '';
|
||||
$headers['x-appwrite-continent-code'] = '';
|
||||
$headers['x-appwrite-continent-eu'] = 'false';
|
||||
$headers['x-appwrite-country-code'] = $geoRecord['countryCode'];
|
||||
$headers['x-appwrite-continent-code'] = $geoRecord['contenentCode'];
|
||||
|
||||
$ip = $headers['x-real-ip'] ?? '';
|
||||
if (!empty($ip)) {
|
||||
$record = $geodb->get($ip);
|
||||
|
||||
if ($record) {
|
||||
$eu = Config::getParam('locale-eu');
|
||||
|
||||
$headers['x-appwrite-country-code'] = $record['country']['iso_code'] ?? '';
|
||||
$headers['x-appwrite-continent-code'] = $record['continent']['code'] ?? '';
|
||||
$headers['x-appwrite-continent-eu'] = (\in_array($record['country']['iso_code'], $eu)) ? 'true' : 'false';
|
||||
}
|
||||
}
|
||||
$eu = Config::getParam('locale-eu');
|
||||
$headers['x-appwrite-continent-eu'] = (\in_array($geoRecord['countryCode'], $eu)) ? 'true' : 'false';
|
||||
|
||||
$headersFiltered = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
@@ -473,14 +461,14 @@ App::init()
|
||||
->inject('locale')
|
||||
->inject('localeCodes')
|
||||
->inject('clients')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('queueForUsage')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForCertificates')
|
||||
->inject('queueForFunctions')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, Reader $geodb, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Document $console, Document $project, Database $dbForPlatform, callable $getProjectDB, Locale $locale, array $localeCodes, array $clients, array $geoRecord, Usage $queueForUsage, Event $queueForEvents, Certificate $queueForCertificates, Func $queueForFunctions, callable $isResourceBlocked, string $previewHostname) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -488,7 +476,7 @@ App::init()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geoRecord, $isResourceBlocked, $previewHostname)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -709,10 +697,10 @@ App::options()
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, array $geoRecord, callable $isResourceBlocked, string $previewHostname) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -720,7 +708,7 @@ App::options()
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
// Only run Router when external domain
|
||||
if ($host !== $mainDomain || !empty($previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname)) {
|
||||
if (router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geoRecord, $isResourceBlocked, $previewHostname)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1008,10 +996,10 @@ App::get('/robots.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, array $geoRecord, callable $isResourceBlocked, string $previewHostname) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1019,7 +1007,7 @@ App::get('/robots.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/robots.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname);
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geoRecord, $isResourceBlocked, $previewHostname);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1036,10 +1024,10 @@ App::get('/humans.txt')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForUsage')
|
||||
->inject('queueForFunctions')
|
||||
->inject('geodb')
|
||||
->inject('geoRecord')
|
||||
->inject('isResourceBlocked')
|
||||
->inject('previewHostname')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, Reader $geodb, callable $isResourceBlocked, string $previewHostname) {
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, Usage $queueForUsage, Func $queueForFunctions, array $geoRecord, callable $isResourceBlocked, string $previewHostname) {
|
||||
$host = $request->getHostname() ?? '';
|
||||
$mainDomain = System::getEnv('_APP_DOMAIN', '');
|
||||
|
||||
@@ -1047,7 +1035,7 @@ App::get('/humans.txt')
|
||||
$template = new View(__DIR__ . '/../views/general/humans.phtml');
|
||||
$response->text($template->render(false));
|
||||
} else {
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geodb, $isResourceBlocked, $previewHostname);
|
||||
router($utopia, $dbForPlatform, $getProjectDB, $swooleRequest, $request, $response, $queueForEvents, $queueForUsage, $queueForFunctions, $geoRecord, $isResourceBlocked, $previewHostname);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use Appwrite\Auth\Auth;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Utopia\Request;
|
||||
use MaxMind\Db\Reader;
|
||||
use Utopia\App;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
@@ -34,13 +33,12 @@ App::init()
|
||||
->inject('utopia')
|
||||
->inject('request')
|
||||
->inject('project')
|
||||
->inject('geodb')
|
||||
->action(function (App $utopia, Request $request, Document $project, Reader $geodb) {
|
||||
->inject('geoRecord')
|
||||
->action(function (App $utopia, Request $request, Document $project, array $geoRecord) {
|
||||
$denylist = System::getEnv('_APP_CONSOLE_COUNTRIES_DENYLIST', '');
|
||||
if (!empty($denylist && $project->getId() === 'console')) {
|
||||
$countries = explode(',', $denylist);
|
||||
$record = $geodb->get($request->getIP()) ?? [];
|
||||
$country = $record['country']['iso_code'] ?? '';
|
||||
$country = $geoRecord['countryCode'];
|
||||
if (in_array($country, $countries)) {
|
||||
throw new Exception(Exception::GENERAL_REGION_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\PubSub\Adapter\Redis as PubSub;
|
||||
use Appwrite\URL\URL as AppwriteURL;
|
||||
use Appwrite\Utopia\Fetch\Client;
|
||||
use Appwrite\Utopia\Request;
|
||||
use MaxMind\Db\Reader;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
@@ -1067,6 +1068,7 @@ $register->set('smtp', function () {
|
||||
$register->set('geodb', function () {
|
||||
return new Reader(__DIR__ . '/assets/dbip/dbip-country-lite-2024-09.mmdb');
|
||||
});
|
||||
|
||||
$register->set('passwordsDictionary', function () {
|
||||
$content = \file_get_contents(__DIR__ . '/assets/security/10k-common-passwords');
|
||||
$content = explode("\n", $content);
|
||||
@@ -1682,6 +1684,65 @@ App::setResource('geodb', function ($register) {
|
||||
return $register->get('geodb');
|
||||
}, ['register']);
|
||||
|
||||
App::setResource('geoRecord', function (Reader $geodb, Request $request, Locale $locale) {
|
||||
$ip = $request->getIp();
|
||||
$eu = Config::getParam('locale-eu');
|
||||
$currencies = Config::getParam('locale-currencies');
|
||||
|
||||
$client = new Client();
|
||||
$client->addHeader('Authorization', 'Bearer ' . System::getEnv('_APP_GEO_SECRET'));
|
||||
$client->setBaseUrl('http://appwrite-geo/v1');
|
||||
|
||||
$record = null;
|
||||
try {
|
||||
$record = $client->fetch("/ips/{$ip}", Client::METHOD_GET);
|
||||
$record = $record->json();
|
||||
} catch (Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
Console::error($th->getTraceAsString());
|
||||
$record = null;
|
||||
}
|
||||
|
||||
if (empty($record)) {
|
||||
// Fallback
|
||||
$dbRecord = $geodb->get($ip);
|
||||
if ($dbRecord) {
|
||||
$record = [];
|
||||
$record['countryCode'] = $dbRecord['country']['iso_code'];
|
||||
$record['country'] = $dbRecord['country']['names'];
|
||||
$record['continent'] = $dbRecord['continent']['names'];
|
||||
$record['continentCode'] = $dbRecord['continent']['code'];
|
||||
}
|
||||
}
|
||||
|
||||
$output = [];
|
||||
$output['ip'] = $ip;
|
||||
$currency = null;
|
||||
if (!empty($record)) {
|
||||
$output['countryCode'] = $record['countryCode'];
|
||||
$output['country'] = $locale->getText('countries.' . strtolower($record['countryCode']), $locale->getText('locale.country.unknown'));
|
||||
$output['continent'] = $locale->getText('continents.' . strtolower($record['continentCode']), $locale->getText('locale.country.unknown'));
|
||||
$output['continentCode'] = $record['continentCode'];
|
||||
$output['eu'] = (\in_array($record['countryCode'], $eu)) ? true : false;
|
||||
|
||||
foreach ($currencies as $code => $element) {
|
||||
if (isset($element['locations']) && isset($element['code']) && \in_array($record['countryCode'], $element['locations'])) {
|
||||
$currency = $element['code'];
|
||||
}
|
||||
}
|
||||
|
||||
$output['currency'] = $currency;
|
||||
} else {
|
||||
$output['countryCode'] = '--';
|
||||
$output['country'] = $locale->getText('locale.country.unknown');
|
||||
$output['continent'] = $locale->getText('locale.country.unknown');
|
||||
$output['continentCode'] = '--';
|
||||
$output['eu'] = false;
|
||||
$output['currency'] = $currency;
|
||||
}
|
||||
return $output;
|
||||
}, ['geodb', 'request', 'locale']);
|
||||
|
||||
App::setResource('passwordsDictionary', function ($register) {
|
||||
/** @var Utopia\Registry\Registry $register */
|
||||
return $register->get('passwordsDictionary');
|
||||
|
||||
@@ -193,6 +193,7 @@ services:
|
||||
- _APP_EXPERIMENT_LOGGING_PROVIDER
|
||||
- _APP_EXPERIMENT_LOGGING_CONFIG
|
||||
- _APP_DATABASE_SHARED_TABLES
|
||||
- _APP_GEO_SECRET
|
||||
- _APP_DATABASE_SHARED_TABLES_V1
|
||||
- _APP_DATABASE_SHARED_NAMESPACE
|
||||
- _APP_FUNCTIONS_CREATION_ABUSE_LIMIT
|
||||
@@ -874,6 +875,14 @@ services:
|
||||
- appwrite
|
||||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
|
||||
appwrite-geo:
|
||||
container_name: appwrite-geo
|
||||
image: appwrite/geo:0.1.0
|
||||
networks:
|
||||
- appwrite
|
||||
environment:
|
||||
- GEO_SECRET=$_APP_GEO_SECRET
|
||||
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
|
||||
@@ -22,6 +22,7 @@ use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Domains\Domain;
|
||||
use Utopia\Fetch\Client;
|
||||
use Utopia\Locale\Locale;
|
||||
use Utopia\Logger\Log;
|
||||
use Utopia\Platform\Action;
|
||||
@@ -189,6 +190,35 @@ class Certificates extends Action
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom hostname to Cloudflare registrar
|
||||
*
|
||||
* @param Document $project
|
||||
* @param string $hostname
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function addCustomHostnameToRegistrar(Document $project, string $hostname): void
|
||||
{
|
||||
$client = new Client();
|
||||
$client
|
||||
->addHeader('content-type', Client::CONTENT_TYPE_APPLICATION_JSON)
|
||||
->addHeader('Authorization', 'Bearer ' . System::getEnv('_APP_SYSTEM_CLOUDFLARE_TOKEN'));
|
||||
|
||||
$response = $client->fetch("https://api.cloudflare.com/client/v4/zones/b2d0e62383d3c0f6299efab107af2c7a/custom_hostnames", Client::METHOD_POST, [
|
||||
'hostname' => $hostname,
|
||||
'ssl' => [
|
||||
"method" => "http",
|
||||
"type" => "dv",
|
||||
"wildcard" => false
|
||||
]
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() !== 201) {
|
||||
throw new Exception('Failed to add custom hostname to Cloudflare: ' . $response->getBody());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save certificate data into database.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Utopia\Fetch;
|
||||
|
||||
use Utopia\Fetch\Client as UtopiaClient;
|
||||
use Utopia\Fetch\Response;
|
||||
|
||||
class Client extends UtopiaClient
|
||||
{
|
||||
protected string $baseUrl = '';
|
||||
|
||||
public function setBaseUrl(string $baseUrl): void
|
||||
{
|
||||
$this->baseUrl = $baseUrl;
|
||||
}
|
||||
|
||||
public function getBaseUrl(): string
|
||||
{
|
||||
return $this->baseUrl;
|
||||
}
|
||||
|
||||
public function fetch(
|
||||
string $url,
|
||||
string $method = self::METHOD_GET,
|
||||
array $body = [],
|
||||
array $query = [],
|
||||
): Response {
|
||||
$url = "{$this->baseUrl}{$url}";
|
||||
return parent::fetch($url, $method, $body, $query);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user