Compare commits

...
Author SHA1 Message Date
Damodar Lohani ad36bb32f2 Merge remote-tracking branch 'origin/1.6.x' into feat-docker-geo 2025-01-07 02:59:27 +00:00
Damodar Lohani c66d963200 set new attributes on session document 2024-11-26 07:17:23 +00:00
Damodar Lohani 53b1e1201c new attributes 2024-11-26 06:43:44 +00:00
Damodar Lohani 448dde3913 remove unused injects 2024-11-12 09:10:02 +00:00
Damodar Lohani d60fac7f8d Merge remote-tracking branch 'origin/feat-custom-cf-hostnames' into feat-docker-geo 2024-11-12 09:08:40 +00:00
Jake Barnby 316693798e Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-12 21:44:50 +13:00
Damodar Lohani 5d79dcb6f9 fix typo 2024-11-11 04:42:55 +00:00
Damodar Lohani fe0aa823d5 update to use geoRecord 2024-11-10 09:51:39 +00:00
Damodar Lohani ade9db7ef0 update to use geo record 2024-11-10 09:36:40 +00:00
Damodar LohaniandGitHub fbff7ec90e Merge branch '1.6.x' into feat-docker-geo 2024-11-10 14:52:47 +05:45
Christy Jacob 76216c3bf6 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-09 16:01:16 +00:00
loks0n c8c4576bbc Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-09 13:07:15 +01:00
loks0n dac8766eb4 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 22:02:31 +01:00
loks0n f6de256220 chore: composer update 2024-11-08 21:50:33 +01:00
loks0n 2f9b44930f Revert "Merge pull request #8946 from appwrite/chore-update-database"
This reverts commit c0bd1664be, reversing
changes made to b42dd86451.
2024-11-08 21:48:27 +01:00
loks0n 627df0d11f chore: remove redundant compression 2024-11-08 20:24:55 +01:00
loks0n fcd323baa4 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 20:24:35 +01:00
loks0n 0009b73b06 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-08 16:53:22 +01:00
Jake Barnby 030e26b223 Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-08 23:33:10 +13:00
loks0n 472f167b4a Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-07 20:31:41 +01:00
Fabian Gruber b4c986839e Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-11-06 12:40:56 +01:00
Damodar LohaniandGitHub d425c9f071 Merge pull request #8930 from appwrite/pathc-update-utopia-storage
upgrade utopia storage
2024-11-06 16:01:56 +05:45
Damodar Lohani e219ee2d84 upgrade utopia storage 2024-11-06 10:02:11 +00:00
Jake Barnby e66d0216c6 Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-06 17:02:06 +13:00
Damodar Lohani 9532631d90 refactor resource 2024-11-06 02:38:54 +00:00
Steven NguyenandGitHub e3e20d2923 Merge pull request #8922 from appwrite/lohanidamodar-patch-4
Improve compression param checks
2024-11-05 17:35:39 -08:00
loks0n e0c503e249 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-11-05 19:47:29 +01:00
Jake Barnby 228cabab3a Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-05 23:38:24 +13:00
Damodar Lohani 028c5366c2 make compression nullable and assign default in action
- also update the `update bucket` endpoint
2024-11-05 08:12:58 +00:00
Damodar LohaniandGitHub cca0c3ae45 Make compression param whitelist strict 2024-11-05 12:59:11 +05:45
Jake Barnby 0b85a64dab Merge remote-tracking branch 'origin/1.6.x' into feat-custom-cf-hostnames 2024-11-04 22:44:25 +13:00
Jake BarnbyandGitHub 75e8635563 Merge pull request #8904 from appwrite/1.6.x
Merge 1.6.x into feat-custom-cf-hostnames
2024-10-31 22:12:38 +13:00
Fabian Gruber 6e3160c502 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-29 16:15:54 +01:00
Fabian Gruber 104ec3188f Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-29 15:36:38 +01:00
Damodar Lohani 73ea15d839 fix type 2024-10-27 08:08:08 +00:00
Damodar LohaniandGitHub c7bd5f2db5 Merge branch '1.6.x' into feat-docker-geo 2024-10-27 13:27:04 +05:45
Damodar Lohani 005e196324 add type definitions 2024-10-27 07:15:51 +00:00
Damodar Lohani 68bc1a4fd7 fix missing injections 2024-10-27 07:11:12 +00:00
Fabian Gruber b47a4703c4 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-25 13:39:12 +02:00
Fabian Gruber 4ceff430f9 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-24 12:49:26 +02:00
Christy JacobandGitHub 5603516d88 Merge branch '1.6.x' into feat-custom-cf-hostnames 2024-10-23 23:56:43 +04:00
Christy Jacob 54f39494c0 Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-custom-cf-hostnames 2024-10-22 19:51:03 +00:00
Christy Jacob ae4edf119f chore: linter 2024-10-22 19:49:10 +00:00
Fabian GruberandChristy Jacob a56293e018 chore: replace 'Expires' with 'Cache-Control: private' header to avoid CDN caching 2024-10-22 12:18:58 +00:00
Christy Jacob 5ea83b8827 chore: update cert generation 2024-10-18 23:45:42 +00:00
Christy Jacob 6fe7d92fea chore: update cert generation 2024-10-18 22:32:03 +00:00
Christy Jacob 28b02a4ba8 chore: fix bug 2024-10-18 21:18:20 +00:00
Christy Jacob f4d456fa4c chore: updat certs logic 2024-10-18 20:52:29 +00:00
Fabian Gruber 687252b15b fix adding custom hostname & error logging 2024-10-18 22:21:53 +02:00
Fabian Gruber f21b1c87a6 fix missing ssl object 2024-10-18 22:07:36 +02:00
Fabian Gruber ccbde6c470 fix zone id 2024-10-18 21:44:36 +02:00
Torsten Dittmann f189c41421 temp: custom cloudflare hostnames 2024-10-18 21:39:16 +02:00
Damodar Lohani b939e452a2 refactor geo record 2024-10-02 10:11:36 +00:00
Damodar Lohani ebb1da8b31 rough implementation of geodb docker service 2024-10-02 09:26:07 +00:00
15 changed files with 426 additions and 234 deletions
+1
View File
@@ -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
+132
View File
@@ -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,
+66 -30
View File
@@ -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([
+12 -34
View File
@@ -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([
+6 -19
View File
@@ -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) {
+3 -40
View File
@@ -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
+16 -45
View File
@@ -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([
+19 -16
View File
@@ -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),
+19 -16
View File
@@ -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
View File
@@ -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 -5
View File
@@ -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);
}
+61
View File
@@ -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');
+9
View File
@@ -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.
*
+32
View File
@@ -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);
}
}