From 4f67db160bf4d991e820741e8d3183b596fc80f1 Mon Sep 17 00:00:00 2001 From: achraf112ben Date: Sun, 28 Jan 2024 06:14:21 +0100 Subject: [PATCH 01/42] Adding Darija (Moroccan Arabic) translation file --- app/config/locale/translations/ar-ma.json | 238 ++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 app/config/locale/translations/ar-ma.json diff --git a/app/config/locale/translations/ar-ma.json b/app/config/locale/translations/ar-ma.json new file mode 100644 index 0000000000..18fcaa1ee0 --- /dev/null +++ b/app/config/locale/translations/ar-ma.json @@ -0,0 +1,238 @@ +{ + "settings.inspire": "\"الفن ديال الحكمة هو الفن ديال أنك تعرف أش تنخّل.\"", + "settings.locale": "ar-ma", + "settings.direction": "rtl", + "emails.sender": "فرقة %s", + "emails.verification.subject": "التيْقان ديال الحساب", + "emails.verification.hello": "السلام {{user}}", + "emails.verification.body": "تبّع هاد الوصلة باش تيقّن لادريسة تاع ليميل ديالك.", + "emails.verification.footer": "إلا ماشي نتا اللي طلبتي تيقّن هاد لادريسة تاع ليميل، ممكن تنخّل هاد البرية.", + "emails.verification.thanks": "شكرا", + "emails.verification.signature": "فرقة {{project}}", + "emails.magicSession.subject": "تكونيكطا", + "emails.magicSession.hello": "السلام,", + "emails.magicSession.body": "تبّع هاد الوصلة باش تتكونيكطا.", + "emails.magicSession.footer": "إلا ماشي نتا اللي طلبتي تتكونيكطا بهاد ليميل، ممكن تنخّل هاد البرية.", + "emails.magicSession.thanks": "شكرا", + "emails.magicSession.signature": "فرقة {{project}}", + "emails.recovery.subject": "تبدال كلمة السر", + "emails.recovery.hello": "السلام {{user}}", + "emails.recovery.body": "تبّع هاد الوصلة باش تبدّل كلمة السر تاع {{project}}.", + "emails.recovery.footer": "إلا ماشي نتا اللي طلبتي تبدّل كلمة السر، ممكن تنخّل هاد البرية.", + "emails.recovery.thanks": "شكرا", + "emails.recovery.signature": "فرقة {{project}}", + "emails.invitation.subject": "عراضة ل فرقة %s ف %s", + "emails.invitation.hello": "السلام", + "emails.invitation.body": "هاد البرية تصيفطات ليك حيت {{owner}} بغى يعرض عليك تولّي عضو ف فرقة {{team}} عند {{project}}.", + "emails.invitation.footer": "إلا كنتي ما مسوّقش, ممكن تنخّل هاد البرية.", + "emails.invitation.thanks": "شكرا", + "emails.invitation.signature": "فرقة {{project}}", + "emails.certificate.subject": "Certificate failure for %s", + "emails.certificate.hello": "Hello", + "emails.certificate.body": "السرتافيكة ديال ضومينك '{{domain}}' ما قدّاتش تجينيرا. هادي هي المحاولة نمرة {{attempt}}, السبب ديال هاد العطبة هو: {{error}}", + "emails.certificate.footer": "السرتافيكة الفايتة ديالك غاتبقى مزيانة لمدة 30 يوم من عند أول عطبة. كانشجعوك بزاف أنك تبقشش فهاد الموضوع, وا إلّا الضومين ديالك ما غايبقاش خدّام فيه الـ SSL.", + "emails.certificate.thanks": "شكرا", + "emails.certificate.signature": "فرقة {{project}}", + "locale.country.unknown": "ما معروفش", + "countries.af": "أفغانستان", + "countries.ao": "أنڭولا", + "countries.al": "ألبانيا", + "countries.ad": "أندورا", + "countries.ae": "الإمارات العربية المتّاحدة", + "countries.ar": "الأرجنتين", + "countries.am": "أرمينيا", + "countries.ag": "أنتيڭوا وبربودا", + "countries.au": "ؤسطراليا", + "countries.at": "النامسا", + "countries.az": "أديربيجان", + "countries.bi": "بوروندي", + "countries.be": "بلجيكا", + "countries.bj": "بينين", + "countries.bf": "بوركينا فاصو", + "countries.bd": "بنڭلاديش", + "countries.bg": "بلڭاريا", + "countries.bh": "البحرين", + "countries.bs": "دزيرات البهاما", + "countries.ba": "البوسنة ؤ الهرسك", + "countries.by": "بيلاروسيا", + "countries.bz": "بيليز", + "countries.bo": "بوليڤيا", + "countries.br": "البرازيل", + "countries.bb": "باربادوس", + "countries.bn": "بروناي", + "countries.bt": "بوتان", + "countries.bw": "بوتسوانا", + "countries.cf": "جمهورية إفريقيا الوسطانية", + "countries.ca": "كانادا", + "countries.ch": "سويسرا", + "countries.cl": "تشيلي", + "countries.cn": "الشينوا", + "countries.ci": "ساحل العاج", + "countries.cm": "الكاميرون", + "countries.cd": "جمهورية الكونڭو الديمقراطية", + "countries.cg": "جمهورية الكونڭو", + "countries.co": "كولومبيا", + "countries.km": "دزيرات القومور", + "countries.cv": "الراس الخضر", + "countries.cr": "كوسطاريكا", + "countries.cu": "كوبا", + "countries.cy": "قوبروص", + "countries.cz": "التشيك", + "countries.de": "ألمانيا", + "countries.dj": "دجيبوتي", + "countries.dm": "ضومينيكا", + "countries.dk": "الدنمارك", + "countries.do": "جمهورية الضومينيكان", + "countries.dz": "الدزاير", + "countries.ec": "إكوادور", + "countries.eg": "مصر", + "countries.er": "إريتريا", + "countries.es": "سبانيا", + "countries.ee": "إسطونيا", + "countries.et": "إتيوپيا", + "countries.fi": "فينلاندا", + "countries.fj": "فيدجي", + "countries.fr": "فرانسا", + "countries.fm": "ميكرونيزيا", + "countries.ga": "الڭابون", + "countries.gb": "المملكة المتّاحدة", + "countries.ge": "تجورجيا", + "countries.gh": "غانا", + "countries.gn": "غينيا", + "countries.gm": "ڭامبيا", + "countries.gw": "غينيا بيساو", + "countries.gq": "غينيا الستوائية", + "countries.gr": "اليونان", + "countries.gd": "ڭرينادا", + "countries.gt": "ڭواتيمالا", + "countries.gy": "ڭيانا", + "countries.hn": "هوندوراس", + "countries.hr": "كرواتيا", + "countries.ht": "هايتي", + "countries.hu": "الماجر", + "countries.id": "إندونيسيا", + "countries.in": "الهند", + "countries.ie": "إرلاندا", + "countries.ir": "إران", + "countries.iq": "العراق", + "countries.is": "إسلاندا", + "countries.il": "إسرائيل", + "countries.it": "الطاليان", + "countries.jm": "جامايكا", + "countries.jo": "الأردن", + "countries.jp": "الجاپون", + "countries.kz": "كازاخستان", + "countries.ke": "كينيا", + "countries.kg": "قيرغيزستان", + "countries.kh": "كمبوديا", + "countries.ki": "كيريباتي", + "countries.kn": "سانت كيتس ؤ نيفيس", + "countries.kr": "كوريا الجنوبية", + "countries.kw": "الكويت", + "countries.la": "لاوس", + "countries.lb": "لبنان", + "countries.lr": "ليبيريا", + "countries.ly": "ليبيا", + "countries.lc": "سانت لوسيا", + "countries.li": "ليختنشتاين", + "countries.lk": "سري لانكا", + "countries.ls": "ليسوتو", + "countries.lt": "ليتوانيا", + "countries.lu": "لوكسمبورڭ", + "countries.lv": "لاتفيا", + "countries.ma": "المغريب", + "countries.mc": "موناكو", + "countries.md": "مولضوڤا", + "countries.mg": "ماداغشقار", + "countries.mv": "دزيرات المالديڤ", + "countries.mx": "الميكسيك", + "countries.mh": "دزيرات مارشال", + "countries.mk": "مقدونيا", + "countries.ml": "مالي", + "countries.mt": "مالطا", + "countries.mm": "ميانمار", + "countries.me": "مونطينيڭرو", + "countries.mn": "منغوليا", + "countries.mz": "الموزمبيق", + "countries.mr": "موريتانيا", + "countries.mu": "موريشيوس", + "countries.mw": "مالاوي", + "countries.my": "ماليزيا", + "countries.na": "ناميبيا", + "countries.ne": "النيجر", + "countries.ng": "نيجيريا", + "countries.ni": "نيكاراڭوا", + "countries.nl": "هولاندا", + "countries.no": "النرويج", + "countries.np": "نيپال", + "countries.nr": "ناورو", + "countries.nz": "نيوزيلاندا", + "countries.om": "عمّان", + "countries.pk": "پاكيستان", + "countries.pa": "پاناما", + "countries.pe": "الپيرو", + "countries.ph": "الفيليپين", + "countries.pw": "پالاو", + "countries.pg": "پاپوا غينيا الجديدة", + "countries.pl": "پولاندا", + "countries.kp": "كوريا الشمالية", + "countries.pt": "البرطقيز", + "countries.py": "الپاراڭواي", + "countries.qa": "قطر", + "countries.ro": "رومانيا", + "countries.ru": "روسيا", + "countries.rw": "روّاندا", + "countries.sa": "المملكة العربية السعودية", + "countries.sd": "السودان", + "countries.sn": "السينيڭال", + "countries.sg": "سنغافورة", + "countries.sb": "دزيرات سليمان", + "countries.sl": "صييراليون", + "countries.sv": "السالڤاضور", + "countries.sm": "سان مارينو", + "countries.so": "الصومال", + "countries.rs": "صيربيا", + "countries.ss": "جنوب السودان", + "countries.st": "صاو طومي ؤ پرينسيپي", + "countries.sr": "سورينام", + "countries.sk": "صلوڤاكيا", + "countries.si": "صلوڤينيا", + "countries.se": "السويد", + "countries.sz": "سوازيلاند", + "countries.sc": "السيشيل", + "countries.sy": "سوريا", + "countries.td": "تشاد", + "countries.tg": "الطوڭو", + "countries.th": "الطايلوند", + "countries.tj": "طادجيكيستان", + "countries.tm": "تركمانيستان", + "countries.tl": "تيمور الشرقية", + "countries.to": "تونڭا", + "countries.tt": "ترينيداد ؤ طوباڭو", + "countries.tn": "تونس", + "countries.tr": "توركيا", + "countries.tv": "توڤالو", + "countries.tz": "طنزانيا", + "countries.ug": "ؤڭاندا", + "countries.ua": "ؤكرانيا", + "countries.uy": "ؤروڭواي", + "countries.us": "ميريكان", + "countries.uz": "ؤزباكيستان", + "countries.va": "مدينة الڤاتيكان", + "countries.vc": "سانت ڤانسون ؤ دزيرات ڭرينادين", + "countries.ve": "ڤينيزويلا", + "countries.vn": "ڤيطنام", + "countries.vu": "ڤانواتو", + "countries.ws": "ساموا", + "countries.ye": "اليمن", + "countries.za": "جنوب إفريقيا", + "countries.zm": "زامبيا", + "countries.zw": "زيمبابوي", + "continents.af": "أفريقيا", + "continents.an": "القارة القطبية الجنوبية", + "continents.as": "أسيا", + "continents.eu": "ؤروپا", + "continents.na": "ميريكان الشمالية", + "continents.oc": "ؤقيانوسيا", + "continents.sa": "ميريكان الجنوبية" +} From 3a35412bf8905abaf5a8912305f4820c1e05ec63 Mon Sep 17 00:00:00 2001 From: achraf112ben Date: Mon, 29 Jan 2024 04:21:14 +0100 Subject: [PATCH 02/42] fix some missed values --- app/config/locale/translations/ar-ma.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/config/locale/translations/ar-ma.json b/app/config/locale/translations/ar-ma.json index 18fcaa1ee0..453de25c80 100644 --- a/app/config/locale/translations/ar-ma.json +++ b/app/config/locale/translations/ar-ma.json @@ -27,10 +27,10 @@ "emails.invitation.footer": "إلا كنتي ما مسوّقش, ممكن تنخّل هاد البرية.", "emails.invitation.thanks": "شكرا", "emails.invitation.signature": "فرقة {{project}}", - "emails.certificate.subject": "Certificate failure for %s", - "emails.certificate.hello": "Hello", - "emails.certificate.body": "السرتافيكة ديال ضومينك '{{domain}}' ما قدّاتش تجينيرا. هادي هي المحاولة نمرة {{attempt}}, السبب ديال هاد العطبة هو: {{error}}", - "emails.certificate.footer": "السرتافيكة الفايتة ديالك غاتبقى مزيانة لمدة 30 يوم من عند أول عطبة. كانشجعوك بزاف أنك تبقشش فهاد الموضوع, وا إلّا الضومين ديالك ما غايبقاش خدّام فيه الـ SSL.", + "emails.certificate.subject": "السرتافيكة فشلات ل %s", + "emails.certificate.hello": "السلام", + "emails.certificate.body": "السرتافيكة ديال الضومين ديالك '{{domain}}' ما قدّاتش تجينيرا. هادي هي المحاولة نمرة {{attempt}}, السبب ديال هاد الفشل هو: {{error}}", + "emails.certificate.footer": "السرتافيكة الفايتة ديالك غاتبقى مزيانة لمدة 30 يوم من عند أول فشل. كانشجعوك بزاف أنك تبقشش فهاد الموضوع, وا إلّا الضومين ديالك ما غايبقاش خدّام فيه الـ SSL.", "emails.certificate.thanks": "شكرا", "emails.certificate.signature": "فرقة {{project}}", "locale.country.unknown": "ما معروفش", From a9cee074be22d7123a722568bc9d78175f5843ae Mon Sep 17 00:00:00 2001 From: ItzNotABug Date: Wed, 5 Jun 2024 13:45:41 +0530 Subject: [PATCH 03/42] update: add api doesn't support redirections. --- docs/references/avatars/get-favicon.md | 2 ++ docs/references/avatars/get-image.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/references/avatars/get-favicon.md b/docs/references/avatars/get-favicon.md index b571e0af93..c3a63dd83f 100644 --- a/docs/references/avatars/get-favicon.md +++ b/docs/references/avatars/get-favicon.md @@ -1 +1,3 @@ Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL. + +This endpoint does not follow HTTP redirects. \ No newline at end of file diff --git a/docs/references/avatars/get-image.md b/docs/references/avatars/get-image.md index efd654b362..ca9cc5e418 100644 --- a/docs/references/avatars/get-image.md +++ b/docs/references/avatars/get-image.md @@ -1,3 +1,5 @@ Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol. When one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px. + +This endpoint does not follow HTTP redirects. \ No newline at end of file From e6686bd3dd0983c2087fa971579c7c6deb691251 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:40:11 +0530 Subject: [PATCH 04/42] Add APPWRITE_REGION in env var --- app/controllers/api/functions.php | 3 ++- app/controllers/general.php | 3 ++- src/Appwrite/Platform/Workers/Builds.php | 3 ++- src/Appwrite/Platform/Workers/Functions.php | 3 ++- tests/e2e/Services/Functions/FunctionsCustomClientTest.php | 2 ++ tests/resources/functions/php-fn/index.php | 1 + tests/resources/functions/php-large/index.php | 1 + tests/resources/functions/php/index.php | 1 + 8 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d2a1790d94..bc8e91b966 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1825,7 +1825,8 @@ App::post('/v1/functions/:functionId/executions') 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_VERSION' => APP_VERSION_STABLE + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), ]); /** Execute function */ diff --git a/app/controllers/general.php b/app/controllers/general.php index 10c9eb8e18..fc572a6fd7 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -250,7 +250,8 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_VERSION' => APP_VERSION_STABLE + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), ]); /** Execute function */ diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 922498c3fa..b712edd402 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -400,7 +400,8 @@ class Builds extends Action 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_VERSION' => APP_VERSION_STABLE + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), ]); $command = $deployment->getAttribute('commands', ''); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 5dfdc0a63a..19c690577c 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -464,7 +464,8 @@ class Functions extends Action 'APPWRITE_FUNCTION_PROJECT_ID' => $project->getId(), 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'] ?? '', - 'APPWRITE_VERSION' => APP_VERSION_STABLE + 'APPWRITE_VERSION' => APP_VERSION_STABLE, + 'APPWRITE_REGION' => $project->getAttribute('region'), ]); /** Execute function */ diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index bf969d388a..18bdba5af4 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -449,6 +449,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); $this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']); + $this->assertEquals('default', $output['APPWRITE_REGION']); $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); @@ -834,6 +835,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('PHP', $output['APPWRITE_FUNCTION_RUNTIME_NAME']); $this->assertEquals('8.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']); $this->assertEquals(APP_VERSION_STABLE, $output['APPWRITE_VERSION']); + $this->assertEquals('default', $output['APPWRITE_REGION']); $this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']); $this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']); $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); diff --git a/tests/resources/functions/php-fn/index.php b/tests/resources/functions/php-fn/index.php index b353ad2ca4..0b6e3d206c 100644 --- a/tests/resources/functions/php-fn/index.php +++ b/tests/resources/functions/php-fn/index.php @@ -11,6 +11,7 @@ return function ($context) { 'APPWRITE_FUNCTION_RUNTIME_NAME' => \getenv('APPWRITE_FUNCTION_RUNTIME_NAME') ?: '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => \getenv('APPWRITE_FUNCTION_RUNTIME_VERSION') ?: '', 'APPWRITE_VERSION' => \getenv('APPWRITE_VERSION') ?: '', + 'APPWRITE_REGION' => \getenv('APPWRITE_REGION') ?: '', 'APPWRITE_FUNCTION_EVENT' => $context->req->headers['x-appwrite-event'] ?? '', 'APPWRITE_FUNCTION_EVENT_DATA' => $context->req->bodyRaw ?? '', 'APPWRITE_FUNCTION_DATA' => $context->req->bodyRaw ?? '', diff --git a/tests/resources/functions/php-large/index.php b/tests/resources/functions/php-large/index.php index 5a9666488e..ab3d050245 100644 --- a/tests/resources/functions/php-large/index.php +++ b/tests/resources/functions/php-large/index.php @@ -8,6 +8,7 @@ return function ($context) { 'APPWRITE_FUNCTION_TRIGGER' => $context->req->headers['x-appwrite-trigger'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_NAME' => \getenv('APPWRITE_FUNCTION_RUNTIME_NAME') ?: '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => \getenv('APPWRITE_FUNCTION_RUNTIME_VERSION') ?: '', + 'APPWRITE_REGION' => \getenv('APPWRITE_REGION') ?: '', 'UNICODE_TEST' => "êä" ]); }; diff --git a/tests/resources/functions/php/index.php b/tests/resources/functions/php/index.php index ac7b85a43a..d5328c40e1 100644 --- a/tests/resources/functions/php/index.php +++ b/tests/resources/functions/php/index.php @@ -8,6 +8,7 @@ return function ($context) { 'APPWRITE_FUNCTION_TRIGGER' => $context->req->headers['x-appwrite-trigger'] ?? '', 'APPWRITE_FUNCTION_RUNTIME_NAME' => \getenv('APPWRITE_FUNCTION_RUNTIME_NAME') ?: '', 'APPWRITE_FUNCTION_RUNTIME_VERSION' => \getenv('APPWRITE_FUNCTION_RUNTIME_VERSION') ?: '', + 'APPWRITE_REGION' => \getenv('APPWRITE_REGION') ?: '', 'UNICODE_TEST' => "êä", 'GLOBAL_VARIABLE' => \getenv('GLOBAL_VARIABLE') ?: '' ]); From eacd965ae3a51ad510793b6ee884595d2852bd39 Mon Sep 17 00:00:00 2001 From: Binyamin Yawitz <316103+byawitz@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:13:34 -0400 Subject: [PATCH 05/42] feat: Adding profiler for debugging --- CONTRIBUTING.md | 12 ++++++++++++ Dockerfile | 3 ++- dev/xdebug.ini | 6 ++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e3e6fcd81..8d8ddadda6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -497,6 +497,18 @@ If you are in PHP Storm you don't need any plugin. Below are the settings requir 2. If needed edit the **dev/xdebug.ini** file to your needs. 3. Launch your Appwrite instance while your debugger is listening for connections. +## Profiling +Appwrite uses XDebug [Profiler](https://xdebug.org/docs/profiler) for generating **CacheGrind** files. The generated file would be located in each of the `appwrite` containers inside the `/tmp/xdebug` folder. + +To disable the profiler while debugging remove the `,profiler` mode from the `xdebug.ini` file +```diff +zend_extension=xdebug + +[xdebug] +-xdebug.mode=develop,debug,profile ++xdebug.mode=develop,debug +``` + ### VS Code Launch Configuration ```json diff --git a/Dockerfile b/Dockerfile index 1d82930c1d..7cc0403b84 100755 --- a/Dockerfile +++ b/Dockerfile @@ -108,9 +108,10 @@ RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/ # Enable Extensions RUN if [ "$DEBUG" == "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi +RUN if [ "$DEBUG" == "true" ]; then mkdir -p /tmp/xdebug; fi RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi EXPOSE 80 -CMD [ "php", "app/http.php" ] \ No newline at end of file +CMD [ "php", "app/http.php" ] diff --git a/dev/xdebug.ini b/dev/xdebug.ini index e29c8bd46e..f9c535019f 100644 --- a/dev/xdebug.ini +++ b/dev/xdebug.ini @@ -1,6 +1,8 @@ zend_extension=xdebug [xdebug] -xdebug.mode=develop,debug +xdebug.mode=develop,debug,profile xdebug.client_host=host.docker.internal -xdebug.start_with_request=yes \ No newline at end of file +xdebug.start_with_request=yes +xdebug.output_dir=/tmp/xdebug +xdebug.use_compression=false From 5d6b74e447a71b2d23ee594baac1a60194616685 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 14:52:17 +0900 Subject: [PATCH 06/42] Add migrations and filters for 1.6.x --- app/controllers/general.php | 9 +- src/Appwrite/Migration/Migration.php | 1 + src/Appwrite/Migration/Version/V21.php | 143 ++++++++++++++++++ src/Appwrite/Utopia/Request/Filters/V18.php | 21 +++ src/Appwrite/Utopia/Response/Filters/V18.php | 36 +++++ tests/unit/Utopia/Request/Filters/V18Test.php | 51 +++++++ .../unit/Utopia/Response/Filters/V18Test.php | 84 ++++++++++ 7 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 src/Appwrite/Migration/Version/V21.php create mode 100644 src/Appwrite/Utopia/Request/Filters/V18.php create mode 100644 src/Appwrite/Utopia/Response/Filters/V18.php create mode 100644 tests/unit/Utopia/Request/Filters/V18Test.php create mode 100644 tests/unit/Utopia/Response/Filters/V18Test.php diff --git a/app/controllers/general.php b/app/controllers/general.php index 10c9eb8e18..72143cbeca 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -11,9 +11,10 @@ use Appwrite\Network\Validator\Origin; use Appwrite\Utopia\Request; use Appwrite\Utopia\Request\Filters\V16 as RequestV16; use Appwrite\Utopia\Request\Filters\V17 as RequestV17; +use Appwrite\Utopia\Request\Filters\V18 as RequestV18; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V16 as ResponseV16; -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; @@ -434,6 +435,9 @@ App::init() if (version_compare($requestFormat, '1.5.0', '<')) { $request->addFilter(new RequestV17()); } + if (version_compare($requestFormat, '1.6.0', '<')) { + $request->addFilter(new RequestV18()); + } } $domain = $request->getHostname(); @@ -550,6 +554,9 @@ App::init() if (version_compare($responseFormat, '1.5.0', '<')) { $response->addFilter(new ResponseV17()); } + if (version_compare($responseFormat, '1.6.0', '<')) { + $response->addFilter(new ResponseV18()); + } if (version_compare($responseFormat, APP_VERSION_STABLE, '>')) { $response->addHeader('X-Appwrite-Warning', "The current SDK is built for Appwrite " . $responseFormat . ". However, the current Appwrite server version is ". APP_VERSION_STABLE . ". Please downgrade your SDK to match the Appwrite version: https://appwrite.io/docs/sdks"); } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index e3a2021c1a..716f6c6381 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -86,6 +86,7 @@ abstract class Migration '1.5.5' => 'V20', '1.5.6' => 'V20', '1.5.7' => 'V20', + '1.6.0' => 'V12' ]; /** diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php new file mode 100644 index 0000000000..7dc9e4374b --- /dev/null +++ b/src/Appwrite/Migration/Version/V21.php @@ -0,0 +1,143 @@ + null, + fn () => [] + ); + } + + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + + Console::info('Migrating Collections'); + $this->migrateCollections(); + + Console::info('Migrating Documents'); + $this->forEachDocument([$this, 'fixDocument']); + } + + /** + * Migrate Collections. + * + * @return void + * @throws Exception|Throwable + */ + private function migrateCollections(): void + { + $internalProjectId = $this->project->getInternalId(); + $collectionType = match ($internalProjectId) { + 'console' => 'console', + default => 'projects', + }; + + $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { + $id = $collection['$id']; + + Console::log("Migrating Collection \"{$id}\""); + + $this->projectDB->setNamespace("_$internalProjectId"); + + switch ($id) { + case 'projects': + // Create accessedAt attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'accessedAt'); + } catch (Throwable $th) { + Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); + } + break; + case 'schedules': + // Create data attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'data'); + } catch (Throwable $th) { + Console::warning("'data' from {$id}: {$th->getMessage()}"); + } + + break; + + case 'functions': + // Create scopes attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'scopes'); + } catch (Throwable $th) { + Console::warning("'scopes' from {$id}: {$th->getMessage()}"); + } + + break; + case 'executions': + // Create requestMethod index + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_requestMethod'); + } catch (\Throwable $th) { + Console::warning("'_key_requestMethod' from {$id}: {$th->getMessage()}"); + } + + // Create requestPath index + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_requestPath'); + } catch (\Throwable $th) { + Console::warning("'_key_requestPath' from {$id}: {$th->getMessage()}"); + } + + // Create deployment index + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_deployment'); + } catch (\Throwable $th) { + Console::warning("'_key_deployment' from {$id}: {$th->getMessage()}"); + } + } + + usleep(50000); + } + } + + /** + * Fix run on each document + * + * @param Document $document + * @return Document + */ + protected function fixDocument(Document $document): Document + { + switch ($document->getCollection()) { + case 'projects': + /** + * Bump version number. + */ + $document->setAttribute('version', '1.6.0'); + break; + case 'functions': + /** + * Add scopes attribute. + */ + if (!$document->getAttribute('scopes', false)) { + $document->setAttribute('scopes', []); + } + break; + } + return $document; + } +} diff --git a/src/Appwrite/Utopia/Request/Filters/V18.php b/src/Appwrite/Utopia/Request/Filters/V18.php new file mode 100644 index 0000000000..fd8b7ffd3a --- /dev/null +++ b/src/Appwrite/Utopia/Request/Filters/V18.php @@ -0,0 +1,21 @@ + $this->parseFunction($content), + Response::MODEL_PROJECT => $this->parseProject($content), + default => $parsedResponse, + }; + + return $parsedResponse; + } + + protected function parseFunction(array $content) + { + unset($content['scopes']); + return $content; + } + + protected function parseProject(array $content) + { + unset($content['authMockNumbers']); + unset($content['authSessionAlerts']); + return $content; + } +} \ No newline at end of file diff --git a/tests/unit/Utopia/Request/Filters/V18Test.php b/tests/unit/Utopia/Request/Filters/V18Test.php new file mode 100644 index 0000000000..4e1f81573a --- /dev/null +++ b/tests/unit/Utopia/Request/Filters/V18Test.php @@ -0,0 +1,51 @@ +filter = new V18(); + } + + public function tearDown(): void + { + } + + public function deleteMfaAuthenticatorProvider() + { + return [ + 'remove otp' => [ + [ + 'type' => 'totp', + 'otp' => 1230 + ], + [ + 'type' => 'totp' + ] + ] + ]; + } + + /** + * @dataProvider deleteMfaAuthenticatorProvider + */ + public function testdeleteMfaAuthenticator(array $content, array $expected): void + { + $model = 'account.deleteMfaAuthenticator'; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } +} diff --git a/tests/unit/Utopia/Response/Filters/V18Test.php b/tests/unit/Utopia/Response/Filters/V18Test.php new file mode 100644 index 0000000000..0b12ca66cd --- /dev/null +++ b/tests/unit/Utopia/Response/Filters/V18Test.php @@ -0,0 +1,84 @@ +filter = new V18(); + } + + public function tearDown(): void + { + } + + public function functionProvider(): array + { + return [ + 'remove scopes' => [ + [ + 'scopes' => [ + 'example_scope', + 'example_scope2', + ], + ], + [ + ] + ] + ]; + } + + /** + * @dataProvider functionProvider + */ + public function testFunction(array $content, array $expected): void + { + $model = Response::MODEL_FUNCTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + + public function projectProvider(): array + { + return [ + 'remove authMockNumbers and authSessionAlerts' => [ + [ + 'authMockNumbers' => [ + 'example_mock_number', + 'example_mock_number2', + ], + 'authSessionAlerts' => [ + 'example_alert', + 'example_alert2', + ], + ], + [ + ] + ] + ]; + } + + /** + * @dataProvider projectProvider + */ + public function testProject(array $content, array $expected): void + { + $model = Response::MODEL_PROJECT; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } +} \ No newline at end of file From ec9bb8a898b7e7a08d1106c33922d6653aa574dd Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 14:53:23 +0900 Subject: [PATCH 07/42] Re-add V17 Response filter --- app/controllers/general.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 72143cbeca..70acd9d482 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -14,6 +14,7 @@ use Appwrite\Utopia\Request\Filters\V17 as RequestV17; use Appwrite\Utopia\Request\Filters\V18 as RequestV18; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filters\V16 as ResponseV16; +use Appwrite\Utopia\Response\Filters\V17 as ResponseV17; use Appwrite\Utopia\Response\Filters\V18 as ResponseV18; use Appwrite\Utopia\View; use Executor\Executor; From 35375c42ad38a7266f4a45f1f3383c2ee0236197 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 14:54:37 +0900 Subject: [PATCH 08/42] Fix typos --- src/Appwrite/Migration/Migration.php | 2 +- src/Appwrite/Migration/Version/V21.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 716f6c6381..9075b85702 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -86,7 +86,7 @@ abstract class Migration '1.5.5' => 'V20', '1.5.6' => 'V20', '1.5.7' => 'V20', - '1.6.0' => 'V12' + '1.6.0' => 'V21' ]; /** diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 7dc9e4374b..10193ec60c 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -9,7 +9,7 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; -class V20 extends Migration +class V21 extends Migration { /** * @throws Throwable From 917de006bff0fc694140ca04fd293470a936099b Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 15:01:44 +0900 Subject: [PATCH 09/42] Increate stable version number --- app/init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/init.php b/app/init.php index a0e71f041b..ef7742956f 100644 --- a/app/init.php +++ b/app/init.php @@ -118,7 +118,7 @@ const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4314; -const APP_VERSION_STABLE = '1.5.7'; +const APP_VERSION_STABLE = '1.6.0'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; From d78c880bf02aadb8ede51bb3ca50bf59f3b7ff69 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 15:20:34 +0900 Subject: [PATCH 10/42] Update V21.php --- src/Appwrite/Migration/Version/V21.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 10193ec60c..4bd27b71bc 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -7,6 +7,7 @@ use Exception; use Throwable; use Utopia\CLI\Console; use Utopia\Database\Database; +use Utopia\Database\DateTime; use Utopia\Database\Document; class V21 extends Migration @@ -133,7 +134,7 @@ class V21 extends Migration /** * Add scopes attribute. */ - if (!$document->getAttribute('scopes', false)) { + if (empty($document->getAttribute('scopes', []))) { $document->setAttribute('scopes', []); } break; From 7dec5f68bef598b1a178de97d051b8e43bb447f7 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 15:20:42 +0900 Subject: [PATCH 11/42] Update V21.php --- src/Appwrite/Migration/Version/V21.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 4bd27b71bc..53d8101af2 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -129,6 +129,7 @@ class V21 extends Migration * Bump version number. */ $document->setAttribute('version', '1.6.0'); + $document->setAttribute('accessedAt', DateTime::now()); break; case 'functions': /** From 83c43503957171fa253d5d0d73bd540d18a31b09 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 17:58:25 +0900 Subject: [PATCH 12/42] Make scopes optional on functions --- app/config/collections.php | 4 ++-- src/Appwrite/Migration/Version/V21.php | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index d0c3df165e..b4dc1049fb 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -4751,8 +4751,8 @@ $consoleCollections = array_merge([ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => true, - 'default' => null, + 'required' => false, + 'default' => [], 'array' => true, 'filters' => [], ], diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 53d8101af2..c5f09822cb 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -131,14 +131,6 @@ class V21 extends Migration $document->setAttribute('version', '1.6.0'); $document->setAttribute('accessedAt', DateTime::now()); break; - case 'functions': - /** - * Add scopes attribute. - */ - if (empty($document->getAttribute('scopes', []))) { - $document->setAttribute('scopes', []); - } - break; } return $document; } From efa1924f26649a13471d5f14ad8e8acc113169f9 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 17 Jul 2024 18:00:41 +0900 Subject: [PATCH 13/42] Run Linter --- src/Appwrite/Utopia/Request/Filters/V18.php | 2 +- src/Appwrite/Utopia/Response/Filters/V18.php | 2 +- tests/unit/Utopia/Response/Filters/V18Test.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Utopia/Request/Filters/V18.php b/src/Appwrite/Utopia/Request/Filters/V18.php index fd8b7ffd3a..4f889ce66b 100644 --- a/src/Appwrite/Utopia/Request/Filters/V18.php +++ b/src/Appwrite/Utopia/Request/Filters/V18.php @@ -18,4 +18,4 @@ class V18 extends Filter return $content; } -} \ No newline at end of file +} diff --git a/src/Appwrite/Utopia/Response/Filters/V18.php b/src/Appwrite/Utopia/Response/Filters/V18.php index ea82f8335e..b32856bdb4 100644 --- a/src/Appwrite/Utopia/Response/Filters/V18.php +++ b/src/Appwrite/Utopia/Response/Filters/V18.php @@ -33,4 +33,4 @@ class V18 extends Filter unset($content['authSessionAlerts']); return $content; } -} \ No newline at end of file +} diff --git a/tests/unit/Utopia/Response/Filters/V18Test.php b/tests/unit/Utopia/Response/Filters/V18Test.php index 0b12ca66cd..36719a7620 100644 --- a/tests/unit/Utopia/Response/Filters/V18Test.php +++ b/tests/unit/Utopia/Response/Filters/V18Test.php @@ -81,4 +81,4 @@ class V18Test extends TestCase $this->assertEquals($expected, $result); } -} \ No newline at end of file +} From 86ed408cfe27a8b52620a80edbefaadd59cb1eb3 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 15:54:04 +0200 Subject: [PATCH 14/42] chore: release cli 6.0.0-rc.4 --- app/config/platforms.php | 2 +- .../console-cli/examples/account/delete-mfa-authenticator.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 7b0e315902..3a77b99887 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -221,7 +221,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '6.0.0-rc.3', + 'version' => '6.0.0-rc.4', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/docs/examples/1.6.x/console-cli/examples/account/delete-mfa-authenticator.md b/docs/examples/1.6.x/console-cli/examples/account/delete-mfa-authenticator.md index c36e9d5578..d4664855b5 100644 --- a/docs/examples/1.6.x/console-cli/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/1.6.x/console-cli/examples/account/delete-mfa-authenticator.md @@ -1,3 +1,2 @@ appwrite account deleteMfaAuthenticator \ - --type totp \ - --otp + --type totp From 6cb9dd0ac8adf46ac5aac83793a682cbbcda4bf7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 18:22:54 +0200 Subject: [PATCH 15/42] chore: update composer lock --- composer.lock | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/composer.lock b/composer.lock index 8d307c5c99..68f109ed72 100644 --- a/composer.lock +++ b/composer.lock @@ -356,16 +356,16 @@ }, { "name": "chillerlan/php-settings-container", - "version": "2.1.5", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e" + "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/f705310389264c3578fdd9ffb15aa2cd6d91772e", - "reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb", + "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb", "shasum": "" }, "require": { @@ -373,15 +373,16 @@ "php": "^7.4 || ^8.0" }, "require-dev": { - "phan/phan": "^5.4", - "phpcsstandards/php_codesniffer": "^3.8", - "phpmd/phpmd": "^2.13", - "phpunit/phpunit": "^9.6" + "phpmd/phpmd": "^2.15", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-deprecation-rules": "^1.2", + "phpunit/phpunit": "^9.6", + "squizlabs/php_codesniffer": "^3.10" }, "type": "library", "autoload": { "psr-4": { - "chillerlan\\Settings\\": "src/" + "chillerlan\\Settings\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -418,7 +419,7 @@ "type": "ko_fi" } ], - "time": "2024-01-05T23:20:55+00:00" + "time": "2024-07-17T01:04:28+00:00" }, { "name": "dragonmantank/cron-expression", @@ -2989,16 +2990,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.39.2", + "version": "0.39.3", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "550b56aa7ee3f98319b79a20d2478e68a1b5e9bd" + "reference": "16142d88270e368030d7956cadf2d7816413f8c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/550b56aa7ee3f98319b79a20d2478e68a1b5e9bd", - "reference": "550b56aa7ee3f98319b79a20d2478e68a1b5e9bd", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/16142d88270e368030d7956cadf2d7816413f8c4", + "reference": "16142d88270e368030d7956cadf2d7816413f8c4", "shasum": "" }, "require": { @@ -3034,9 +3035,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.39.2" + "source": "https://github.com/appwrite/sdk-generator/tree/0.39.3" }, - "time": "2024-07-10T11:23:54+00:00" + "time": "2024-07-12T15:29:48+00:00" }, { "name": "doctrine/deprecations", From 0ecc1849a7357e99db736a34c42accd90eaca48a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 19:24:52 +0200 Subject: [PATCH 16/42] feat: containerized console --- .gitmodules | 4 --- app/console | 1 - app/controllers/web/console.php | 51 ++++++--------------------------- app/views/install/compose.phtml | 22 +++++++++++++- docker-compose.yml | 22 +++++++++++++- 5 files changed, 51 insertions(+), 49 deletions(-) delete mode 100644 .gitmodules delete mode 160000 app/console diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index c9a244dd65..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "app/console"] - path = app/console - url = https://github.com/appwrite/console - branch = 1.6.x diff --git a/app/console b/app/console deleted file mode 160000 index f978cecfaf..0000000000 --- a/app/console +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f978cecfafe55e85fcd20fe90fc020e78a7c7952 diff --git a/app/controllers/web/console.php b/app/controllers/web/console.php index fac8d21261..a4c76a9a35 100644 --- a/app/controllers/web/console.php +++ b/app/controllers/web/console.php @@ -16,8 +16,7 @@ App::init() ; }); -App::get('/console/*') - ->alias('/') +App::get('/') ->alias('auth/*') ->alias('/invite') ->alias('/login') @@ -31,45 +30,13 @@ App::get('/console/*') ->inject('request') ->inject('response') ->action(function (Request $request, Response $response) { - $fallback = file_get_contents(__DIR__ . '/../../../console/index.html'); - - // Card SSR - if (\str_starts_with($request->getURI(), '/card')) { - $urlCunks = \explode('/', $request->getURI()); - $userId = $urlCunks[\count($urlCunks) - 1] ?? ''; - - $domain = $request->getProtocol() . '://' . $request->getHostname(); - - if (!empty($userId)) { - $ogImageUrl = $domain . '/v1/cards/cloud-og?userId=' . $userId; - } else { - $ogImageUrl = $domain . '/v1/cards/cloud-og?mock=normal'; - } - - $ogTags = [ - 'Appwrite Cloud Card', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - ]; - - $fallback = \str_replace('', \implode('', $ogTags), $fallback); + $url = parse_url($request->getURI()); + $target = "/console{$url['path']}"; + if ($url['query'] ?? false) { + $target .= "?{$url['query']}"; } - - $response->html($fallback); + if ($url['fragment'] ?? false) { + $target .= "#{$url['fragment']}"; + } + $response->redirect($target); }); diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index fb88db4f39..4dcc24d909 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -49,7 +49,7 @@ $image = $this->getParam('image', ''); - traefik.enable=true - traefik.constraint-label-stack=appwrite - traefik.docker.network=appwrite - - traefik.http.services.appwrite_api.loadbalancer.server.port=80 + - traefik.http.services.appwrite_api.loadbalancer.server.port=3000 #http - traefik.http.routers.appwrite_api_http.entrypoints=appwrite_web - traefik.http.routers.appwrite_api_http.rule=PathPrefix(`/`) @@ -163,6 +163,26 @@ $image = $this->getParam('image', ''); - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET - _APP_ASSISTANT_OPENAI_API_KEY + appwrite-console: + <<: *x-logging + container_name: appwrite-console + image: /console:latest //TODO: fix tomorrow + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.constraint-label-stack=appwrite" + - "traefik.docker.network=appwrite" + - "traefik.http.services.appwrite_console.loadbalancer.server.port=80" + #ws + - traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web + - traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`) + - traefik.http.routers.appwrite_console_http.service=appwrite_console + # wss + - traefik.http.routers.appwrite_console_https.entrypoints=appwrite_websecure + - traefik.http.routers.appwrite_console_https.rule=PathPrefix(`/console`) + - traefik.http.routers.appwrite_console_https.service=appwrite_console + - traefik.http.routers.appwrite_console_https.tls=true + appwrite-realtime: image: /: entrypoint: realtime diff --git a/docker-compose.yml b/docker-compose.yml index 7be1225eaa..588d3fa526 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -52,7 +52,7 @@ services: DEBUG: false TESTING: true VERSION: dev - ports: + ports: - 9501:80 networks: - appwrite @@ -192,6 +192,26 @@ services: - _APP_EXPERIMENT_LOGGING_CONFIG - _APP_DATABASE_SHARED_TABLES + appwrite-console: + <<: *x-logging + container_name: appwrite-console + image: appwrite/console:dev + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.constraint-label-stack=appwrite" + - "traefik.docker.network=appwrite" + - "traefik.http.services.appwrite_console.loadbalancer.server.port=3000" + #ws + - traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web + - traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`) + - traefik.http.routers.appwrite_console_http.service=appwrite_console + # wss + - traefik.http.routers.appwrite_console_https.entrypoints=appwrite_websecure + - traefik.http.routers.appwrite_console_https.rule=PathPrefix(`/console`) + - traefik.http.routers.appwrite_console_https.service=appwrite_console + - traefik.http.routers.appwrite_console_https.tls=true + appwrite-realtime: entrypoint: realtime <<: *x-logging From e61ff28c0fce982163213406ab2e12a02b999214 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 19:26:27 +0200 Subject: [PATCH 17/42] fix: production compose template --- app/views/install/compose.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 4dcc24d909..7ae5eb1b5b 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -49,7 +49,7 @@ $image = $this->getParam('image', ''); - traefik.enable=true - traefik.constraint-label-stack=appwrite - traefik.docker.network=appwrite - - traefik.http.services.appwrite_api.loadbalancer.server.port=3000 + - traefik.http.services.appwrite_api.loadbalancer.server.port=80 #http - traefik.http.routers.appwrite_api_http.entrypoints=appwrite_web - traefik.http.routers.appwrite_api_http.rule=PathPrefix(`/`) @@ -172,7 +172,7 @@ $image = $this->getParam('image', ''); - "traefik.enable=true" - "traefik.constraint-label-stack=appwrite" - "traefik.docker.network=appwrite" - - "traefik.http.services.appwrite_console.loadbalancer.server.port=80" + - "traefik.http.services.appwrite_console.loadbalancer.server.port=3000" #ws - traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web - traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`) From eb673a931ef09a49deae057bd82282e5588dce5d Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 19:29:48 +0200 Subject: [PATCH 18/42] fix: dockerfile --- Dockerfile | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 56c22fe679..51cca4f4f9 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,23 +12,6 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM --platform=$BUILDPLATFORM node:20.11.0-alpine3.19 as node - -COPY app/console /usr/local/src/console - -WORKDIR /usr/local/src/console - -ARG VITE_GA_PROJECT -ARG VITE_CONSOLE_MODE -ARG VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1 - -ENV VITE_GA_PROJECT=$VITE_GA_PROJECT -ENV VITE_CONSOLE_MODE=$VITE_CONSOLE_MODE -ENV VITE_APPWRITE_GROWTH_ENDPOINT=$VITE_APPWRITE_GROWTH_ENDPOINT - -RUN npm ci -RUN npm run build - FROM appwrite/base:0.9.1 as final LABEL maintainer="team@appwrite.io" @@ -47,9 +30,6 @@ RUN \ WORKDIR /usr/src/code -COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor -COPY --from=node /usr/local/src/console/build /usr/src/code/console - # Add Source Code COPY ./app /usr/src/code/app COPY ./public /usr/src/code/public From 9e1b00d8e5aaef66d398047df1143de1e9a9dd74 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 20:19:34 +0200 Subject: [PATCH 19/42] fix: console image --- .gitignore | 1 + app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index ef05c948ff..5ae03e2a56 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ !/.idea/php.xml .DS_Store .php_cs.cache +.phpactor.json debug/ app/sdks dev/yasd_init.php diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 7ae5eb1b5b..76b3f1fd01 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:latest //TODO: fix tomorrow + image: /console:appwrite/console:5.0.0-rc.3 restart: unless-stopped labels: - "traefik.enable=true" diff --git a/docker-compose.yml b/docker-compose.yml index 588d3fa526..da49e40426 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,7 +195,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:dev + image: appwrite/console:5.0.0-rc.3 restart: unless-stopped labels: - "traefik.enable=true" From 8210e0ffafe59025ecf109ff520ad159feeef2dd Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 20:29:58 +0200 Subject: [PATCH 20/42] fix: new image --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 76b3f1fd01..4e7990cedf 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:appwrite/console:5.0.0-rc.3 + image: /console:appwrite/console:5.0.0-rc.5 restart: unless-stopped labels: - "traefik.enable=true" diff --git a/docker-compose.yml b/docker-compose.yml index da49e40426..56b74bbd58 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,7 +195,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.0-rc.3 + image: appwrite/console:5.0.0-rc.5 restart: unless-stopped labels: - "traefik.enable=true" From 9c4f7dd10851d5d3a584a7f2526043fece5bd874 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 20:35:09 +0200 Subject: [PATCH 21/42] fix: accidentally removed copy command from dockerfile --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 51cca4f4f9..6f0fdcb7b7 100755 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,8 @@ RUN \ WORKDIR /usr/src/code +COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor + # Add Source Code COPY ./app /usr/src/code/app COPY ./public /usr/src/code/public From 8bc75b2bbeb827ade6864d963dab3befbc6bc0af Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 22:22:03 +0200 Subject: [PATCH 22/42] fix: remove console static files from loading --- app/http.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/http.php b/app/http.php index f410d98a0c..ac40639057 100644 --- a/app/http.php +++ b/app/http.php @@ -57,8 +57,6 @@ $http->on(Constant::EVENT_AFTER_RELOAD, function ($server, $workerId) { Console::success('Reload completed...'); }); -Files::load(__DIR__ . '/../console'); - include __DIR__ . '/controllers/general.php'; $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) { From bcd472ca594752b62222c2e1e366f421ec534e3c Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 22:39:32 +0200 Subject: [PATCH 23/42] fix: compose console port --- app/views/install/compose.phtml | 4 +++- docker-compose.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 4e7990cedf..a8de452b85 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -168,11 +168,13 @@ $image = $this->getParam('image', ''); container_name: appwrite-console image: /console:appwrite/console:5.0.0-rc.5 restart: unless-stopped + networks: + - appwrite labels: - "traefik.enable=true" - "traefik.constraint-label-stack=appwrite" - "traefik.docker.network=appwrite" - - "traefik.http.services.appwrite_console.loadbalancer.server.port=3000" + - "traefik.http.services.appwrite_console.loadbalancer.server.port=80" #ws - traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web - traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`) diff --git a/docker-compose.yml b/docker-compose.yml index 56b74bbd58..fc8581c80a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -197,11 +197,13 @@ services: container_name: appwrite-console image: appwrite/console:5.0.0-rc.5 restart: unless-stopped + networks: + - appwrite labels: - "traefik.enable=true" - "traefik.constraint-label-stack=appwrite" - "traefik.docker.network=appwrite" - - "traefik.http.services.appwrite_console.loadbalancer.server.port=3000" + - "traefik.http.services.appwrite_console.loadbalancer.server.port=80" #ws - traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web - traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`) From a1dd9fe3ffe9fc6b6c9408d15bf35e5c4d4a9e90 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 22:47:33 +0200 Subject: [PATCH 24/42] tests: fix endpoint to use traefik --- phpunit.xml | 2 +- tests/e2e/General/HTTPTest.php | 6 +++--- tests/e2e/General/HooksTest.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 90ebd4225f..e772866051 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,7 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" > diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 92bc52561c..5c3b10a9ca 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -15,7 +15,7 @@ class HTTPTest extends Scope public function setUp(): void { parent::setUp(); - $this->client->setEndpoint('http://localhost'); + $this->client->setEndpoint('http://traefik'); } public function testOptions() @@ -163,11 +163,11 @@ class HTTPTest extends Scope public function testDefaultOAuth2() { - $response = $this->client->call(Client::METHOD_GET, '/auth/oauth2/success', $this->getHeaders()); + $response = $this->client->call(Client::METHOD_GET, '/console/auth/oauth2/success', $this->getHeaders()); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/auth/oauth2/failure', $this->getHeaders()); + $response = $this->client->call(Client::METHOD_GET, '/console/auth/oauth2/failure', $this->getHeaders()); $this->assertEquals(200, $response['headers']['status-code']); } diff --git a/tests/e2e/General/HooksTest.php b/tests/e2e/General/HooksTest.php index d67c3256d9..af6ccab0d5 100644 --- a/tests/e2e/General/HooksTest.php +++ b/tests/e2e/General/HooksTest.php @@ -17,7 +17,7 @@ class HooksTest extends Scope public function setUp(): void { parent::setUp(); - $this->client->setEndpoint('http://localhost'); + $this->client->setEndpoint('http://traefik'); } public function testProjectHooks() From 9e1b643c7bafbbf1739a8a28ad9ec5a7fdc85c7b Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 17 Jul 2024 22:47:33 +0200 Subject: [PATCH 25/42] tests: fix endpoint to use traefik --- tests/e2e/General/HTTPTest.php | 6 +++--- tests/e2e/General/HooksTest.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 92bc52561c..5c3b10a9ca 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -15,7 +15,7 @@ class HTTPTest extends Scope public function setUp(): void { parent::setUp(); - $this->client->setEndpoint('http://localhost'); + $this->client->setEndpoint('http://traefik'); } public function testOptions() @@ -163,11 +163,11 @@ class HTTPTest extends Scope public function testDefaultOAuth2() { - $response = $this->client->call(Client::METHOD_GET, '/auth/oauth2/success', $this->getHeaders()); + $response = $this->client->call(Client::METHOD_GET, '/console/auth/oauth2/success', $this->getHeaders()); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_GET, '/auth/oauth2/failure', $this->getHeaders()); + $response = $this->client->call(Client::METHOD_GET, '/console/auth/oauth2/failure', $this->getHeaders()); $this->assertEquals(200, $response['headers']['status-code']); } diff --git a/tests/e2e/General/HooksTest.php b/tests/e2e/General/HooksTest.php index d67c3256d9..af6ccab0d5 100644 --- a/tests/e2e/General/HooksTest.php +++ b/tests/e2e/General/HooksTest.php @@ -17,7 +17,7 @@ class HooksTest extends Scope public function setUp(): void { parent::setUp(); - $this->client->setEndpoint('http://localhost'); + $this->client->setEndpoint('http://traefik'); } public function testProjectHooks() From af998ef868da3a38ab8a662cdaa23dea4ad3b8d5 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 18 Jul 2024 17:29:15 +0200 Subject: [PATCH 26/42] chore: update console --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index a8de452b85..0481a9e2f0 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:appwrite/console:5.0.0-rc.5 + image: /console:appwrite/console:5.0.0-rc.6 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index fc8581c80a..ac4abd6f5a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,7 +195,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.0-rc.5 + image: appwrite/console:5.0.0-rc.6 restart: unless-stopped networks: - appwrite From 0661291d4c11ee45259c272880ee5ecdbe753f43 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 18 Jul 2024 20:59:55 +0200 Subject: [PATCH 27/42] chore: upgrade console --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 0481a9e2f0..d3aa90593a 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:appwrite/console:5.0.0-rc.6 + image: /console:appwrite/console:5.0.0-rc.7 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index ac4abd6f5a..553f44ee9f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,7 +195,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.0-rc.6 + image: appwrite/console:5.0.0-rc.7 restart: unless-stopped networks: - appwrite From 8ad15b2df19f48f405b10683c739bf6b03465df8 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 19 Jul 2024 13:53:42 +0200 Subject: [PATCH 28/42] feat: base migration for 1.6.x --- .env | 2 +- app/init.php | 2 +- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- src/Appwrite/Migration/Migration.php | 1 + src/Appwrite/Migration/Version/V21.php | 72 ++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/Appwrite/Migration/Version/V21.php diff --git a/.env b/.env index 9cccf5ee7e..4062bde932 100644 --- a/.env +++ b/.env @@ -7,7 +7,7 @@ _APP_CONSOLE_WHITELIST_EMAILS= _APP_CONSOLE_SESSION_ALERTS=enabled _APP_CONSOLE_WHITELIST_IPS= _APP_CONSOLE_COUNTRIES_DENYLIST=AQ -_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io +_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io,* _APP_SYSTEM_EMAIL_NAME=Appwrite _APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io _APP_EMAIL_SECURITY=security@appwrite.io diff --git a/app/init.php b/app/init.php index a0e71f041b..ef7742956f 100644 --- a/app/init.php +++ b/app/init.php @@ -118,7 +118,7 @@ const APP_USER_ACCESS = 24 * 60 * 60; // 24 hours const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4314; -const APP_VERSION_STABLE = '1.5.7'; +const APP_VERSION_STABLE = '1.6.0'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index d3aa90593a..70c6fbdebd 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -166,7 +166,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:appwrite/console:5.0.0-rc.7 + image: /console:appwrite/console:5.0.0-rc.11 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 553f44ee9f..d28586bf7b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -195,7 +195,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:5.0.0-rc.7 + image: appwrite/console:5.0.0-rc.11 restart: unless-stopped networks: - appwrite diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index e3a2021c1a..597943f842 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -86,6 +86,7 @@ abstract class Migration '1.5.5' => 'V20', '1.5.6' => 'V20', '1.5.7' => 'V20', + '1.6.0' => 'V21', ]; /** diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php new file mode 100644 index 0000000000..75d083d87d --- /dev/null +++ b/src/Appwrite/Migration/Version/V21.php @@ -0,0 +1,72 @@ + null, + fn () => [] + ); + } + + Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); + $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + + Console::info('Migrating Collections'); + $this->migrateCollections(); + } + + /** + * Migrate Collections. + * + * @return void + * @throws Exception|Throwable + */ + private function migrateCollections(): void + { + $internalProjectId = $this->project->getInternalId(); + $collectionType = match ($internalProjectId) { + 'console' => 'console', + default => 'projects', + }; + + $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { + $id = $collection['$id']; + + Console::log("Migrating Collection \"{$id}\""); + + $this->projectDB->setNamespace("_$internalProjectId"); + + switch ($id) { + case 'projects': + + // Create accessedAt attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'accessedAt'); + } catch (Throwable $th) { + Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); + } + + break; + } + } + } +} From 2d195fb74e894aef2cc85cf27e16efc7b44b9f45 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 19 Jul 2024 13:54:52 +0200 Subject: [PATCH 29/42] revert: wildcard hostname in .env --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 4062bde932..9cccf5ee7e 100644 --- a/.env +++ b/.env @@ -7,7 +7,7 @@ _APP_CONSOLE_WHITELIST_EMAILS= _APP_CONSOLE_SESSION_ALERTS=enabled _APP_CONSOLE_WHITELIST_IPS= _APP_CONSOLE_COUNTRIES_DENYLIST=AQ -_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io,* +_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io _APP_SYSTEM_EMAIL_NAME=Appwrite _APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io _APP_EMAIL_SECURITY=security@appwrite.io From 2065468708c7751d5a97f3e4fdea82495a5b86a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 21 Jul 2024 13:00:12 +0000 Subject: [PATCH 30/42] Make session not required in users JWT generation --- app/controllers/api/users.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 8b32349957..78988f525b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -2109,7 +2109,7 @@ App::post('/v1/users/:userId/jwts') ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) ->label('sdk.response.model', Response::MODEL_JWT) ->param('userId', '', new UID(), 'User ID.') - ->param('sessionId', 'recent', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true) + ->param('sessionId', '', new UID(), 'Session ID. Use the string \'recent\' to use the most recent session. Defaults to the most recent session.', true) ->param('duration', 900, new Range(0, 3600), 'Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.', true) ->inject('response') ->inject('dbForProject') @@ -2137,17 +2137,13 @@ App::post('/v1/users/:userId/jwts') } } - if ($session->isEmpty()) { - throw new Exception(Exception::USER_SESSION_NOT_FOUND); - } - $jwt = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $duration, 0); $response ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic(new Document(['jwt' => $jwt->encode([ 'userId' => $user->getId(), - 'sessionId' => $session->getId() + 'sessionId' => $session->isEmpty() ? '' : $session->getId() ])]), Response::MODEL_JWT); }); From d4a5891c0dc9853cc460d4547f502a287900f26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 21 Jul 2024 13:28:23 +0000 Subject: [PATCH 31/42] Fix user JWTs without sessionID --- app/init.php | 11 +++--- tests/e2e/Services/Users/UsersBase.php | 47 ++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/app/init.php b/app/init.php index ef7742956f..c6a0680a9d 100644 --- a/app/init.php +++ b/app/init.php @@ -1242,14 +1242,15 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons } $jwtUserId = $payload['userId'] ?? ''; - $jwtSessionId = $payload['sessionId'] ?? ''; - - if ($jwtUserId && $jwtSessionId) { + if (!empty($jwtUserId)) { $user = $dbForProject->getDocument('users', $jwtUserId); } - if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token - $user = new Document([]); + $jwtSessionId = $payload['sessionId'] ?? ''; + if(!empty($jwtSessionId)) { + if (empty($user->find('$id', $jwtSessionId, 'sessions'))) { // Match JWT to active token + $user = new Document([]); + } } } diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index c34227e4de..c06bc6f4a8 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -1589,6 +1589,27 @@ trait UsersBase ], false); $this->assertEquals($user['headers']['status-code'], 201); + // Create JWT 0, with no session available + $response = $this->client->call(Client::METHOD_POST, '/users/' . $userId . '/jwts', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['jwt']); + $jwt0 = $response['body']['jwt']; + + // Ensure JWT 0 works + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-jwt' => $jwt0, + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($userId, $response['body']['$id']); + // Create two sessions $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ 'origin' => 'http://localhost', @@ -1641,12 +1662,13 @@ trait UsersBase $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($userId, $response['body']['$id']); - // Create JWT 2 for latest session using default param + // Create JWT 2 for latest session using 'current' param $response = $this->client->call(Client::METHOD_POST, '/users/' . $userId . '/jwts', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'duration' => 5 + 'duration' => 5, + 'sessionId' => 'current' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -1696,6 +1718,27 @@ trait UsersBase $this->assertEquals(401, $response['headers']['status-code']); + // Ensure JWT 0 works still even with no sessions + + $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $userId . '/sessions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'sessionId' => $session2Id + ]); + + $this->assertEquals(204, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/account', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-jwt' => $jwt0, + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($userId, $response['body']['$id']); + // Cleanup after test $response = $this->client->call(Client::METHOD_DELETE, '/users/' . $userId, array_merge([ From 8e61b2149f1b5e538b210dbde947b644904627b4 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 22 Jul 2024 11:33:31 +0900 Subject: [PATCH 32/42] Auto update V3 Runtimes into V4 Runtimes on execution --- app/controllers/api/functions.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d2a1790d94..a810d7be5b 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1621,6 +1621,13 @@ App::post('/v1/functions/:functionId/executions') $version = $function->getAttribute('version', 'v2'); $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); + /** Auto-update v3 runtimes into v4, remove me after we do migrations */ + if ($version === 'v3') { + $function->setAttribute('version', 'v4'); + $function = $dbForProject->updateDocument('functions', $function->getId(), $function); + $version = 'v4'; + } + $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; if (\is_null($runtime)) { From 304910e303b90db4258624cb147ad8f207f00c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 22 Jul 2024 10:36:18 +0000 Subject: [PATCH 33/42] Add schedule date to response format --- app/config/collections.php | 33 +++++++++++++++++++ app/controllers/api/functions.php | 12 +++++-- src/Appwrite/Migration/Version/V16.php | 30 +++++++++++++++++ .../Utopia/Response/Model/Execution.php | 8 +++++ .../Functions/FunctionsCustomClientTest.php | 17 ++++++++++ 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index d0c3df165e..f6a357b3c5 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3848,6 +3848,39 @@ $projectCollections = array_merge([ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('scheduledAt'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('scheduleInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('scheduleId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], ], 'indexes' => [ [ diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d2a1790d94..00988840c9 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1744,9 +1744,8 @@ App::post('/v1/functions/:functionId/executions') ->setContext('function', $function); if ($async) { - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - if(is_null($scheduledAt)) { + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); $queueForFunctions ->setType('http') ->setExecution($execution) @@ -1770,7 +1769,7 @@ App::post('/v1/functions/:functionId/executions') 'jwt' => $jwt, ]; - $dbForConsole->createDocument('schedules', new Document([ + $schedule = $dbForConsole->createDocument('schedules', new Document([ 'region' => System::getEnv('_APP_REGION', 'default'), 'resourceType' => ScheduleExecutions::getSupportedResource(), 'resourceId' => $execution->getId(), @@ -1781,6 +1780,13 @@ App::post('/v1/functions/:functionId/executions') 'data' => $data, 'active' => true, ])); + + $execution = $execution + ->setAttribute('scheduleId', $schedule->getId()) + ->setAttribute('scheduleInternalId', $schedule->getInternalId()) + ->setAttribute('scheduledAt', $scheduledAt); + + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } return $response diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 49f244598e..636a301717 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -48,6 +48,36 @@ class V16 extends Migration $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { + case 'executions': + try { + /** + * Create 'scheduledAt' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); + } catch (\Throwable $th) { + Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleInternalId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); + } catch (\Throwable $th) { + Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); + } catch (\Throwable $th) { + Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); + } + + break; + case 'sessions': try { /** diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index fbd9619a40..90fbdc9689 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Database\DateTime; use Utopia\Database\Helpers\Role; class Execution extends Model @@ -110,6 +111,13 @@ class Execution extends Model 'default' => 0, 'example' => 0.400, ]) + ->addRule('scheduledAt', [ + 'type' => self::TYPE_DATETIME, + 'description' => 'The scheduled time for execution. If left empty, execution will be queued immediately.', + 'required' => false, + 'default' => DateTime::now(), + 'example' => self::TYPE_DATETIME_EXAMPLE, + ]) ; } diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index bf969d388a..39f97cba65 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -269,6 +269,7 @@ class FunctionsCustomClientTest extends Scope // Schedule execution for the future \date_default_timezone_set('UTC'); $futureTime = (new \DateTime())->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); + $futureTimeIso = (new \DateTime($futureTime))->format('Y-m-d\TH:i:s.vP'); $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([ 'content-type' => 'application/json', @@ -286,9 +287,24 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(202, $execution['headers']['status-code']); $this->assertEquals('scheduled', $execution['body']['status']); + $this->assertEquals($futureTimeIso, $execution['body']['scheduledAt']); $executionId = $execution['body']['$id']; + // List executions and ensure it has schedule date + $response = $this->client->call(Client::METHOD_GET, '/functions/' . $function['body']['$id'] . '/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]); + + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertGreaterThan(0, \count($response['body']['executions'])); + $recentExecution = $response['body']['executions'][0]; + $this->assertEquals($executionId, $recentExecution['$id']); + $this->assertEquals($futureTimeIso, $recentExecution['scheduledAt']); + sleep(20); $execution = $this->client->call(Client::METHOD_GET, '/functions/' . $function['body']['$id'] . '/executions/' . $executionId, [ @@ -303,6 +319,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals('/custom', $execution['body']['requestPath']); $this->assertEquals('GET', $execution['body']['requestMethod']); $this->assertGreaterThan(0, $execution['body']['duration']); + $this->assertEquals($futureTimeIso, $execution['body']['scheduledAt']); /* Test for FAILURE */ From 9e3c5b9368745e4a06b80d3822612adf68545139 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 22 Jul 2024 19:40:05 +0900 Subject: [PATCH 34/42] Add variable runtimes sizes migrations --- src/Appwrite/Migration/Version/V21.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 01fc2d19e0..be6c38be67 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -87,6 +87,13 @@ class V21 extends Migration Console::warning("'scopes' from {$id}: {$th->getMessage()}"); } + // Create size attribute + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'size'); + } catch (Throwable $th) { + Console::warning("'size' from {$id}: {$th->getMessage()}"); + } + break; case 'executions': // Create requestMethod index @@ -133,7 +140,14 @@ class V21 extends Migration // Add accessedAt attribute $document->setAttribute('accessedAt', DateTime::now()); break; + case 'functions': + // Add scopes attribute + $document->setAttribute('scopes', []); + + // Add size attribute + $document->setAttribute('size', 's-1vcpu-512m'); } + return $document; } } From 4f558d35be000646725c70f9b3bdda0f70f0829f Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 22 Jul 2024 19:42:29 +0900 Subject: [PATCH 35/42] Improvement v3 -> v4 transition --- app/controllers/api/functions.php | 7 ------- src/Executor/Executor.php | 13 +++++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index a810d7be5b..d2a1790d94 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1621,13 +1621,6 @@ App::post('/v1/functions/:functionId/executions') $version = $function->getAttribute('version', 'v2'); $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); - /** Auto-update v3 runtimes into v4, remove me after we do migrations */ - if ($version === 'v3') { - $function->setAttribute('version', 'v4'); - $function = $dbForProject->updateDocument('functions', $function->getId(), $function); - $version = 'v4'; - } - $runtime = (isset($runtimes[$function->getAttribute('runtime', '')])) ? $runtimes[$function->getAttribute('runtime', '')] : null; if (\is_null($runtime)) { diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 29ed756932..3206381e95 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -75,6 +75,12 @@ class Executor $runtimeId = "$projectId-$deploymentId-build"; $route = "/runtimes"; $timeout = (int) System::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900); + + // Remove after migration + if ($version == 'v3') { + $version = 'v4'; + } + $params = [ 'runtimeId' => $runtimeId, 'source' => $source, @@ -188,6 +194,13 @@ class Executor $runtimeId = "$projectId-$deploymentId"; $route = '/runtimes/' . $runtimeId . '/execution'; + + + // Remove after migration + if ($version == 'v3') { + $version = 'v4'; + } + $params = [ 'runtimeId' => $runtimeId, 'variables' => $variables, From 4b585466e1a43930d2efe097c3f7de0e236ce561 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 22 Jul 2024 20:03:45 +0900 Subject: [PATCH 36/42] Update api.php --- app/controllers/shared/api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 583a0160a1..672366fa01 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -206,6 +206,7 @@ App::init() throw new Exception(Exception::USER_API_KEY_AND_SESSION_SET); } + // Remove after migration if(!\str_contains($apiKey, '_')) { $keyType = API_KEY_STANDARD; $authKey = $apiKey; From cb3c7505fe2157fde54375a713a74eace67dc00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 23 Jul 2024 14:28:13 +0200 Subject: [PATCH 37/42] Fix Router dynamic keys --- app/controllers/general.php | 14 ++++++++++++++ src/Appwrite/Platform/Workers/Functions.php | 3 +++ 2 files changed, 17 insertions(+) diff --git a/app/controllers/general.php b/app/controllers/general.php index 92ddec58f5..469a3a2f6b 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -2,6 +2,7 @@ require_once __DIR__ . '/../init.php'; +use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Event\Certificate; use Appwrite\Event\Event; @@ -163,7 +164,15 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo throw new AppwriteException(AppwriteException::USER_UNAUTHORIZED, 'To execute function using domain, execute permissions must include "any" or "guests"'); } + $jwtExpiry = $function->getAttribute('timeout', 900); + $jwtObj = new JWT(System::getEnv('_APP_OPENSSL_KEY_V1'), 'HS256', $jwtExpiry, 0); + $apiKey = $jwtObj->encode([ + 'projectId' => $project->getId(), + 'scopes' => $function->getAttribute('scopes', []) + ]); + $headers = \array_merge([], $requestHeaders); + $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; $headers['x-appwrite-trigger'] = 'http'; $headers['x-appwrite-user-id'] = ''; $headers['x-appwrite-user-jwt'] = ''; @@ -242,8 +251,13 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo $vars[$var->getAttribute('key')] = $var->getAttribute('value', ''); } + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; + $hostname = System::getEnv('_APP_DOMAIN'); + $endpoint = $protocol . '://' . $hostname . "/v1"; + // Appwrite vars $vars = \array_merge($vars, [ + 'APPWRITE_FUNCTION_API_ENDPOINT' => $endpoint, 'APPWRITE_FUNCTION_ID' => $functionId, 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name'), 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index b071a79bfd..0be652e12d 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -358,6 +358,9 @@ class Functions extends Action $headers['x-appwrite-event'] = $event ?? ''; $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'; /** Create execution or update execution status */ $execution = $dbForProject->getDocument('executions', $executionId ?? ''); From 51c163a42f6fe556425e8b18075635f2892c4b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Jul 2024 06:55:36 +0000 Subject: [PATCH 38/42] Apply migrations properly --- src/Appwrite/Migration/Version/V16.php | 30 ------------------- src/Appwrite/Migration/Version/V21.php | 29 ++++++++++++++++++ src/Appwrite/Utopia/Response/Filters/V18.php | 7 +++++ .../unit/Utopia/Response/Filters/V18Test.php | 26 ++++++++++++++++ 4 files changed, 62 insertions(+), 30 deletions(-) diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 636a301717..49f244598e 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -48,36 +48,6 @@ class V16 extends Migration $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { - case 'executions': - try { - /** - * Create 'scheduledAt' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); - } catch (\Throwable $th) { - Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); - } - - try { - /** - * Create 'scheduleInternalId' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); - } catch (\Throwable $th) { - Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); - } - - try { - /** - * Create 'scheduleId' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); - } catch (\Throwable $th) { - Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); - } - - break; - case 'sessions': try { /** diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index be6c38be67..1eda618c52 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -69,6 +69,35 @@ class V21 extends Migration Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); } break; + case 'executions': + try { + /** + * Create 'scheduledAt' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); + } catch (\Throwable $th) { + Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleInternalId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); + } catch (\Throwable $th) { + Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); + } catch (\Throwable $th) { + Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); + } + + break; case 'schedules': // Create data attribute try { diff --git a/src/Appwrite/Utopia/Response/Filters/V18.php b/src/Appwrite/Utopia/Response/Filters/V18.php index b32856bdb4..d0aa680e3b 100644 --- a/src/Appwrite/Utopia/Response/Filters/V18.php +++ b/src/Appwrite/Utopia/Response/Filters/V18.php @@ -14,6 +14,7 @@ class V18 extends Filter $parsedResponse = match($model) { Response::MODEL_FUNCTION => $this->parseFunction($content), + Response::MODEL_EXECUTION => $this->parseExecution($content), Response::MODEL_PROJECT => $this->parseProject($content), default => $parsedResponse, }; @@ -21,6 +22,12 @@ class V18 extends Filter return $parsedResponse; } + protected function parseExecution(array $content) + { + unset($content['scheduledAt']); + return $content; + } + protected function parseFunction(array $content) { unset($content['scopes']); diff --git a/tests/unit/Utopia/Response/Filters/V18Test.php b/tests/unit/Utopia/Response/Filters/V18Test.php index 36719a7620..c4011c08a1 100644 --- a/tests/unit/Utopia/Response/Filters/V18Test.php +++ b/tests/unit/Utopia/Response/Filters/V18Test.php @@ -50,6 +50,32 @@ class V18Test extends TestCase $this->assertEquals($expected, $result); } + + public function executionProvider(): array + { + return [ + 'remove scheduledAt' => [ + [ + 'scheduledAt' => '2024-07-13T09:00:00.000Z', + ], + [ + ] + ] + ]; + } + + /** + * @dataProvider executionProvider + */ + public function testExecution(array $content, array $expected): void + { + $model = Response::MODEL_EXECUTION; + + $result = $this->filter->parse($content, $model); + + $this->assertEquals($expected, $result); + } + public function projectProvider(): array { return [ From ab55e6f5117407bbf7e1e635d1f041bba33cf155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Jul 2024 07:00:20 +0000 Subject: [PATCH 39/42] Linter fix --- src/Appwrite/Migration/Version/V21.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 1eda618c52..a75ba58949 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -97,7 +97,7 @@ class V21 extends Migration Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); } - break; + break; case 'schedules': // Create data attribute try { From c42a2bc5b7e99ecda80ee02ad3cb17bb64105af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 24 Jul 2024 07:11:48 +0000 Subject: [PATCH 40/42] PR review changes --- src/Appwrite/Migration/Version/V21.php | 56 +++++++++++++------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index a75ba58949..7dd2912234 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -68,35 +68,6 @@ class V21 extends Migration } catch (Throwable $th) { Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); } - break; - case 'executions': - try { - /** - * Create 'scheduledAt' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); - } catch (\Throwable $th) { - Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); - } - - try { - /** - * Create 'scheduleInternalId' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); - } catch (\Throwable $th) { - Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); - } - - try { - /** - * Create 'scheduleId' attribute - */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); - } catch (\Throwable $th) { - Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); - } - break; case 'schedules': // Create data attribute @@ -145,6 +116,33 @@ class V21 extends Migration } catch (\Throwable $th) { Console::warning("'_key_deployment' from {$id}: {$th->getMessage()}"); } + + try { + /** + * Create 'scheduledAt' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); + } catch (\Throwable $th) { + Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleInternalId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); + } catch (\Throwable $th) { + Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); + } + + try { + /** + * Create 'scheduleId' attribute + */ + $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); + } catch (\Throwable $th) { + Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); + } } usleep(50000); From d2b2d1a1354887ba67f1ff5acbb87135684f47d9 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 24 Jul 2024 16:33:37 +0545 Subject: [PATCH 41/42] fix file size calculations --- app/controllers/api/storage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 652644d44b..b080066653 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -63,7 +63,7 @@ App::post('/v1/storage/buckets') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) - ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) + ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) @@ -240,7 +240,7 @@ App::put('/v1/storage/buckets/:bucketId') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('fileSecurity', false, new Boolean(true), 'Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->param('enabled', true, new Boolean(true), 'Is bucket enabled? When set to \'disabled\', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.', true) - ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1024 * 1024), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) + ->param('maximumFileSize', fn (array $plan) => empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000, fn (array $plan) => new Range(1, empty($plan['fileSize']) ? (int) System::getEnv('_APP_STORAGE_LIMIT', 0) : $plan['fileSize'] * 1000 * 1000), 'Maximum file size allowed in bytes. Maximum allowed value is ' . Storage::human(System::getEnv('_APP_STORAGE_LIMIT', 0), 0) . '.', true, ['plan']) ->param('allowedFileExtensions', [], new ArrayList(new Text(64), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Allowed file extensions. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' extensions are allowed, each 64 characters long.', true) ->param('compression', Compression::NONE, new WhiteList([Compression::NONE, Compression::GZIP, Compression::ZSTD]), 'Compression algorithm choosen for compression. Can be one of ' . Compression::NONE . ', [' . Compression::GZIP . '](https://en.wikipedia.org/wiki/Gzip), or [' . Compression::ZSTD . '](https://en.wikipedia.org/wiki/Zstd), For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' compression is skipped even if it\'s enabled', true) ->param('encryption', true, new Boolean(true), 'Is encryption enabled? For file size above ' . Storage::human(APP_STORAGE_READ_BUFFER, 0) . ' encryption is skipped even if it\'s enabled', true) From 5c65fa895d0fe788260b8261495795f7f5d3f54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 25 Jul 2024 06:54:50 +0000 Subject: [PATCH 42/42] PR review changes --- tests/e2e/Services/Functions/FunctionsCustomClientTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index a44420b544..4e501692fa 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -8,6 +8,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; +use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; @@ -269,7 +270,7 @@ class FunctionsCustomClientTest extends Scope // Schedule execution for the future \date_default_timezone_set('UTC'); $futureTime = (new \DateTime())->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); - $futureTimeIso = (new \DateTime($futureTime))->format('Y-m-d\TH:i:s.vP'); + $futureTimeIso = DateTime::formatTz($futureTime); $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $function['body']['$id'] . '/executions', array_merge([ 'content-type' => 'application/json', @@ -298,7 +299,6 @@ class FunctionsCustomClientTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'], ]); - $this->assertEquals(200, $response['headers']['status-code']); $this->assertGreaterThan(0, \count($response['body']['executions'])); $recentExecution = $response['body']['executions'][0];